128位数字的按位移位操作

假设我有一个由4个32位整数组成的数组,用于存储128位数

如何在这个128位数字上执行左右移位?

谢谢!

 void shiftl128 ( unsigned int& a, unsigned int& b, unsigned int& c, unsigned int& d, size_t k) { assert (k <= 128); if (k >= 32) // shifting a 32-bit integer by more than 31 bits is "undefined" { a=b; b=c; c=d; d=0; shiftl128(a,b,c,d,k-32); } else { a = (a << k) | (b >> (32-k)); b = (b << k) | (c >> (32-k)); c = (c << k) | (d >> (32-k)); d = (d << k); } } void shiftr128 ( unsigned int& a, unsigned int& b, unsigned int& c, unsigned int& d, size_t k) { assert (k <= 128); if (k >= 32) // shifting a 32-bit integer by more than 31 bits is "undefined" { d=c; c=b; b=a; a=0; shiftr128(a,b,c,d,k-32); } else { d = (c << (32-k)) | (d >> k); \ c = (b << (32-k)) | (c >> k); \ b = (a << (32-k)) | (b >> k); \ a = (a >> k); } } 

使用uint128 ? 如果可以,请使用专为此设计的x86 SSE指令。 (然后,当你提升你的价值时,你已准备好做其他128位操作……)

SSE2位移动平均需要约4条指令,一个分支(一个case语句)。 移位超过32位也没有问题。 执行此操作的完整代码是,使用gcc内在函数而不是原始汇编程序,在sseutil.c ( github:“SSE2的exception使用” ) – 并且它比在此处粘贴sseutil.c意义。

许多人使用SSE2的障碍是移位操作会立即(恒定)移位计数。 你可以用一点C预处理器来解决这个问题( wordpress:C预处理器技巧 )。 之后,你有op序列,如:

 LeftShift(uint128 x, int n) = _mm_slli_epi64(_mm_slli_si128(x, n/8), n%8) 

对于n = 65..71,73..79,… 121..127 ……在两个指令中完成整个class次。

而不是使用128位数,为什么不使用bitset? 使用bitset,您可以调整您想要的大小。 另外,您可以对其执行相当多的操作。

您可以在此处找到有关这些的更多信息:

http://www.cppreference.com/wiki/utility/bitset/start?do=backlink

首先,如果你移位n位且n大于或等于32,则除以32并移动整数。 这应该是微不足道的。 现在你剩下的移位数从0到31.如果它为零,早点返回,你就完成了。

对于每个整数,您需要移动剩余的n ,然后将相邻的整数移位相同的量并组合每个的有效位。

由于您提到您将128位值存储在4个整数的数组中,因此您可以执行以下操作:

 void left_shift(unsigned int* array) { for (int i=3; i >= 0; i--) { array[i] = array[i] << 1; if (i > 0) { unsigned int top_bit = (array[i-1] >> 31) & 0x1; array[i] = array[i] | top_bit; } } } void right_shift(unsigned int* array) { for (int i=0; i < 4; i++) { array[i] = array[i] >> 1; if (i < 3) { unsigned int bottom_bit = (array[i+1] & 0x1) << 31; array[i] = array[i] | bottom_bit; } } }