Bit manipulation 什么样的转换可以解决这种旋转模式?

Bit manipulation 什么样的转换可以解决这种旋转模式?,bit-manipulation,Bit Manipulation,我有一系列的半字节(0x0-0xF)和一个结果转换,其结果是一个清晰的模式。转换解决方案根本没有出现在我的脑海中(不是因为缺乏尝试)。有没有一个有经验的小玩弄者能够识别这种转变?提前谢谢 0 -> 0 1 -> 1 2 -> 1 3 -> 0 ---------- 4 -> 2 5 -> 3 6 -> 3 7 -> 2 ---------- 8 -> 7 9 -> 6 A -> 6 B -> 7 ---------- C -

我有一系列的半字节(0x0-0xF)和一个结果转换,其结果是一个清晰的模式。转换解决方案根本没有出现在我的脑海中(不是因为缺乏尝试)。有没有一个有经验的小玩弄者能够识别这种转变?提前谢谢

0 -> 0
1 -> 1
2 -> 1
3 -> 0
----------
4 -> 2
5 -> 3
6 -> 3
7 -> 2
----------
8 -> 7
9 -> 6
A -> 6
B -> 7
----------
C -> 5
D -> 4
E -> 4
F -> 5

从单个位来看,输入和输出之间的一种可能关系是:

Y0 = X0^X1^X3
Y1 = X2^X3
Y2 = X3
Y3 = 0
其中X0..X3为输入位,Y0..Y3为输出位

然而,这需要大约10个或更多的位操作来实现,所以您最好只使用一个查找表

下面是一个C语言的测试程序,用于验证按位逻辑是否正确:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

static int convert_bitwise(int x)
{
    int x0 = x & 1;
    int x1 = (x & 2) >> 1;
    int x2 = (x & 4) >> 2;
    int x3 = x >> 3;
    int y0 = x0 ^ x1 ^ x3;
    int y1 = x2 ^ x3;
    int y2 = x3;
    return (y2 << 2) | (y1 << 1) | y0;
}

static int convert_lut(int x)
{
    const int LUT[16] = { 0, 1, 1, 0,
                          2, 3, 3, 2,
                          7, 6, 6, 7,
                          5, 4, 4, 5 };
    return LUT[x & 0x0f];
}

int main(int argc, char *argv[])
{
    int x;

    for (x = 0; x < 16; ++x)
    {
        int y_bitwise = convert_bitwise(x);
        int y_lut = convert_lut(x);

        printf("x = %2d, y (bitwise) = %d, y (LUT) = %d, (%s)\n", x, y_bitwise, y_lut, y_bitwise == y_lut ? "PASS" : "FAIL");
    }
    return 0;
}

保罗,看着你的答案和命名法,我都快抓狂了。以
Y0
(对于mibble 0x00)为例,您是说,为了您的示例的目的,
0^1^11
?那么对于
Y0
(对于半字节0x01)将是
1^10^100
?我想我不明白你在叫什么
X0
X1
X3
。谢谢。@DavidC.Rankin他们只是X的一部分。同样,易建联是结果的一部分。谢谢,我想我只是糊涂了。我将零头序列
0x0
-
0xf
设置为
0000
0001
0010
<代码>1110,
1111
。谢谢你的澄清,我会继续在had里寻找兔子:)@Paul R:啊,好电话!这个模式在下半部的构图上确实发生了一些变化,我在一路上的某个地方看不见了。这里有一种方法只需再做一次操作(这次我测试了它):
((n*0xA0000000)>>31)^(n>>2)^(n>>1)
它应该在超标量上折叠得很好。它假定半字节位于32位无符号整数中,该整数将从右侧滚动并以零移位。乘法将Y0和Y2的XOR放在高位,将其放在高位可以避免由于需要移位而必须将更多位归零(屏蔽)。@Paul R:我喜欢在某些情况下将mul视为按位快捷方式,特别是因为它是一条非常快的指令,至少在x86/64上是如此。然而,我想按位方式执行的操作数实际上是相同的(我没有计算MOV)<代码>无符号t=n>>2;返回((n^t)&1)^t^(n>>1)这样就只需要计时,看看哪个更快(可能是查找表)。可能还值得注意的是,这个问题非常适合于
pshufb
,它可以用于在16字节的表上同时执行16个项目的查找,即使您只使用一个结果。看起来几乎像灰色代码。
$ gcc -Wall bits4.c && ./a.out 
x =  0, y (bitwise) = 0, y (LUT) = 0, (PASS)
x =  1, y (bitwise) = 1, y (LUT) = 1, (PASS)
x =  2, y (bitwise) = 1, y (LUT) = 1, (PASS)
x =  3, y (bitwise) = 0, y (LUT) = 0, (PASS)
x =  4, y (bitwise) = 2, y (LUT) = 2, (PASS)
x =  5, y (bitwise) = 3, y (LUT) = 3, (PASS)
x =  6, y (bitwise) = 3, y (LUT) = 3, (PASS)
x =  7, y (bitwise) = 2, y (LUT) = 2, (PASS)
x =  8, y (bitwise) = 7, y (LUT) = 7, (PASS)
x =  9, y (bitwise) = 6, y (LUT) = 6, (PASS)
x = 10, y (bitwise) = 6, y (LUT) = 6, (PASS)
x = 11, y (bitwise) = 7, y (LUT) = 7, (PASS)
x = 12, y (bitwise) = 5, y (LUT) = 5, (PASS)
x = 13, y (bitwise) = 4, y (LUT) = 4, (PASS)
x = 14, y (bitwise) = 4, y (LUT) = 4, (PASS)
x = 15, y (bitwise) = 5, y (LUT) = 5, (PASS)
$