pub type Bitboard = u64; /// Print bitboard on screen in the same way squares appear in memory /// (i.e the board is actually flipped along X) pub fn print(bb: &Bitboard) { for index in 0..64 { print!("{}", if bb >> index & 1 == 1 { "1" } else { "." }); if (index + 1) % 8 == 0 { println!(); } } return println!(); } /// Return bitboard cardinality, aka number of elements in the set pub fn pop_count(bb: &Bitboard) -> u8 { if bb == &0u64 { return 0; } return pop_count(&(bb >> 1)) + (bb & 1) as u8; } /// Return Bitboard with only Least Single Bit pub fn ls1b(bb: &Bitboard) -> u64 { bb & !(bb - 1) } /// Log base 2 (aka Trailing Zero Count) /// /// WARNING: Only works for SINGLE Bitboards /// Useful for calculating bit-index of LS1B pub fn bitscan(bb: &Bitboard) -> u8 { debug_assert!(pop_count(bb) == 1, "Bitscan only works for SINGLE Bitboards!"); pop_count(&(bb - 1)) } #[cfg(test)] mod tests { use super::*; #[test] fn test_pop_count() { assert_eq!(pop_count(&127), 7); } #[test] fn test_ls1b() { assert_eq!(ls1b(&38), 2); assert_eq!(ls1b(&16), 16); assert_eq!(ls1b(&20), 4); } #[test] fn test_bitscan() { assert_eq!(bitscan(&4), 2); assert_eq!(bitscan(&16), 4); assert_eq!(bitscan(&64), 6); assert_eq!(bitscan(&128), 7); } #[test] #[should_panic(expected = "Bitscan only works for SINGLE Bitboards!")] fn test_bitscan_with_non_single_bb() { bitscan(&5); } }