Skip to main content

usiagent/
bitboard.rs

1//! 合法手を生成するために利用するビットボード関連の実装
2use std::fmt;
3use std::fmt::Formatter;
4use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, Shr, Sub};
5use bits::pop_lsb;
6use rule::Square;
7
8/// 合法手を生成するために内部で利用するビットボード
9#[derive(Clone, Copy)]
10pub union BitBoard {
11    merged_bitboard:u128,
12    bitboard:[u64; 2]
13}
14impl From<u128> for BitBoard {
15    #[inline]
16    fn from(bits: u128) -> Self {
17        BitBoard {
18            merged_bitboard: bits
19        }
20    }
21}
22impl Default for BitBoard {
23    #[inline]
24    fn default() -> Self {
25        BitBoard {
26            merged_bitboard: 0
27        }
28    }
29}
30impl From<BitBoard> for (u64,u64) {
31    #[inline]
32    fn from(bitboard: BitBoard) -> Self {
33        unsafe { (*bitboard.bitboard.get_unchecked(0), *bitboard.bitboard.get_unchecked(1)) }
34    }
35}
36impl BitOr for BitBoard {
37    type Output = Self;
38
39    #[inline]
40    fn bitor(self, rhs: Self) -> Self {
41        unsafe {
42            BitBoard { merged_bitboard: self.merged_bitboard | rhs.merged_bitboard }
43        }
44    }
45}
46impl BitAnd for BitBoard {
47    type Output = Self;
48
49    #[inline]
50    fn bitand(self, rhs: Self) -> Self::Output {
51        unsafe {
52            BitBoard { merged_bitboard: self.merged_bitboard & rhs.merged_bitboard }
53        }
54    }
55}
56impl BitAndAssign for BitBoard {
57    #[inline]
58    fn bitand_assign(&mut self, rhs: Self) {
59        *self = unsafe {
60            BitBoard { merged_bitboard: self.merged_bitboard & rhs.merged_bitboard }
61        }
62    }
63}
64impl BitOrAssign for BitBoard {
65    #[inline]
66    fn bitor_assign(&mut self, rhs: Self) {
67        *self = unsafe {
68            BitBoard { merged_bitboard: self.merged_bitboard | rhs.merged_bitboard }
69        }
70    }
71}
72impl BitXor for BitBoard {
73    type Output = Self;
74
75    #[inline]
76    fn bitxor(self, rhs: Self) -> Self {
77        unsafe {
78            BitBoard { merged_bitboard: self.merged_bitboard ^ rhs.merged_bitboard }
79        }
80    }
81}
82impl BitXorAssign for BitBoard {
83
84    #[inline]
85    fn bitxor_assign(&mut self, rhs: Self) {
86        unsafe {
87            self.merged_bitboard ^= rhs.merged_bitboard;
88        }
89    }
90}
91impl Not for BitBoard {
92    type Output = Self;
93
94    #[inline]
95    fn not(self) -> Self {
96        unsafe {
97            BitBoard { merged_bitboard: !self.merged_bitboard }
98        }
99    }
100}
101impl Sub for BitBoard {
102    type Output = Self;
103
104    #[inline]
105    fn sub(self, rhs: Self) -> Self::Output {
106        unsafe {
107            BitBoard { merged_bitboard: self.merged_bitboard - rhs.merged_bitboard }
108        }
109    }
110}
111impl PartialEq for BitBoard {
112    #[inline]
113    fn eq(&self,other:&BitBoard) -> bool {
114        unsafe { self.merged_bitboard == other.merged_bitboard }
115    }
116}
117impl BitOr<u128> for BitBoard {
118    type Output = Self;
119
120    #[inline]
121    fn bitor(self, rhs: u128) -> Self {
122        unsafe {
123            BitBoard { merged_bitboard: self.merged_bitboard | rhs }
124        }
125    }
126}
127impl BitAnd<u128> for BitBoard {
128    type Output = Self;
129
130    #[inline]
131    fn bitand(self, rhs: u128) -> Self::Output {
132        unsafe {
133            BitBoard { merged_bitboard: self.merged_bitboard & rhs }
134        }
135    }
136}
137impl BitAndAssign<u128> for BitBoard {
138    #[inline]
139    fn bitand_assign(&mut self, rhs: u128) {
140        *self = unsafe {
141            BitBoard { merged_bitboard: self.merged_bitboard & rhs }
142        }
143    }
144}
145impl BitOrAssign<u128> for BitBoard {
146    #[inline]
147    fn bitor_assign(&mut self, rhs: u128) {
148        *self = unsafe {
149            BitBoard { merged_bitboard: self.merged_bitboard | rhs }
150        }
151    }
152}
153impl BitXor<u128> for BitBoard {
154    type Output = Self;
155
156    #[inline]
157    fn bitxor(self, rhs: u128) -> Self {
158        unsafe {
159            BitBoard { merged_bitboard: self.merged_bitboard ^ rhs }
160        }
161    }
162}
163impl BitXorAssign<u128> for BitBoard {
164
165    #[inline]
166    fn bitxor_assign(&mut self, rhs: u128) {
167        unsafe {
168            self.merged_bitboard ^= rhs;
169        }
170    }
171}
172impl Sub<u128> for BitBoard {
173    type Output = Self;
174
175    #[inline]
176    fn sub(self, rhs: u128) -> Self::Output {
177        unsafe {
178            BitBoard { merged_bitboard: self.merged_bitboard - rhs }
179        }
180    }
181}
182impl Shl<u128> for BitBoard {
183    type Output = Self;
184
185    #[inline]
186    fn shl(self, rhs: u128) -> Self::Output {
187        BitBoard { merged_bitboard: unsafe { self.merged_bitboard } << rhs }
188    }
189}
190impl Shr<u128> for BitBoard {
191    type Output = Self;
192
193    #[inline]
194    fn shr(self, rhs: u128) -> Self::Output {
195        BitBoard { merged_bitboard: unsafe { self.merged_bitboard } >> rhs }
196    }
197}
198impl PartialEq<u128> for BitBoard {
199    #[inline]
200    fn eq(&self,other:&u128) -> bool {
201        unsafe { self.merged_bitboard == *other }
202    }
203}
204impl Eq for BitBoard {}
205impl fmt::Debug for BitBoard {
206    #[inline]
207    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
208        write!(f, "{}", unsafe { self.merged_bitboard })
209    }
210}
211impl BitAnd<BitBoard> for u128 {
212    type Output = BitBoard;
213
214    #[inline]
215    fn bitand(self, rhs: BitBoard) -> Self::Output {
216        unsafe {
217            BitBoard { merged_bitboard: self & rhs.merged_bitboard }
218        }
219    }
220}
221/// ビットボードの最下位ビットを取り出すイテレータ
222pub struct PopLsbIterByCallback<F> {
223    callback:F
224}
225impl BitBoard {
226    /// ビットボード内の下位方向から見たビット位置を取り出して返すイテレータを生成する
227    #[inline]
228    pub fn iter(self) -> impl Iterator<Item = Square> {
229        let br = (unsafe { *self.bitboard.get_unchecked(0) } == 0) as usize;
230        let bl = (unsafe { *self.bitboard.get_unchecked(1) } == 0) as usize;
231
232        let mut index = br + (bl & br);
233
234        let mut board = self;
235
236        PopLsbIterByCallback {
237            callback: move || {
238                if index == 2 {
239                    None
240                } else {
241                    let p = unsafe { board.bitboard.get_unchecked_mut(index) };
242
243                    if *p == 0 {
244                        return None;
245                    }
246
247                    let s = pop_lsb(&mut *p) as Square + index as Square * 64 - 1;
248
249                    index += ((*p) == 0) as usize;
250
251                    Some(s as Square)
252                }
253            }
254        }
255    }
256
257    /// ビットボードのビット列を反転させ、下位から82bit分の範囲に収まるように位置を調整する
258    #[inline]
259    pub fn reverse(self) -> BitBoard {
260        BitBoard {
261            merged_bitboard: unsafe { self.merged_bitboard.reverse_bits() >> 45 }
262        }
263    }
264
265    /// ビットボード内の立っているビットの個数を返す
266    #[inline]
267    pub fn bitcount(self) -> usize {
268        unsafe {
269            self.bitboard.get_unchecked(0).count_ones() as usize + self.bitboard.get_unchecked(1).count_ones() as usize
270        }
271    }
272
273    /// BitBoardに対するオーバーフローを許容する減算
274    #[inline]
275    pub fn wrapping_sub(self,rhs: u128) -> BitBoard {
276        BitBoard {
277            merged_bitboard: unsafe { self.merged_bitboard.wrapping_sub(rhs) }
278        }
279    }
280}
281impl<F> Iterator for PopLsbIterByCallback<F> where F: FnMut() -> Option<Square> {
282    type Item = Square;
283
284    #[inline]
285    fn next(&mut self) -> Option<Self::Item> {
286        (self.callback)()
287    }
288}