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.