7.10.2011

Mirroring bitboard hirozontally

ビットボードの水平反転

盤面の左右の反転は、Hacker's Delight 的アプローチで簡単にできる。

3回のビット交換を行った後、5筋を追加すればよい。(変換処理は24基本RISC命令で分岐不要)
各段について以下の処理を行うイメージ。
 x ← abcdefghi 初期状態
 y ← .a.c..f.h + b.d..g.i. = badc.gfih 隣り合うビットを交換
 y ← ..ba...gf + dc...ih.. = dcba.ihgf 2ビットを交換
 .....dcba + ihgf..... + ....e.... = ihgfedcba 
4ビットを交換した後、中央のビットを抽出して加算
 

def mirror_horizontal(self):
  """Return bitboard mirrored horizontally."""
  x = self.data
  y = ((x & int('101001010' * 9, 2)) >> 1) + ((x & int('010100101' * 9, 2)) << 1)
  y = ((y & int('110001100' * 9, 2)) >> 2) + ((y & int('001100011' * 9, 2)) << 2)
  return BitBoard(((y & int('111100000' * 9, 2)) >> 5) +
      ((y & int('000001111' * 9, 2)) << 5) + (x & int('000010000' * 9, 2)))

反転前 反転後

--------*
----***-*
*-----**-
*---*-*-*
*-**-***-
*-***-*--
***-*----
***---*--
-*-------

*--------
*-***----
-**-----*
*-*-*---*
-***-**-*
--*-***-*
----*-***
--*---***
-------*-

加算部分は、論理和演算でも同値だが、手元の計測では加算のほうが性能がよかった。

>>> min(timeit.Timer("0x155555555555555555555 | 0xaaaaaaaaaaaaaaaaaaaa").repeat(100))
0.03194931199357143
>>> min(timeit.Timer("0x155555555555555555555 + 0xaaaaaaaaaaaaaaaaaaaa").repeat(100))
0.026588016074668985

参考:
http://chessprogramming.wikispaces.com/Flipping+Mirroring+and+Rotating

0 件のコメント:

コメントを投稿