作为previous question的后续行动:
假设您有一个uint64_t,并且只关心uint64_t
中每个字节的非高位数位。像这样:
0111.1111 0111.1111 0111.1111 0111.1111 0111.1111 0111.1111 0111.1111 0111.1111
--->
0000.0000 1111.1111 1111.1111 1111.1111 1111.1111 1111.1111 1111.1111 1111.1111
是否有更快的方法将每个7位部分向右移动,而不是将每个部分屏蔽掉,向右移动,然后添加到下一部分?
不幸的是,我没有热AVX指令允许快速和一般的比特收集;我只能访问SSE2指令。
答案 0 :(得分:3)
你可以用三个面具和轮班来做。
u64 val;
// remove bits at 7, 23, 39, 47
u64 odd8 = val & 0x7f007f007f007f00L;
u64 even8 = val & 0x007f007f007f007fL;
val = ( odd8 >> 1 ) | even8;
// remove bits at 15-16, 23-24
u64 odd16 = val & 0x3FFF00003FFF0000L;
u64 even16 = val & 0x00003FFF00003FFFL;
val = ( odd16 >> 2 ) | even16;
// remove bits at 31-35
u64 odd32 = val & 0x0FFFFFFF00000000L;
u64 even32 = val & 0x000000000FFFFFFFL;
val = ( odd32 >> 4 ) | even32;