#![allow(dead_code)]
#[allow(dead_code)]
pub fn popcount(x: u64) -> u32 {
x.count_ones()
}
#[allow(dead_code)]
pub fn count_trailing_zeros(x: u64) -> u32 {
if x == 0 {
64
} else {
x.trailing_zeros()
}
}
#[allow(dead_code)]
pub fn count_leading_zeros(x: u64) -> u32 {
x.leading_zeros()
}
#[allow(dead_code)]
pub fn toggle_bit(mask: u64, bit: u32) -> u64 {
mask ^ (1u64 << (bit & 63))
}
#[allow(dead_code)]
pub fn set_bit(mask: u64, bit: u32) -> u64 {
mask | (1u64 << (bit & 63))
}
#[allow(dead_code)]
pub fn clear_bit(mask: u64, bit: u32) -> u64 {
mask & !(1u64 << (bit & 63))
}
#[allow(dead_code)]
pub fn is_bit_set(mask: u64, bit: u32) -> bool {
mask & (1u64 << (bit & 63)) != 0
}
#[allow(dead_code)]
pub fn range_mask(lo: u32, hi: u32) -> u64 {
if lo >= 64 || hi == 0 || lo >= hi {
return 0;
}
let hi = hi.min(64);
let lo = lo.min(63);
if hi >= 64 {
!0u64 << lo
} else {
((1u64 << hi) - 1) & (!0u64 << lo)
}
}
#[allow(dead_code)]
pub fn extract_range(mask: u64, lo: u32, hi: u32) -> u64 {
(mask & range_mask(lo, hi)) >> lo.min(63)
}
#[allow(dead_code)]
pub fn rotate_left(mask: u64, n: u32) -> u64 {
mask.rotate_left(n)
}
#[allow(dead_code)]
pub fn rotate_right(mask: u64, n: u32) -> u64 {
mask.rotate_right(n)
}
#[allow(dead_code)]
pub fn highest_bit(mask: u64) -> Option<u32> {
if mask == 0 {
None
} else {
Some(63 - mask.leading_zeros())
}
}
#[allow(dead_code)]
pub fn lowest_bit(mask: u64) -> Option<u32> {
if mask == 0 {
None
} else {
Some(mask.trailing_zeros())
}
}
#[allow(dead_code)]
pub fn set_bit_indices(mut mask: u64) -> Vec<u32> {
let mut out = Vec::new();
while mask != 0 {
let bit = mask.trailing_zeros();
out.push(bit);
mask &= mask - 1;
}
out
}
#[allow(dead_code)]
pub fn parity(x: u64) -> bool {
!x.count_ones().is_multiple_of(2)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn popcount_basic() {
assert_eq!(popcount(0b1011), 3);
assert_eq!(popcount(0), 0);
assert_eq!(popcount(u64::MAX), 64);
}
#[test]
fn toggle_bit_roundtrip() {
let m = 0u64;
let m2 = toggle_bit(m, 5);
assert!(is_bit_set(m2, 5));
let m3 = toggle_bit(m2, 5);
assert!(!is_bit_set(m3, 5));
}
#[test]
fn set_and_clear_bit() {
let m = set_bit(0, 10);
assert!(is_bit_set(m, 10));
let m2 = clear_bit(m, 10);
assert!(!is_bit_set(m2, 10));
}
#[test]
fn range_mask_basic() {
let m = range_mask(0, 4);
assert_eq!(m, 0b1111);
}
#[test]
fn range_mask_empty() {
assert_eq!(range_mask(5, 5), 0);
assert_eq!(range_mask(10, 5), 0);
}
#[test]
fn highest_lowest_bit() {
let m = 0b10100u64;
assert_eq!(highest_bit(m), Some(4));
assert_eq!(lowest_bit(m), Some(2));
}
#[test]
fn set_bit_indices_correct() {
let m = 0b1011u64;
let indices = set_bit_indices(m);
assert_eq!(indices, vec![0, 1, 3]);
}
#[test]
fn rotate_left_basic() {
let m = 1u64;
assert_eq!(rotate_left(m, 4), 16);
}
#[test]
fn parity_even_odd() {
assert!(!parity(0b1100));
assert!(parity(0b1110));
}
#[test]
fn count_trailing_zeros_zero() {
assert_eq!(count_trailing_zeros(0), 64);
}
}