[board] Rehash BitBoard's std::ops implementations

Implement bitwise AND and OR for all permutations of BitBoard and &BitBoard.
Refer to the std::ops traits by fully-qualified path rather than requiring the
module to import those traits to implement them.

Implement bitwise AND and OR assignment (&= and |=) for BitBoard and &BitBoard.

Implement XOR and XOR assignment for BitBoards.
This commit is contained in:
Eryn Wells 2024-01-21 09:14:02 -08:00
parent 918b68f300
commit 620701057d

View file

@ -4,7 +4,7 @@ use super::library::{library, FILES, RANKS};
use super::LeadingBitScanner; use super::LeadingBitScanner;
use crate::{square::Direction, Square}; use crate::{square::Direction, Square};
use std::fmt; use std::fmt;
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not}; use std::ops::Not;
#[derive(Clone, Copy, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub(crate) struct BitBoard(pub(super) u64); pub(crate) struct BitBoard(pub(super) u64);
@ -156,39 +156,49 @@ impl fmt::Debug for BitBoard {
} }
macro_rules! infix_op { macro_rules! infix_op {
($trait_type:ident, $func_name:ident, $type:ty) => {
infix_op!($trait_type, $func_name, $type, $type);
infix_op!($trait_type, $func_name, $type, &$type);
infix_op!($trait_type, $func_name, &$type, $type);
infix_op!($trait_type, $func_name, &$type, &$type);
};
($trait_type:ident, $func_name:ident, $left_type:ty, $right_type:ty) => { ($trait_type:ident, $func_name:ident, $left_type:ty, $right_type:ty) => {
impl $trait_type<$right_type> for $left_type { impl std::ops::$trait_type<$right_type> for $left_type {
type Output = BitBoard; type Output = BitBoard;
#[inline] #[inline]
fn $func_name(self, rhs: $right_type) -> Self::Output { fn $func_name(self, rhs: $right_type) -> Self::Output {
BitBoard($trait_type::$func_name(self.0, rhs.0)) BitBoard(std::ops::$trait_type::$func_name(self.0, rhs.0))
} }
} }
}; };
} }
macro_rules! assign_op { macro_rules! assign_op {
($trait_type:ident, $func_name:ident, $left_type:ty) => { ($trait_type:ident, $func_name:ident, $type:ty) => {
impl $trait_type for $left_type { impl std::ops::$trait_type for $type {
#[inline] #[inline]
fn $func_name(&mut self, rhs: Self) { fn $func_name(&mut self, rhs: $type) {
$trait_type::$func_name(&mut self.0, rhs.0) std::ops::$trait_type::$func_name(&mut self.0, rhs.0)
}
}
impl std::ops::$trait_type<&$type> for $type {
#[inline]
fn $func_name(&mut self, rhs: &$type) {
std::ops::$trait_type::$func_name(&mut self.0, rhs.0)
} }
} }
}; };
} }
infix_op!(BitAnd, bitand, BitBoard, BitBoard); infix_op!(BitAnd, bitand, BitBoard);
infix_op!(BitAnd, bitand, BitBoard, &BitBoard); infix_op!(BitOr, bitor, BitBoard);
infix_op!(BitAnd, bitand, &BitBoard, &BitBoard); infix_op!(BitXor, bitxor, BitBoard);
assign_op!(BitAndAssign, bitand_assign, BitBoard); assign_op!(BitAndAssign, bitand_assign, BitBoard);
assign_op!(BitOrAssign, bitor_assign, BitBoard); assign_op!(BitOrAssign, bitor_assign, BitBoard);
assign_op!(BitXorAssign, bitxor_assign, BitBoard);
infix_op!(BitOr, bitor, BitBoard, BitBoard);
infix_op!(BitOr, bitor, BitBoard, &BitBoard);
infix_op!(BitOr, bitor, &BitBoard, &BitBoard);
impl Not for BitBoard { impl Not for BitBoard {
type Output = BitBoard; type Output = BitBoard;
@ -232,13 +242,12 @@ impl BitBoardBuilder {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::Square; use crate::{bitboard, Square};
#[test] #[test]
fn display_and_debug() { fn display_and_debug() {
let bb = BitBoard::file(0) | BitBoard::file(3) | BitBoard::rank(7) | BitBoard::rank(4); let bb = BitBoard::file(0) | BitBoard::file(3) | BitBoard::rank(7) | BitBoard::rank(4);
println!("{}", &bb); println!("{}", &bb);
println!("{:?}", &bb);
} }
#[test] #[test]
@ -302,4 +311,34 @@ mod tests {
assert_eq!(a, b); assert_eq!(a, b);
} }
} }
#[test]
fn xor() {
let a = bitboard![C5, G7];
let b = bitboard![B5, G7, H3];
assert_eq!(a ^ b, bitboard![B5, C5, H3]);
assert_eq!(a ^ BitBoard::empty(), a);
assert_eq!(BitBoard::empty() ^ BitBoard::empty(), BitBoard::empty());
}
#[test]
fn bitand_assign() {
let mut a = bitboard![C5, G7];
let b = bitboard![B5, G7, H3];
a &= b;
assert_eq!(a, bitboard![G7]);
}
#[test]
fn bitor_assign() {
let mut a = bitboard![C5, G7];
let b = bitboard![B5, G7, H3];
a |= b;
assert_eq!(a, bitboard![B5, C5, G7, H3]);
}
} }