[board] Implement a BitScanner on u64

This struct implements an Iterator that returns the positions of the 1 bits in the u64.
BitBoard takes this iterator and maps it into Squares in the pieces() method.

This is laying the groundwork for an iterator over the pieces in a Position. 👀
This commit is contained in:
Eryn Wells 2023-12-23 23:04:18 -07:00
parent a2f88f0fde
commit 1da827a3bb
3 changed files with 91 additions and 23 deletions

View file

@ -1,11 +1,14 @@
// Eryn Wells <eryn@erynwells.me>
mod bit_scanner;
use self::bit_scanner::BitScanner;
use crate::square::Square;
use std::fmt;
use std::ops::{BitAnd, BitOr, Not};
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitBoard(u64);
pub(crate) struct BitBoard(u64);
impl BitBoard {
pub fn empty() -> BitBoard {
@ -16,7 +19,7 @@ impl BitBoard {
BitBoard(bits)
}
fn is_empty(&self) -> bool {
pub fn is_empty(&self) -> bool {
self.0 == 0
}
@ -31,20 +34,6 @@ impl BitBoard {
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 BitBoard {
@ -92,6 +81,15 @@ impl BitBoard {
}
}
impl BitBoard {
fn pieces(&self) -> impl Iterator<Item = Square> {
BitScanner::new(self.0)
.map(|x| u8::try_from(x))
.take_while(|x| x.is_ok())
.map(|x| Square::from_index_unsafe(x.unwrap()))
}
}
impl fmt::Debug for BitBoard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
let bits = self.0;
@ -229,12 +227,15 @@ mod tests {
);
}
#[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);
fn pieces() {
let bb = BitBoard(0x1001_1010); // e4
let mut pieces = bb.pieces();
assert_eq!(pieces.next(), Some(Square::from_index_unsafe(28)));
assert_eq!(pieces.next(), Some(Square::from_index_unsafe(16)));
assert_eq!(pieces.next(), Some(Square::from_index_unsafe(12)));
assert_eq!(pieces.next(), Some(Square::from_index_unsafe(4)));
assert_eq!(pieces.next(), None);
}
}