这是一种将16位掩码拉伸为64位的方法,其中每个位表示4位拉伸掩码的方法:
uint64_t x = 0x000000000000CF00LL;
x = (x | (x << 24)) & 0x000000ff000000ffLL;
x = (x | (x << 12)) & 0x000f000f000f000fLL;
x = (x | (x << 6)) & 0x0303030303030303LL;
x = (x | (x << 3)) & 0x1111111111111111LL;
x |= x << 1;
x |= x << 2;
首先,它从底部16位中获取掩码。然后将掩码的前8位移动到顶部32位中,如下所示:
0000000000000000 0000000000000000 0000000000000000 ABCDEFGHIJKLMNOP
变成
0000000000000000 00000000ABCDEFGH 0000000000000000 00000000IJKLMNOP
然后它解决了一个类似的问题,即将32位字的底部8位拉伸到顶部和底部的32位同时:
000000000000ABCD 000000000000EFGH 000000000000IJKL 000000000000MNOP
然后它会在16位中处理4位,以此类推,直到所有位都被分散开来。
000A000B000C000D 000E000F000G000H 000I000J000K000L 000M000N000O000P
然后它通过将结果与两个自身的OR运算符"涂抹"在4位上。
AAAABBBBCCCCDDDD EEEEFFFFGGGGHHHH IIIIJJJJKKKKLLLL MMMMNNNNOOOOPPPP
您可以通过添加一个额外的第一步骤,即将其向左移动48个比特并与一个128位常量进行掩码处理,从而将其扩展到128位:
x = (x | (x << 48)) & 0x000000000000ffff000000000000ffffLLL;
你还需要将其他常量通过重复比特模式扩展到128位。但是(据我所知),在C ++中没有声明128位常量的方法,但也许你可以使用宏或其他方式来实现(
参见此问题)。你也可以通过将64位版本分别用于顶部和底部16位来创建128位版本。
如果加载掩码常数变得困难或成为瓶颈,您可以使用移位和掩码从前一个常数生成每个常数:
uint64_t m = 0x000000ff000000ffLL;
m &= m >> 4; m |= m << 16; // gives 0x000f000f000f000fLL
m &= m >> 2; m |= m << 8; // gives 0x0303030303030303LL
m &= m >> 1; m |= m << 4; // gives 0x1111111111111111LL
_pdep_u32
是被允许的吗? - harold