// Eryn Wells use crate::square::Square; use std::ops::{BitAnd, BitOr, Not}; #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct BitBoard(u64); impl BitBoard { pub fn empty() -> BitBoard { BitBoard(0) } pub fn from_bit_field(bits: u64) -> BitBoard { BitBoard(bits) } fn is_empty(&self) -> bool { self.0 == 0 } pub fn has_piece_at(&self, sq: &Square) -> bool { (self.0 & (1 << sq.index)) > 0 } pub fn place_piece_at(&mut self, sq: &Square) { self.0 |= 1 << sq.index } fn remove_piece_at(&mut self, sq: &Square) { self.0 &= !(1 << sq.index) } #[cfg(target_arch = "arm")] fn _arm_count_leading_zeros(&self) -> u8 { let mut number_of_leading_zeros: u8 = 0; unsafe { asm!( "clz {count}, {bitfield}", count = out(reg) number_of_leading_zeros, bitfield = in(reg) self.0, ); } number_of_leading_zeros } } impl BitAnd for BitBoard { type Output = BitBoard; #[inline] fn bitand(self, rhs: Self) -> Self { BitBoard(self.0 & rhs.0) } } impl BitAnd<&BitBoard> for BitBoard { type Output = BitBoard; #[inline] fn bitand(self, rhs: &Self) -> Self { BitBoard(self.0 & rhs.0) } } impl Not for BitBoard { type Output = BitBoard; #[inline] fn not(self) -> Self::Output { BitBoard(!self.0) } } impl Not for &BitBoard { type Output = BitBoard; #[inline] fn not(self) -> Self::Output { BitBoard(!self.0) } } impl BitOr for BitBoard { type Output = BitBoard; #[inline] fn bitor(self, rhs: Self) -> Self { BitBoard(self.0 | rhs.0) } } impl BitOr<&BitBoard> for BitBoard { type Output = BitBoard; #[inline] fn bitor(self, rhs: &Self) -> Self { BitBoard(self.0 | rhs.0) } } #[cfg(test)] mod tests { use super::*; use crate::square::Square; #[test] fn is_empty() { assert!(BitBoard(0).is_empty()); } #[test] fn has_piece_at() { let bb = BitBoard(0b1001100); let c1 = Square::from_algebraic_string("c1").expect("Unable to get square for 'c1'"); assert!(bb.has_piece_at(&c1)); let b1 = Square::from_algebraic_string("b1").expect("Unable to get square for 'b1'"); assert!(!bb.has_piece_at(&b1)); } #[test] fn place_piece_at() { let sq = Square::from_index(34).expect("Invalid square index"); let mut bb = BitBoard(0b1001100); bb.place_piece_at(&sq); assert!(bb.has_piece_at(&sq)); } #[test] fn remove_piece_at() { let sq = Square::from_index(2).expect("Invalid square index"); let mut bb = BitBoard(0b1001100); bb.remove_piece_at(&sq); assert!(!bb.has_piece_at(&sq)); } #[cfg(target_arch = "arm")] #[test] fn arm_count_leading_zeros() { assert_eq!(BitBoard(0)._arm_count_leading_zeros(), 0); assert_eq!(BitBoard(0b10)._arm_count_leading_zeros(), 62); assert_eq!(BitBoard(0b1010)._arm_count_leading_zeros(), 60); assert_eq!(BitBoard(0x80000000)._arm_count_leading_zeros(), 0); } }