From 620701057d461fee657407e849d563cbe5d838a3 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 21 Jan 2024 09:14:02 -0800 Subject: [PATCH] [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. --- board/src/bitboard/bitboard.rs | 71 ++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/board/src/bitboard/bitboard.rs b/board/src/bitboard/bitboard.rs index 070f43f..6480e99 100644 --- a/board/src/bitboard/bitboard.rs +++ b/board/src/bitboard/bitboard.rs @@ -4,7 +4,7 @@ use super::library::{library, FILES, RANKS}; use super::LeadingBitScanner; use crate::{square::Direction, Square}; use std::fmt; -use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not}; +use std::ops::Not; #[derive(Clone, Copy, Eq, Hash, PartialEq)] pub(crate) struct BitBoard(pub(super) u64); @@ -156,39 +156,49 @@ impl fmt::Debug for BitBoard { } 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) => { - impl $trait_type<$right_type> for $left_type { + impl std::ops::$trait_type<$right_type> for $left_type { type Output = BitBoard; #[inline] 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 { - ($trait_type:ident, $func_name:ident, $left_type:ty) => { - impl $trait_type for $left_type { + ($trait_type:ident, $func_name:ident, $type:ty) => { + impl std::ops::$trait_type for $type { #[inline] - fn $func_name(&mut self, rhs: Self) { - $trait_type::$func_name(&mut self.0, rhs.0) + fn $func_name(&mut self, rhs: $type) { + 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, &BitBoard); -infix_op!(BitAnd, bitand, &BitBoard, &BitBoard); +infix_op!(BitAnd, bitand, BitBoard); +infix_op!(BitOr, bitor, BitBoard); +infix_op!(BitXor, bitxor, BitBoard); assign_op!(BitAndAssign, bitand_assign, BitBoard); assign_op!(BitOrAssign, bitor_assign, BitBoard); - -infix_op!(BitOr, bitor, BitBoard, BitBoard); -infix_op!(BitOr, bitor, BitBoard, &BitBoard); -infix_op!(BitOr, bitor, &BitBoard, &BitBoard); +assign_op!(BitXorAssign, bitxor_assign, BitBoard); impl Not for BitBoard { type Output = BitBoard; @@ -232,13 +242,12 @@ impl BitBoardBuilder { #[cfg(test)] mod tests { use super::*; - use crate::Square; + use crate::{bitboard, Square}; #[test] fn display_and_debug() { let bb = BitBoard::file(0) | BitBoard::file(3) | BitBoard::rank(7) | BitBoard::rank(4); println!("{}", &bb); - println!("{:?}", &bb); } #[test] @@ -302,4 +311,34 @@ mod tests { 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]); + } }