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