aboutsummaryrefslogtreecommitdiff
path: root/src/bitboard.rs
blob: a4b54e54b9eb32a2e6afd3b47822bd6025ca383a (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
78
79
80
81
82
83
84
85
86
87
88
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) {
    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 == 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 {
    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)
}

/// Aliases to board square indexes
#[allow(dead_code)]
enum Square {
  A1, B1, C1, D1, E1, F1, G1, H1,
  A2, B2, C2, D2, E2, F2, G2, H2,
  A3, B3, C3, D3, E3, F3, G3, H3,
  A4, B4, C4, D4, E4, F4, G4, H4,
  A5, B5, C5, D5, E5, F5, G5, H5,
  A6, B6, C6, D6, E6, F6, G6, H6,
  A7, B7, C7, D7, E7, F7, G7, H7,
  A8, B8, C8, D8, E8, F8, G8, H8,
}

#[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);
    }

    #[test]
    fn test_square_enum() {
        assert_eq!(Square::A1 as u8, 0);
        assert_eq!(Square::F1 as u8, 5);
        assert_eq!(Square::H8 as u8, 63);
    }
}