Кстати, это не проблема порядка байтов;вы не делаете байтовый доступ к объектному представлению.Вы работаете с ним как с 256-битным целым числом и просто запрашиваете младшие 8 бит за раз с data & 0xFF
.
Если вы знали, что порядковый номер целевой реализации C и порядок данных известныобъекта boost
, вы можете эффективно зациклить его в нисходящем порядке адресов с помощью unsigned char*
.
Вы вводите идею порядка байтов только потому, что он связан с обращением байтов, что вам и нужнопытаюсь сделать. Но это действительно неэффективно, просто переберите байты вашего bigint другим способом.
Я не решаюсь рекомендовать конкретное решение, потому что я не знаю, что скомпилируетсяэффективно.Но вы могли бы захотеть что-то вроде этого вместо того, чтобы переворачивать байты раньше времени :
for (outer loop) {
uint64_t chunk = data >> (64*3); // grab the highest 64-bit chunk
data <<= 64; // and shift everything up
// alternative: maybe keep a shift-count in a variable instead of modifying `data`
// Then pick apart the chunk into its component bytes, in MSB first order
for (int = 0 ; i<8 ; i++) {
unsigned tmp = (chunk >> 56) & 0xFF;
// do something with it
chunk <<= 8; // bring the next byte to the top
}
}
Во внутреннем цикле более эффективно, чем использование двух смен, можно использовать вращение , чтобы привести старший байт к низу (для & 0xFF
) одновременно со смещением младших байтов вверх. Лучшие практики для операций кругового сдвига (поворота) в C ++
Во внешнем цикле IDK, если boost::multiprecision::number
, имеет какие-либо API для эффективной индексации встроенных блоков;если это так, то это, вероятно, более эффективно.
Я использовал вложенные циклы, потому что я предполагаю, что data <<= 8
не компилируется особенно эффективно, и ни один не будет (data >> (256-8)) & 0xFF
.Но именно так вы можете брать байты сверху, а не снизу.
Другой вариант - стандартный прием для преобразования чисел в строки: сохранение символов в буфере по убываниюзаказ .256-битное (32-байтовое) число займет 64 шестнадцатеричных числа, и вам нужно еще 32 байта между ними.
Например:
// 97 = 32 * 2 + 32, plus 1 byte for an implicit-length C string terminator
// plus another 1 for an extra space
char buf[98]; // small enough to use automatic storage
char *outp = buf+96; // pointer to the end
*outp = 0; // terminator
const char *hex_lut = "0123456789abcdef";
for (int i=0 ; i<32 ; i++) {
uint8_t byte = data & 0xFF;
*--outp = hex_lut[byte >> 4];
*--outp = hex_lut[byte & 0xF];
*--outp = ' ';
data >>= 8;
}
// outp points at an extra ' '
outp++;
// outp points at the first byte of a string like "12 ab cd"
stream << outp;
Если вы хотите разбитьчто можно разбить на куски, чтобы вставить разрыв строки, вы тоже можете это сделать.
Если вас интересует эффективное преобразование в гекс для 8, 16 или 32 байтовданных сразу, см. Как преобразовать число в шестнадцатеричное? для некоторых x86 SIMD-способов .Asm должен легко портировать на встроенные функции C ++.(Вы можете использовать SIMD-тасования для обработки размещения байтов в MSB-первом порядке печати после загрузки из целых чисел с прямым порядком байтов.)
Вы также можете использовать SIMD-тасование, чтобы разделить пробелы между парами шестнадцатеричных цифр перед сохранением впамять, как вы, очевидно, хотите здесь.
Ошибка в коде, который вы добавили:
Поэтому я добавил этот код перед циклом выше:
for(unsigned int i=0,data,_data;i<33;++i)
unsigned i, data, _data
объявляет новые переменные типа unsigned int
, которые затеняют предыдущие объявления data
и _data
.Этот цикл имеет нулевой эффект для data
или _data
вне области действия цикла.(И содержит UB, потому что вы читаете _data
и data
без их инициализации.)
Если эти переменные на самом деле все еще являются u256
переменными внешней области видимости, я не вижу очевидной проблемыкроме эффективности, но, возможно, я тоже упускаю очевидное.Я выглядел не очень усердно, потому что использование 64x 256-битных сдвигов и 32x OR кажется ужасной идеей.Это возможно , которое может полностью оптимизироваться, или bswap
инструкций обратного байта на ISA, которые их имеют, но я сомневаюсь в этом.Особенно из-за дополнительного усложнения функций оболочки boost::multiprecision::number
.