#[derive(Debug, Clone)]
pub struct FastCounting {
genes: Vec<u64>,
length: usize, length_words: usize, }
impl FastCounting {
pub fn new(length: usize) -> Self {
let length_words = length.div_ceil(64); Self {
genes: vec![0; length_words],
length,
length_words,
}
}
#[inline(always)]
pub fn get(&self, index: usize) -> bool {
debug_assert!(index < self.length);
let word = index >> 6; let bit = index & 63; (self.genes[word] & (1u64 << bit)) != 0
}
#[inline(always)]
pub fn set(&mut self, index: usize, value: bool) {
debug_assert!(index < self.length);
let word = index >> 6; let bit = index & 63;
if value {
self.genes[word] |= 1u64 << bit;
} else {
self.genes[word] &= !(1u64 << bit);
}
}
#[inline]
pub fn count_ones(&self) -> usize {
self.genes
.iter()
.map(|&word| word.count_ones() as usize)
.sum()
}
#[inline]
pub fn count_xor(&self, other: &Self) -> usize {
debug_assert_eq!(self.length_words, other.length_words);
self.genes
.iter()
.zip(other.genes.iter())
.map(|(&a, &b)| (a ^ b).count_ones() as usize)
.sum()
}
pub fn length(&self) -> usize {
self.length
}
pub fn length_words(&self) -> usize {
self.length_words
}
pub fn genes(&self) -> &[u64] {
&self.genes
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fast_counting() {
let mut fc = FastCounting::new(100);
fc.set(0, true);
fc.set(50, true);
fc.set(99, true);
assert!(fc.get(0));
assert!(fc.get(50));
assert!(fc.get(99));
assert!(!fc.get(1));
assert_eq!(fc.count_ones(), 3);
}
#[test]
fn test_count_xor() {
let mut fc1 = FastCounting::new(100);
let mut fc2 = FastCounting::new(100);
fc1.set(0, true);
fc1.set(50, true);
fc2.set(0, true);
fc2.set(99, true);
assert_eq!(fc1.count_xor(&fc2), 2);
}
}