Intereting Posts
выполнение if / else if / else с fork () Вычислить произведение двойного слова (подписанное) из двух слов, учитывая нижнее словосочетание Последняя строка повторяется при выполнении fgets / fputs sched_setscheduler для всех streamов или основного streamа? dreferencing 2 d array segmentation fault в C во время scanf преобразование в ‘size_t’ из ‘int’ может изменить знак результата – GCC, C Как проверить, открыт ли удаленный порт UDP? C Получение ошибки сегментации strcpy Любая реализация однопользовательской блокировки свободной очереди в C? как использовать verilog PLI для связи с c с помощью компилятора ncverilog Могу ли я безопасно использовать CGFloat для хранения значений Float64 или Float32? Когда следует использовать perror (“…”) и fprintf (stderr, “…”)? Какая встроенная firebase database, способная на 100 миллионов записей, имеет эффективный C или C ++ API ISO C ++ запрещает массив переменных размеров (ошибка компиляции)

Эффективный способ выполнения 64-битного вращения с использованием 32-битных значений

Мне нужно повернуть 64-битное значение, используя 2 32-битных регистра. Кто-нибудь может найти эффективный способ сделать это?

Ну, нормальный поворот может быть реализован следующим образом:

unsigned int rotate(unsigned int bits, unsigned int n) { return bits << n | (bits >> (32 - n)); } 

Итак, вот догадка о 64-битной реализации с 32-битными vars:

 void bit_rotate_left_64(unsigned int hi, unsigned int lo, unsigned int n, unsigned int *out_hi, unsigned int *out_lo) { unsigned int hi_shift, hi_rotated; unsigned int lo_shift, lo_rotated; hi_shift = hi << n; hi_rotated = hi >> (32 - n); lo_shift = lo << n; lo_rotated = lo >> (32 - n); *out_hi = hi_shift | lo_rotated; *out_lo = lo_shift | hi_rotated; } 

В основном, я просто беру вращающиеся биты с высоким словом и OR-им с низким словом, и наоборот.

Вот быстрый тест:

 int main(int argc, char *argv[]) { /* watch the one move left */ hi = 0; lo = 1; for (i = 0; i < 129; i++) { bit_rotate_left_64(hi, lo, 1, &hi, &lo); printf("Result: %.8x %.8x\n", hi, lo); } /* same as above, but the 0 moves left */ hi = -1U; lo = 0xFFFFFFFF ^ 1; for (i = 0; i < 129; i++) { bit_rotate_left_64(hi, lo, 1, &hi, &lo); printf("Result: %.8x %.8x\n", hi, lo); } } 

Вот альтернативная реализация, которая меняет значения при n> = 32. Она также обрабатывает случай, когда n = 0 или n = 32, что приводит к hi >> (32 - n) больше, чем ширина типа, что приводит к неопределенному поведению ,

 void rot64 (uint32_t hi, uint32_t lo, uint32_t n, uint32_t *hi_out, uint32_t *lo_out) { /* Rotations go modulo 64 */ n &= 0x3f; /* Swap values if 32 <= n < 64 */ if (n & 0x20) { lo ^= hi; hi ^= lo; lo ^= hi; } /* Shift 0-31 steps */ uint8_t shift = n & 0x1f; if (!shift) { *hi_out = hi; *lo_out = lo; return; } *hi_out = (hi << shift) | (lo >> (32 - shift)); *lo_out = (lo << shift) | (hi >> (32 - shift)); }