为特定半字节创建蒙版

时间:2016-09-10 13:05:40

标签: 64-bit bit-manipulation bitwise-operators bit

我怎样才能 - 以尽可能高效的方式 - 为符合特定值的无符号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半字节感兴趣。

2 个答案:

答案 0 :(得分:1)

例如如下(只是一个众所周知的技巧组合)

  1. 使用所需的值进行XOR,使半字符0 iff 具有正确的值
  2. 计算所有半字节的水平OR值
  3. 删除垃圾位
  4. 扩大结果以适应整个半字节
  5. 面罩最终倒置,倒转
  6. 所以,未经测试:

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

答案 1 :(得分:0)

这是我在经过数小时的试验和错误后设法提出的一个版本,但它并不像哈罗德的版本那样整洁。我在这里发布它只是为了完整性: 我用朱莉亚语写出来。

@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