blob: 1d6d0bcdd1e6be8e3a68f12c26cf21569f49e150 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
/// Finite set of up to 64 bits representing chess board squares
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)
#[allow(dead_code)]
pub fn print(bb: Bitboard) {
println!();
for rank in (0..8).rev() {
print!("{}|", rank + 1);
for file in 0..8 {
let index = rank * 8 + file;
print!("{}", if bb >> index & 1 == 1 { "⚫" } else { ". " });
if file == 7 {
println!();
}
}
}
return println!(" a b c d e f g h");
}
/// Return bitboard cardinality, aka number of elements in the set
pub fn pop_count(bb: Bitboard) -> u8 {
if bb == 0 {
return 0;
}
return pop_count(bb >> 1) + (bb & 1) as u8;
}
/// Return Bitboard with only Least Single Bit
pub fn ls1b(bb: Bitboard) -> u64 {
if bb == 0 {
return 0
}
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);
}
}
|