2023-12-19 11:13:06 -08:00
|
|
|
// Eryn Wells <eryn@erynwells.me>
|
|
|
|
|
2023-12-21 08:17:06 -08:00
|
|
|
use crate::square::Square;
|
2023-12-23 09:16:32 -07:00
|
|
|
use std::ops::{BitAnd, BitOr, Not};
|
2023-12-21 08:17:06 -08:00
|
|
|
|
2023-12-19 11:13:06 -08:00
|
|
|
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
2023-12-22 08:50:03 -08:00
|
|
|
pub struct BitBoard(u64);
|
2023-12-21 08:17:06 -08:00
|
|
|
|
|
|
|
impl BitBoard {
|
2023-12-22 08:50:03 -08:00
|
|
|
pub fn empty() -> BitBoard {
|
|
|
|
BitBoard(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_bit_field(bits: u64) -> BitBoard {
|
|
|
|
BitBoard(bits)
|
|
|
|
}
|
|
|
|
|
2023-12-21 08:17:06 -08:00
|
|
|
fn is_empty(&self) -> bool {
|
|
|
|
self.0 == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn has_piece_at(&self, sq: &Square) -> bool {
|
|
|
|
(self.0 & (1 << sq.index)) > 0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn place_piece_at(&mut self, sq: &Square) {
|
|
|
|
self.0 |= 1 << sq.index
|
|
|
|
}
|
2023-12-21 08:17:17 -08:00
|
|
|
|
2023-12-21 08:30:48 -08:00
|
|
|
fn remove_piece_at(&mut self, sq: &Square) {
|
|
|
|
self.0 &= !(1 << sq.index)
|
|
|
|
}
|
|
|
|
|
2023-12-21 08:17:17 -08:00
|
|
|
#[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
|
|
|
|
}
|
2023-12-21 08:17:06 -08:00
|
|
|
}
|
|
|
|
|
2023-12-22 08:50:03 -08:00
|
|
|
impl BitAnd for BitBoard {
|
|
|
|
type Output = BitBoard;
|
|
|
|
|
2023-12-23 09:17:07 -07:00
|
|
|
#[inline]
|
2023-12-22 08:50:03 -08:00
|
|
|
fn bitand(self, rhs: Self) -> Self {
|
|
|
|
BitBoard(self.0 & rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BitAnd<&BitBoard> for BitBoard {
|
|
|
|
type Output = BitBoard;
|
|
|
|
|
2023-12-23 09:17:07 -07:00
|
|
|
#[inline]
|
2023-12-22 08:50:03 -08:00
|
|
|
fn bitand(self, rhs: &Self) -> Self {
|
|
|
|
BitBoard(self.0 & rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-23 09:16:32 -07:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-22 08:50:03 -08:00
|
|
|
impl BitOr for BitBoard {
|
|
|
|
type Output = BitBoard;
|
|
|
|
|
2023-12-23 09:16:32 -07:00
|
|
|
#[inline]
|
2023-12-22 08:50:03 -08:00
|
|
|
fn bitor(self, rhs: Self) -> Self {
|
|
|
|
BitBoard(self.0 | rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BitOr<&BitBoard> for BitBoard {
|
|
|
|
type Output = BitBoard;
|
|
|
|
|
2023-12-23 09:17:07 -07:00
|
|
|
#[inline]
|
2023-12-22 08:50:03 -08:00
|
|
|
fn bitor(self, rhs: &Self) -> Self {
|
|
|
|
BitBoard(self.0 | rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-21 08:17:06 -08:00
|
|
|
#[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);
|
|
|
|
|
|
|
|
assert!(bb.has_piece_at(
|
|
|
|
&Square::from_algebraic_string("a3").expect("Unable to get square for 'a3'")
|
|
|
|
));
|
|
|
|
assert!(!bb.has_piece_at(
|
|
|
|
&Square::from_algebraic_string("a2").expect("Unable to get square for 'a2'")
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn place_piece_at() {
|
2023-12-21 08:30:48 -08:00
|
|
|
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");
|
|
|
|
|
2023-12-21 08:17:06 -08:00
|
|
|
let mut bb = BitBoard(0b1001100);
|
2023-12-21 08:30:48 -08:00
|
|
|
bb.remove_piece_at(&sq);
|
|
|
|
assert!(!bb.has_piece_at(&sq));
|
2023-12-21 08:17:06 -08:00
|
|
|
}
|
2023-12-21 08:17:17 -08:00
|
|
|
|
|
|
|
#[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);
|
|
|
|
}
|
2023-12-21 08:17:06 -08:00
|
|
|
}
|