87flowers ~ $

calculating piece directions for a piece list (featuring GFNI)

chess

  1. example
  2. explanation
  3. acknowledgements

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;
}

example

visualization of the coordinates in coord for the below example
coords:         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

explanation

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.

acknowledgements

© 2024. All rights reserved. 87flowers