为特定的半字节创建掩码

问题描述:

如何以尽可能高效的方式为所有半字节创建一个无符号64位整数的掩码,以匹配某个值?为特定的半字节创建掩码

例如,假设我有一个64位无符号整数:

0000 0100 0011 0011 0011 0011 0010 0010 0010 0010 0010 0010 0001 0001 0001 0001 

而且说我只希望允许拥有的0010 值啃我怎样才能找到那些蚕食和创建蒙为他们。 在这种人为的例子我知道当然半字节5:10是0010,等等对应的掩模来创建是:

0000 0000 0000 0000 0000 0000 1111 1111 1111 1111 1111 1111 0000 0000 0000 0000 

但是我想为任何64位无符号整数,任何形成这种掩模蚕食价值。例如,我可能对010000101000半字节感兴趣。

+0

这是一个解谜意义上的有趣问题,但我不知道它是否可能是XY问题? – njuffa

例如如下(只是的公知的技巧的组合物)

  1. XOR与期望的值,使得一个半字节0 当且仅当它具有正确的值
  2. 计算水平-OR为所有啃
  3. 删除垃圾位
  4. 加宽的结果,以适应整个啃
  5. 面具最终倒,反转回来

所以没有测试:

x ^= test_value 
// now h-OR nibbles 
x |= x >> 1 
x |= x >> 2 
// remove junk 
x &= 0x1111111111111111 
// widen 
x *= 15 
// invert 
x = ~x 
+0

真是太神奇了,谢谢!我在回答问题之前10分钟就想出了一个解决方案,我已经将它包括在内以提供完整性,但它不像您的解决方案那么简洁!我接受你的答案。 – Ward9250

这里有一个版本,我设法拿出试验和错误小时后,却是近norwhere以纯如哈罗德的版本。为了完整性,我在这里发布它: 我把它写在茱莉亚语言中。

@inline function mask_nibbles(x::UInt64, value::UInt64) 
    x = ~(x $ value) 
    x = (x & 0x1111111111111111) & 
    ((x >> 1) & 0x1111111111111111) & 
    ((x >> 2) & 0x1111111111111111) & 
    ((x >> 3) & 0x1111111111111111) 
    return x | (x << 1) | (x << 2) | (x << 3) 
end