1use core::marker::PhantomData;
4
5pub trait BitBoardKernel: Send + Sync + 'static {
16 fn rook_attacks(square: u8, occupancy: u64) -> u64;
21
22 fn bishop_attacks(square: u8, occupancy: u64) -> u64;
27
28 #[inline(always)]
33 fn queen_attacks(square: u8, occupancy: u64) -> u64 {
34 Self::rook_attacks(square, occupancy) | Self::bishop_attacks(square, occupancy)
35 }
36}
37
38#[repr(transparent)]
43pub struct BitBoardView<'a, Backend, Arch, Ref: 'a = &'a [u64]> {
44 ptr: *mut [u64],
45 _marker: PhantomData<(&'a u64, Backend, Arch, Ref)>,
46}
47
48unsafe impl<'a, Backend, Arch, Ref: 'a> Send for BitBoardView<'a, Backend, Arch, Ref> where Ref: Send
49{}
50unsafe impl<'a, Backend, Arch, Ref: 'a> Sync for BitBoardView<'a, Backend, Arch, Ref> where Ref: Sync
51{}
52
53impl<'a, Backend, Arch> Clone for BitBoardView<'a, Backend, Arch, &'a [u64]> {
54 #[inline(always)]
55 fn clone(&self) -> Self {
56 *self
57 }
58}
59
60impl<'a, Backend, Arch> Copy for BitBoardView<'a, Backend, Arch, &'a [u64]> {}
61
62impl<'a, Backend, Arch> BitBoardView<'a, Backend, Arch, &'a [u64]> {
63 #[inline(always)]
65 pub fn new(data: &'a [u64]) -> Self {
66 Self {
67 ptr: data as *const [u64] as *mut [u64],
68 _marker: PhantomData,
69 }
70 }
71}
72
73impl<'a, Backend, Arch> BitBoardView<'a, Backend, Arch, &'a mut [u64]> {
74 #[inline(always)]
76 pub fn new_mut(data: &'a mut [u64]) -> Self {
77 Self {
78 ptr: data as *mut [u64],
79 _marker: PhantomData,
80 }
81 }
82
83 #[inline(always)]
85 pub fn as_slice_mut(&mut self) -> &mut [u64] {
86 unsafe { &mut *self.ptr }
92 }
93
94 #[inline(always)]
96 pub fn downgrade(self) -> BitBoardView<'a, Backend, Arch, &'a [u64]> {
97 BitBoardView {
98 ptr: self.ptr,
99 _marker: PhantomData,
100 }
101 }
102}
103
104impl<'a, Backend, Arch, Ref: 'a> BitBoardView<'a, Backend, Arch, Ref> {
105 #[inline(always)]
107 pub fn as_slice(&self) -> &[u64] {
108 unsafe { &*self.ptr }
115 }
116}
117
118impl<'a, Backend, Arch, Ref: 'a> core::ops::Deref for BitBoardView<'a, Backend, Arch, Ref> {
119 type Target = [u64];
120 #[inline(always)]
121 fn deref(&self) -> &Self::Target {
122 self.as_slice()
123 }
124}
125
126impl<'a, Backend, Arch> core::ops::DerefMut for BitBoardView<'a, Backend, Arch, &'a mut [u64]> {
127 #[inline(always)]
128 fn deref_mut(&mut self) -> &mut Self::Target {
129 self.as_slice_mut()
130 }
131}
132
133impl<'a, Backend, Arch, Ref: 'a> BitBoardView<'a, Backend, Arch, Ref>
134where
135 Backend: BitBoardKernel,
136{
137 #[inline(always)]
139 pub fn rook_attacks(&self, square: u8, occupancy: u64) -> u64 {
140 Backend::rook_attacks(square, occupancy)
141 }
142
143 #[inline(always)]
145 pub fn bishop_attacks(&self, square: u8, occupancy: u64) -> u64 {
146 Backend::bishop_attacks(square, occupancy)
147 }
148
149 #[inline(always)]
151 pub fn queen_attacks(&self, square: u8, occupancy: u64) -> u64 {
152 Backend::queen_attacks(square, occupancy)
153 }
154
155 #[inline]
160 pub fn batch_attacks_single_occupancy(
161 &self,
162 squares: &[u8],
163 occupancy: u64,
164 out: &mut [u64],
165 is_rook: bool,
166 ) {
167 assert!(
168 out.len() >= squares.len(),
169 "Output slice too short for batch attacks"
170 );
171
172 let len = squares.len();
173 let mut i = 0;
174
175 let unroll = (len / 4) * 4;
176 while i < unroll {
177 let sq0 = squares[i];
178 let sq1 = squares[i + 1];
179 let sq2 = squares[i + 2];
180 let sq3 = squares[i + 3];
181
182 if is_rook {
183 out[i] = Backend::rook_attacks(sq0, occupancy);
184 out[i + 1] = Backend::rook_attacks(sq1, occupancy);
185 out[i + 2] = Backend::rook_attacks(sq2, occupancy);
186 out[i + 3] = Backend::rook_attacks(sq3, occupancy);
187 } else {
188 out[i] = Backend::bishop_attacks(sq0, occupancy);
189 out[i + 1] = Backend::bishop_attacks(sq1, occupancy);
190 out[i + 2] = Backend::bishop_attacks(sq2, occupancy);
191 out[i + 3] = Backend::bishop_attacks(sq3, occupancy);
192 }
193 i += 4;
194 }
195
196 while i < len {
197 let sq = squares[i];
198 out[i] = if is_rook {
199 Backend::rook_attacks(sq, occupancy)
200 } else {
201 Backend::bishop_attacks(sq, occupancy)
202 };
203 i += 1;
204 }
205 }
206}