C 用N个不可靠位计算无符号整数可能值的最快方法?

C 用N个不可靠位计算无符号整数可能值的最快方法?,c,performance,binary,unsigned-integer,C,Performance,Binary,Unsigned Integer,给定一个无符号int A(32位)和另一个无符号int B,其中B的二进制形式表示A的10个“最不可靠”位,那么扩展A的所有1024个潜在值的最快方法是什么?我想用C来做这个 例如,uint B保证始终具有二进制形式的10个1和22个0(10个最不可靠位) 比如说 A = 2323409845 B = 1145324694 它们的二进制表示形式是: a=10001010011111000110101110110101 b=01000100010001000100010010010110

给定一个无符号int A(32位)和另一个无符号int B,其中B的二进制形式表示A的10个“最不可靠”位,那么扩展A的所有1024个潜在值的最快方法是什么?我想用C来做这个

例如,uint B保证始终具有二进制形式的10个1和22个0(10个最不可靠位)

比如说

A = 2323409845  
B = 1145324694
它们的二进制表示形式是:

a=10001010011111000110101110110101

b=01000100010001000100010010010110
B表示A的10个最不可靠位。因此,B中设置为1的每个位表示A中的一个不可靠位


我想计算通过在A中切换这10位中的任何一位而创建的所有1024个可能值。

不能保证这是可证明的“最快的”,但这就是我要做的。首先,筛选出固定钻头:

uint32_t const reliable_mask = ~B;
uint32_t const reliable_value = A & reliable_mask;
现在,我将预处理1024个不可靠位的可能值的数组:

uint32_t const unreliables[1024] = /* ... */
最后,我想把所有这些放在一起:

for (size_t i = 0; i != 1024; ++i)
{
   uint32_t const val = reliable_value | unreliables[i];
}

要获得不可靠的位,您只需在
[0,1024)
上循环(甚至可能在现有循环中),然后将位“分散”到所需的位置。

不能保证这是可证明的“最快的”,但这就是我要做的。首先,筛选出固定位:

uint32_t const reliable_mask = ~B;
uint32_t const reliable_value = A & reliable_mask;
现在,我将预处理1024个不可靠位的可能值的数组:

uint32_t const unreliables[1024] = /* ... */
最后,我想把所有这些放在一起:

for (size_t i = 0; i != 1024; ++i)
{
   uint32_t const val = reliable_value | unreliables[i];
}

要获得不可靠的位,您可以只循环
[0,1024)
(甚至可能在现有循环中)并将位“分散”到必要的位置。

这基本上遵循了Kerrek使用的技术,但充实了困难的部分:

int* getValues(int value, int unreliable_bits)
{
  int unreliables[10];
  int *values = malloc(1024 * sizeof(int));
  int i = 0;
  int mask;
函数定义和一些变量声明。这里,
是您的
A
不可靠位
是您的
B

  value &= ~unreliable_bits;
屏蔽不可靠的位,以确保对包含一些不可靠位和
值的整数进行ORing将产生我们想要的结果

  for(mask = 1;i < 10;mask <<= 1)
  {
    if(mask & unreliable_bits)
      unreliables[i++] = mask;
  }
最后,返回我们构建的数组。下面是一个简短的main,可以使用问题中给出的
a
B
的值来测试它:

int main()
{
  int *values = getValues(0x8A7C6BB5, 0x44444496);
  int i;
  for(i = 0;i < 1024;i++)
    printf("%X\n", values[i]);
}
intmain()
{
int*values=getValues(0x8A7C6BB5,0x4496);
int i;
对于(i=0;i<1024;i++)
printf(“%X\n”,值[i]);
}

这基本上遵循了Kerrek使用的技术,但充实了困难的部分:

int* getValues(int value, int unreliable_bits)
{
  int unreliables[10];
  int *values = malloc(1024 * sizeof(int));
  int i = 0;
  int mask;
函数定义和一些变量声明。这里,
是您的
A
不可靠位
是您的
B

  value &= ~unreliable_bits;
屏蔽不可靠的位,以确保对包含一些不可靠位和
值的整数进行ORing将产生我们想要的结果

  for(mask = 1;i < 10;mask <<= 1)
  {
    if(mask & unreliable_bits)
      unreliables[i++] = mask;
  }
最后,返回我们构建的数组。下面是一个简短的main,可以使用问题中给出的
a
B
的值来测试它:

int main()
{
  int *values = getValues(0x8A7C6BB5, 0x44444496);
  int i;
  for(i = 0;i < 1024;i++)
    printf("%X\n", values[i]);
}
intmain()
{
int*values=getValues(0x8A7C6BB5,0x4496);
int i;
对于(i=0;i<1024;i++)
printf(“%X\n”,值[i]);
}

您可以迭代
b
中1024个不同的位设置,如下所示:

unsigned long b = 1145324694;
unsigned long c;

c = 0;
do {
    printf("%#.8lx\n", c & b);
    c = (c | ~b) + 1;
} while (c);
要使用这些修改
a
,只需使用XOR即可:

unsigned long a = 2323409845;
unsigned long b = 1145324694;
unsigned long c;

c = 0;
do {
    printf("%#.8lx\n", a ^ (c & b));
    c = (c | ~b) + 1;
} while (c);
这种方法的优点是,您不需要预先计算任何表,也不需要硬编码1024-它将完全基于
b
中的1位数循环


使用整数向量指令并行此算法也是一件相对简单的事情。

您可以迭代
b
中1024个不同的位设置,如下所示:

unsigned long b = 1145324694;
unsigned long c;

c = 0;
do {
    printf("%#.8lx\n", c & b);
    c = (c | ~b) + 1;
} while (c);
要使用这些修改
a
,只需使用XOR即可:

unsigned long a = 2323409845;
unsigned long b = 1145324694;
unsigned long c;

c = 0;
do {
    printf("%#.8lx\n", a ^ (c & b));
    c = (c | ~b) + 1;
} while (c);
这种方法的优点是,您不需要预先计算任何表,也不需要硬编码1024-它将完全基于
b
中的1位数循环


使用整数向量指令并行该算法也是一件相对简单的事情。

请给出一个具体的例子,因为这不是很清楚。谢谢-添加了一个例子,这会让它更清楚吗?请给出一个具体的例子,因为这不是很清楚。谢谢-添加了一个例子,这会让它更清楚吗?@Aaro恩杜弗:再读一遍,我在第二行把它们关掉。@Arondufour:再读一遍,我在第二行把它们关掉。