128位数字的按位移位操作

时间:2011-05-13 18:48:46

标签: c++ c bit-manipulation bitwise-operators bit-shift

假设我有一个包含4个32位整数的数组,用于存储128位数字

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

谢谢!

5 个答案:

答案 0 :(得分:4)

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

SSE2位移动平均需要约4条指令,带有一个分支(case语句)。移位超过32位也没有问题。执行此操作的完整代码是,使用gcc内在函数而不是原始汇编程序,位于sseutil.cgithub: "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;
        }
    }
}