HooverChessUtils_PgnReader 0.9.0
Loading...
Searching...
No Matches
bitboard-attacks-aarch64-sve2-bitperm.h
Go to the documentation of this file.
1// Hoover Chess Utilities / PGN reader
2// Copyright (C) 2023-2025 Sami Kiminki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17#ifndef HOOVER_CHESS_UTILS__PGN_READER__BITBOARD_ATTACKS_AARCH64_SVE2_BITPERM_H_INCLUDED
18#define HOOVER_CHESS_UTILS__PGN_READER__BITBOARD_ATTACKS_AARCH64_SVE2_BITPERM_H_INCLUDED
19
20#include "bitboard-tables.h"
21
23#include "pgnreader-config.h"
24
25#include <array>
26#include <cinttypes>
27#include <utility>
28
29#include <arm_sve.h>
30
31static_assert(HAVE_AARCH64_SVE2_BITPERM, "This file should be included only when AArch64 SVE2 BitPerm is available");
32
34{
35
39{
40private:
41 struct PextData
42 {
43 alignas(64) std::array<std::uint64_t, 128U> bishopRookMasks;
44 alignas(64) std::array<std::uint64_t, 128U> bishopRookOffsets;
45 alignas(64) std::array<std::uint64_t, 5248U + 102400U> bishopRookAttackData;
46 };
47
48 static const PextData ctPextData;
49
50public:
52 static SquareSet getBishopAttackMask(Square sq, SquareSet occupancyMask) noexcept
53 {
54 const std::uint64_t pextMask { ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(sq)] };
55 const std::uint64_t offset { ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(sq)] };
56
57 svuint64_t occupancyMaskV { svdup_u64(static_cast<std::uint64_t>(occupancyMask)) };
58
59 svuint64_t extractedV { svbext_n_u64(occupancyMaskV, static_cast<std::uint64_t>(pextMask)) };
60 const std::uint64_t extracted { extractedV[0U] };
61
62 return SquareSet { ctBitBoardTables.sve2BishopRookAttackData[offset + extracted] };
63 }
64
66 static inline SquareSet getRookAttackMask(Square sq, SquareSet occupancyMask) noexcept
67 {
68 const std::uint64_t pextMask { ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(sq) + 1U] };
69 const std::uint64_t offset { ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(sq) + 1U] };
70
71 svuint64_t occupancyMaskV { svdup_u64(static_cast<std::uint64_t>(occupancyMask)) };
72
73 svuint64_t extractedV { svbext_n_u64(occupancyMaskV, static_cast<std::uint64_t>(pextMask)) };
74 const std::uint64_t extracted { extractedV[0U] };
75
76 return SquareSet { ctBitBoardTables.sve2BishopRookAttackData[offset + extracted] };
77 }
78
80 static inline SquareSet getQueenAttackMask(Square sq, SquareSet occupancyMask) noexcept
81 {
82 // note: the vector elements are in order: bishop, rook
83
84 // we'll use the first two elements of the vector when it matters
85 const std::uint64_t pextMaskB { ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(sq)] };
86 const std::uint64_t pextMaskR { ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(sq) + 1U] };
87
88 const std::uint64_t offsetB { ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(sq)] };
89 const std::uint64_t offsetR { ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(sq) + 1U] };
90
91 const svuint64_t pextMaskV { svdupq_u64(pextMaskB, pextMaskR) };
92
93 const svuint64_t occupancyMaskV { svdup_u64(static_cast<std::uint64_t>(occupancyMask)) };
94
95 const svuint64_t extractedV { svbext_u64(occupancyMaskV, pextMaskV) };
96
97 const std::uint64_t extractedB { extractedV[0U] };
98 const std::uint64_t extractedR { extractedV[1U] };
99
100 return
101 SquareSet { ctBitBoardTables.sve2BishopRookAttackData[offsetB + extractedB] } |
102 SquareSet { ctBitBoardTables.sve2BishopRookAttackData[offsetR + extractedR] };
103
104 }
105
106 static inline std::pair<SquareSet, SquareSet> getBishopAndRookAttackMasks(
107 Square sq,
108 SquareSet occupancyMask) noexcept
109 {
110 const std::uint64_t pextMaskB { ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(sq)] };
111 const std::uint64_t pextMaskR { ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(sq) + 1U] };
112
113 const svuint64_t pextMaskV { svdupq_u64(pextMaskB, pextMaskR) };
114
115 const std::uint64_t offsetB { ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(sq)] };
116 const std::uint64_t offsetR { ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(sq) + 1U] };
117
118 const svuint64_t occupancyMaskV { svdup_u64(static_cast<std::uint64_t>(occupancyMask)) };
119
120 svuint64_t extractedV { svbext_u64(occupancyMaskV, pextMaskV) };
121
122 const std::uint64_t extractedB { extractedV[0U] };
123 const std::uint64_t extractedR { extractedV[1U] };
124
125 return std::make_pair(
126 SquareSet { ctBitBoardTables.sve2BishopRookAttackData[offsetB + extractedB] },
127 SquareSet { ctBitBoardTables.sve2BishopRookAttackData[offsetR + extractedR] });
128 }
129
130 static inline std::pair<SquareSet, SquareSet> getBishopAndRookAttackMasks(
131 Square sq,
132 SquareSet occupancyMaskForBishopAttacks,
133 SquareSet occupancyMaskForRookAttacks) noexcept
134 {
135 const std::uint64_t pextMaskB { ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(sq)] };
136 const std::uint64_t pextMaskR { ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(sq) + 1U] };
137
138 const svuint64_t pextMaskV { svdupq_u64(pextMaskB, pextMaskR) };
139
140 const std::uint64_t offsetB { ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(sq)] };
141 const std::uint64_t offsetR { ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(sq) + 1U] };
142
143 const svuint64_t occupancyMaskV { svdupq_u64(
144 static_cast<std::uint64_t>(occupancyMaskForBishopAttacks),
145 static_cast<std::uint64_t>(occupancyMaskForRookAttacks)) };
146
147 svuint64_t extractedV { svbext_u64(occupancyMaskV, pextMaskV) };
148
149 const std::uint64_t extractedB { extractedV[0U] };
150 const std::uint64_t extractedR { extractedV[1U] };
151
152 return std::make_pair(
153 SquareSet { ctBitBoardTables.sve2BishopRookAttackData[offsetB + extractedB] },
154 SquareSet { ctBitBoardTables.sve2BishopRookAttackData[offsetR + extractedR] });
155 }
156
158 Square kingSq,
159 SquareSet occupancyMask,
160 SquareSet rooks,
161 SquareSet bishops,
162 SquareSet opponentPieces,
163 SquareSet epCapturable,
164 SquareSet &out_checkers,
165 SquareSet &out_pinners) noexcept
166 {
167 const svbool_t firstTwo { svptrue_pat_b64(SV_VL2) };
168
169 const svuint64_t pextMaskV { svld1_u64(firstTwo, &ctBitBoardTables.sve2BishopRookMasks[2U * static_cast<std::uint8_t>(kingSq)]) };
170 const svuint64_t occupancyMaskV { svdup_u64(static_cast<std::uint64_t>(occupancyMask)) };
171 const svuint64_t opponentPiecesV { svdup_u64(static_cast<std::uint64_t>(opponentPieces)) };
172 const svuint64_t bishopsRooksV { svdupq_u64(static_cast<std::uint64_t>(bishops), static_cast<std::uint64_t>(rooks)) };
173 const svuint64_t baseOffsetV { svld1_u64(firstTwo, &ctBitBoardTables.sve2BishopRookOffsets[2U * static_cast<std::uint8_t>(kingSq)]) };
174
175 // Resolve checkers
176 svuint64_t extractedV { svbext_u64(occupancyMaskV, pextMaskV) };
177 const svuint64_t firstHitsV { svld1_gather_u64index_u64(firstTwo, ctBitBoardTables.sve2BishopRookAttackData.data(), baseOffsetV + extractedV) };
178 const svuint64_t checkersV { firstHitsV & bishopsRooksV & opponentPiecesV };
179
180 out_checkers = { SquareSet { svorv_u64(firstTwo, checkersV) } };
181
182 // Resolve pinned pieces. Notes:
183 // - We'll remove only pinnable pieces from the first hits. The idea is to avoid
184 // x-rays over non-pinnable pieces in order to minimize the number of pinners
185 // - In the second hit check, we'll remove pieces that are already determined to be checkers.
186 // The reason is the same as the above.
187 extractedV = svbext_u64(
188 ((occupancyMaskV &~ firstHitsV) | (opponentPiecesV &~ svdupq_u64(static_cast<std::uint64_t>(epCapturable), 0U))),
189 pextMaskV);
190
191 const svuint64_t secondHitsV { svld1_gather_u64index_u64(firstTwo, ctBitBoardTables.sve2BishopRookAttackData.data(), baseOffsetV + extractedV) };
192 const svuint64_t pinnersV { secondHitsV & bishopsRooksV };
193
194 out_pinners = SquareSet { svorv_u64(firstTwo, pinnersV) } &~ out_checkers & opponentPieces;
195 }
196};
197
198}
199
200#endif
Slider attacks implementation using PEXT/PDEP.
Definition bitboard-attacks-aarch64-sve2-bitperm.h:39
static SquareSet getQueenAttackMask(Square sq, SquareSet occupancyMask) noexcept
See Attacks::getQueenAttackMask() for documentation.
Definition bitboard-attacks-aarch64-sve2-bitperm.h:80
static std::pair< SquareSet, SquareSet > getBishopAndRookAttackMasks(Square sq, SquareSet occupancyMask) noexcept
Definition bitboard-attacks-aarch64-sve2-bitperm.h:106
static const PextData ctPextData
Definition bitboard-attacks-aarch64-sve2-bitperm.h:48
static SquareSet getBishopAttackMask(Square sq, SquareSet occupancyMask) noexcept
See Attacks::getBishopAttackMask() for documentation.
Definition bitboard-attacks-aarch64-sve2-bitperm.h:52
static void determineSliderCheckersAndPinners(Square kingSq, SquareSet occupancyMask, SquareSet rooks, SquareSet bishops, SquareSet opponentPieces, SquareSet epCapturable, SquareSet &out_checkers, SquareSet &out_pinners) noexcept
Definition bitboard-attacks-aarch64-sve2-bitperm.h:157
static std::pair< SquareSet, SquareSet > getBishopAndRookAttackMasks(Square sq, SquareSet occupancyMaskForBishopAttacks, SquareSet occupancyMaskForRookAttacks) noexcept
Definition bitboard-attacks-aarch64-sve2-bitperm.h:130
static SquareSet getRookAttackMask(Square sq, SquareSet occupancyMask) noexcept
See Attacks::getRookAttackMask() for documentation.
Definition bitboard-attacks-aarch64-sve2-bitperm.h:66
Set of squares. Implemented using a bit-mask.
Definition chessboard-types-squareset.h:35
Square
Named square.
Definition chessboard-types.h:122
Definition chessboard-types-squareset.h:30
const BitBoardTables ctBitBoardTables
Various bitboard attack and other tables.
Definition bitboard-attacks-aarch64-sve2-bitperm.h:42
std::array< std::uint64_t, 5248U+102400U > bishopRookAttackData
Definition bitboard-attacks-aarch64-sve2-bitperm.h:45
std::array< std::uint64_t, 128U > bishopRookMasks
Definition bitboard-attacks-aarch64-sve2-bitperm.h:43
std::array< std::uint64_t, 128U > bishopRookOffsets
Definition bitboard-attacks-aarch64-sve2-bitperm.h:44