static POPCNT8: &'static [u8] = &[
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
];
static DEBRUIJ_T: &'static [u8] = &[
0, 47, 1, 56, 48, 27, 2, 60,
57, 49, 41, 37, 28, 16, 3, 61,
54, 58, 35, 52, 50, 42, 21, 44,
38, 32, 29, 23, 17, 11, 4, 62,
46, 55, 26, 59, 40, 36, 15, 53,
34, 51, 20, 43, 31, 22, 10, 45,
25, 39, 14, 33, 19, 30, 9, 24,
13, 18, 8, 12, 7, 6, 5, 63
];
const DEBRUIJ_M: u64 = 0x03f7_9d71_b4cb_0a89;
#[inline(always)]
pub fn popcount64(x: u64) -> u8 {
popcount_rust(x)
}
#[inline(always)]
pub fn bit_scan_forward(bits: u64) -> u8 {
assert_ne!(bits, 0);
unsafe {
*DEBRUIJ_T.get_unchecked((((bits ^ bits.wrapping_sub(1)).wrapping_mul(DEBRUIJ_M)).wrapping_shr(58)) as usize)
}
}
#[inline(always)]
pub fn bit_scan_forward_rust_trailing(bits: u64) -> u8 {
assert_ne!(bits, 0);
bits.trailing_zeros() as u8
}
#[inline(always)]
pub fn bit_scan_reverse(mut bb: u64) -> u8 {
assert_ne!(bb, 0);
bb |= bb >> 1;
bb |= bb >> 2;
bb |= bb >> 4;
bb |= bb >> 8;
bb |= bb >> 16;
bb |= bb >> 32;
unsafe {
*DEBRUIJ_T.get_unchecked((bb.wrapping_mul(DEBRUIJ_M)).wrapping_shr(58) as usize)
}
}
#[inline(always)]
pub fn more_than_one(x: u64) -> bool {
(x & (x.wrapping_sub(1))) != 0
}
#[inline(always)]
pub fn lsb(bits: u64) -> u64 {
(1 as u64).wrapping_shl(bits.trailing_zeros())
}
#[inline]
pub fn popcount_table(x: u64) -> u8 {
let x = x as usize;
if x == 0 {
return 0;
}
if x & (x.wrapping_sub(1)) == 0 {
return 1;
}
POPCNT8[x >> 56] + POPCNT8[(x >> 48) & 0xFF] + POPCNT8[(x >> 40) & 0xFF] +
POPCNT8[(x >> 32) & 0xFF] + POPCNT8[(x >> 24) & 0xFF] + POPCNT8[(x >> 16) & 0xFF] +
POPCNT8[(x >> 8) & 0xFF] + POPCNT8[x & 0xFF]
}
#[inline(always)]
pub fn popcount_rust(x: u64) -> u8 {
x.count_ones() as u8
}
#[inline(always)]
pub fn diff(x: u8, y: u8) -> u8 {
if x < y {
y - x
} else {
x - y
}
}
pub fn msb(x: u64) -> u64 {
(1 as u64).wrapping_shl(63 - x.leading_zeros())
}
pub fn reverse_bytes(b: u64) -> u64 {
let mut m: u64 = 0;
m |= (reverse_byte(((b >> 56) & 0xFF) as u8) as u64) << 56;
m |= (reverse_byte(((b >> 48) & 0xFF) as u8) as u64) << 48;
m |= (reverse_byte(((b >> 40) & 0xFF) as u8) as u64) << 40;
m |= (reverse_byte(((b >> 32) & 0xFF) as u8) as u64) << 32;
m |= (reverse_byte(((b >> 24) & 0xFF) as u8) as u64) << 24;
m |= (reverse_byte(((b >> 16) & 0xFF) as u8) as u64) << 16;
m |= (reverse_byte(((b >> 8) & 0xFF) as u8) as u64) << 8;
m |= reverse_byte((b & 0xFF) as u8) as u64;
m
}
#[inline]
pub fn reverse_byte(b: u8) -> u8 {
let m: u8 = ((0b0000_0001 & b) << 7) | ((0b0000_0010 & b) << 5) | ((0b0000_0100 & b) << 3) |
((0b0000_1000 & b) << 1) |
((0b0001_0000 & b) >> 1) | ((0b0010_0000 & b) >> 3) |
((0b0100_0000 & b) >> 5) | ((0b1000_0000 & b) >> 7);
m
}
pub fn string_u64(input: u64) -> String {
let mut s = String::new();
let format_in = format_u64(input);
for x in 0..8 {
let slice = &format_in[x * 8..((x * 8) + 8)];
s += slice;
s += "\n";
}
s
}
fn format_u64(input: u64) -> String {
format!("{:064b}", input)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bit_scan() {
assert_eq!(bit_scan_forward(2), 1);
assert_eq!(bit_scan_forward(4), 2);
assert_eq!(bit_scan_forward(8), 3);
assert_eq!(bit_scan_forward(16), 4);
assert_eq!(bit_scan_forward(32), 5);
assert_eq!(bit_scan_forward(31), 0);
assert_eq!(bit_scan_forward(0b000000000000001), 0);
assert_eq!(bit_scan_forward(0b000000000000010), 1);
assert_eq!(bit_scan_forward(0b110011100000010), 1);
assert_eq!(bit_scan_forward(0b110011100000010), 1);
}
#[test]
fn msb_t() {
assert_eq!(msb(0b0011),0b0010);
}
#[test]
fn popcount_t() {
assert_eq!(popcount64(0b000000000000000), 0);
assert_eq!(popcount64(0b11111100000001), 7);
assert_eq!(popcount64(0b1000010000), 2);
assert_eq!(popcount64(0xFFFFFFFF), 32);
assert_eq!(popcount64(0x55555555), 16);
}
#[test]
fn lsb_t() {
assert_eq!(lsb(0b110011100000010), 0b10);
assert_eq!(lsb(0b1010000000000000), 0b10000000000000);
assert_eq!(lsb(0b11001110000), 0b10000);
assert_eq!(lsb(0b100001000000), 0b1000000);
assert_eq!(lsb(0b1), 0b1);
}
}