假设我有一个包含4个32位整数的数组,用于存储128位数字
如何在这个128位数字上执行左右移位?
谢谢!
答案 0 :(得分:4)
使用uint128
?如果可以,请使用专为此设计的x86 SSE指令。 (然后,当你提升了你的价值时,你已准备好做其他的128位操作......)
SSE2位移动平均需要约4条指令,带有一个分支(case语句)。移位超过32位也没有问题。执行此操作的完整代码是,使用gcc内在函数而不是原始汇编程序,位于sseutil.c
(github: "Unusual uses of SSE2") - 并且它比在此处粘贴更有意义。
许多人使用SSE2的障碍是移位操作会立即(恒定)移位计数。你可以用一点C预处理器来解决这个问题(wordpress: C preprocessor tricks)。之后,您将拥有如下操作序列:
LeftShift(uint128 x, int n) = _mm_slli_epi64(_mm_slli_si128(x, n/8), n%8)
对于n = 65..71,73..79,... 121..127 ......用两条指令完成整个班次。
答案 1 :(得分:3)
为什么不使用bitset,而不是使用128位数?使用bitset,您可以调整您想要的大小。另外,您可以对其执行相当多的操作。
您可以在此处找到有关这些内容的更多信息:
http://www.cppreference.com/wiki/utility/bitset/start?do=backlink
答案 2 :(得分:3)
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);
}
}
答案 3 :(得分:1)
首先,如果您移位n
位且n
大于或等于32,则除以32并移位整数。这应该是微不足道的。现在你剩下的移位数从0到31.如果它为零,早点返回,你就完成了。
对于每个整数,您需要移动剩余的n
,然后将相邻的整数移位相同的数量并合并每个整数的有效位。
答案 4 :(得分:0)
由于您提到将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;
}
}
}