87flowers ~ $
chess
Came up with this while thinking about methods of implementing Static Exchange Evaluation. Ultimately rejected this method but found the code interesting enough to post.
This function takes in a list of coordinates coords
, and returns the compass direction they are in relative to a square sq
.
v128 raysOfCoords(v128 coords, Square sq) {
// 00rrrfff → 0rrr0fff
const v128 expandedCoords = vec::gf2p8affine8(coords, v128::broadcast64(0x0102040008102000), 0);
const v128 expandedSq = v128::broadcast8(expandSq(sq));
// difference between files and ranks (sign bit of result is extracted later)
const v128 diff = vec::sub8(expandedCoords | v128::broadcast8(0x88), expandedSq);
// are files and ranks the same (sign bit of result is extracted later)
const v128 same = vec::add8(expandedCoords ^ expandedSq, v128::broadcast8(0x77));
// extract above four sign bits into an index for LUT
const v128 indexes =
vec::gf2p8affine8(diff, v128::broadcast64(0x8008000000000000), 0)
| vec::gf2p8affine8(same, v128::broadcast64(0x0000800800000000), 0);
constexpr v128 LUT{std::array<u8, 16>{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 4, 0,
0xFF, 6, 0xFF, 2, 5, 7, 3, 1,
}};
// do the lookup with LUT to determine rays
const v128 ray = vec::permute8(indexes, LUT);
return ray;
}
coord
for the below examplecoords: d6 f6 h4 e3 d2 a1 b4 a7 e7 f5 h3 e2 b1 a2 a6 b8
expandedCoords: 53 55 37 24 13 00 31 60 64 45 27 14 01 10 50 71
expandedSq: 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33
diff: a8 aa 8c 79 68 55 86 b5 b9 9a 7c 69 56 65 a5 c6
same: d7 dd 7b 8e 97 aa 79 ca ce ed 8b 9e a9 9a da b9
nearly_indexes: 07 0f 0b 0e 06 0c 09 0d 0f 0f 0e 0e 0c 0c 0d 0d
indexes: 00 01 02 03 04 05 06 07 01 01 03 03 05 05 07 07
diff
calculates the difference between the files and ranks between each coord
and sq
.
We extract the sign of this difference. (Two bits of information.)
same
detects when files or ranks between code
and sq
are the same.
We extract whether the file/rank was the same. (Two bits of information.)
indexes
extracts the above four bits of information and compresses it into a four bit lookup index.
LUT
determines which ray it is from the above four bits.
ray
indicates compass direction:
00
= North
01
= NE
02
= East
03
= SE
04
= South
05
= SW
06
= West
07
= NW
Detecting the off-ray squares is possible (xor file diff with rank diff to determine if on diagonal), but this was not required for my use case.