有没有一种廉价的方法来 "mirror" 一个字节中的位?

Is there a cheap way to "mirror" the bits in a byte?

当尝试在没有循环的直线上测试可达性时,您可以使用位板表示。想象一下国际象棋,棋盘上的一行或一列表示为一个字节,问题是方格 X 上的车是否可以捕获方格 T 上的目标。

设T:目标,X:开始,O:其他被占用的方格,_:空方格

我发现使用这些符号可视化可能的场景很方便:

// __OXO___ -> X is between others on both sides
// __XOO___ -> X is leftmost of others
// __OOX___ -> X is rightmost of other others
//A: T_OOX___ -> Target left of X x not leftmost -> T > X and O > X -> NOT reachable
//B: T_XOO___ -> Target left of X, X leftmost    -> T > X and O < X -> reachable
//C: __OXO_T_ -> Target right of X, X embedded   -> T < X and ???? -> NOT reachable
//D: __OOX_T_ -> Target right of X, X rightmost  -> T < X and ???? -> reachable

这里有 4 个感兴趣的案例 - 从 A 到 D 标记。情况 A 和 B 很容易处理。

但案例C和D不是。您不能简单地测试 > 或 < 来确定目标是否可达或路径是否被阻塞。

但我们可以做的是通过镜像字节中的位将 C、D 转换为 A、B。所以位 0 -> 位 7,位 1 -> 位 6,...

有谁知道是否有优化的翻转实现?

编辑:我刚刚注意到另一种情况是:E:OT__X___ ...我的理论变坏了,但问题仍然存在。 :)

对此有一些 bit-hackery 解决方案(下面列出了一个示例),但如果您只处理单个字节,则简单的 256 条目查找 table 可能是最有效的.

这是我的 FFT 黑客时代的个人代码库示例(不保证它符合现代 C 标准或任何东西 - 特别是,uint8typedefunsigned char,但现代 C 有,IIRC,一个原生的 uint8_t 可以达到目的):

inline uint8 bitrev8(uint8 n)
{ uint8 tmp = 0x55;
  n = (((n >> 1) & tmp) | ((n & tmp) << 1));

  tmp = 0x33;
  n = (((n >> 2) & tmp) | ((n & tmp) << 2));

  return ((n >> 4) | (n << 4));
}

由于大型查找 tables 的不切实际,16 位、32 位和 64 位数据的相应例程比 8 位版本更胜一筹,这显然解决了比简单的 v = reversed[n]; 更多的指令...

而不是

// __OXO___ -> X is between others on both sides
// __XOO___ -> X is leftmost of others
// __OOX___ -> X is rightmost of other others
//A: T_OOX___ -> Target left of X x not leftmost -> T > X and O > X -> NOT reachable
//B: T_XOO___ -> Target left of X, X leftmost    -> T > X and O < X -> reachable
//C: __OXO_T_ -> Target right of X, X embedded   -> T < X and ???? -> NOT reachable
//D: __OOX_T_ -> Target right of X, X rightmost  -> T < X and ???? -> reachable

在情况 C 和 D 中反转 X 和 T 似乎合乎逻辑:

//C: __OTO_X_ -> Target left of X x not leftmost -> T > X and O > X -> NOT reachable
//D: __OOT_X_ -> Target left of X, X leftmost    -> T > X and O < X -> reachable

我意识到如果 T 是主教而 X 是车,那么 T 可能不会像 X 那样移动,但我们所做的只是看看 T 是否是车,如果它可以移动到 X。该问题与 X 移动到 T 相同。它可以或不能回答相反的问题(X 可以移动到 T)。

为每个字节进行 256 字节查找 table 并使用它而不是执行任何计算。

你可以在不倒车的情况下做这个测试。如果 xto 是您示例中的位掩码(其中 xt 正好设置了一位,并且未设置这些位在 o) 中,那么您可以创建一个包含 tx 之间的位的位掩码,如下所示:

tx = t | x
txhi = tx & (tx - 1)
return (txhi - 1) ^ (tx - 1)

这使用减 1 将以“100...000”结尾的位模式替换为“011...111”。然后您可以简单地检查此掩码是否与 o.

相交