use crate::std::{cmp::Ordering, iter, ops::BitOr, vec::Vec};
use either::Either;
#[derive(Eq, PartialEq, Clone, Debug, Default)]
pub struct Bitfield {
bits: Vec<u64>,
}
impl From<Vec<u64>> for Bitfield {
fn from(bits: Vec<u64>) -> Bitfield {
Bitfield { bits }
}
}
impl Bitfield {
pub fn new() -> Bitfield {
Bitfield { bits: Vec::new() }
}
pub fn is_blank(&self) -> bool {
self.bits.is_empty()
}
pub fn merge(&mut self, other: &Self) -> &mut Self {
if self.bits.len() < other.bits.len() {
let new_len = other.bits.len();
self.bits.resize(new_len, 0);
}
for (i, word) in other.bits.iter().enumerate() {
self.bits[i] |= word;
}
self
}
pub fn set_bit(&mut self, position: usize) -> &mut Self {
let word_off = position / 64;
let bit_off = position % 64;
if word_off >= self.bits.len() {
let new_len = word_off + 1;
self.bits.resize(new_len, 0);
}
self.bits[word_off] |= 1 << (63 - bit_off);
self
}
#[cfg(test)]
pub fn test_bit(&self, position: usize) -> bool {
let word_off = position / 64;
if word_off >= self.bits.len() {
return false
}
test_bit(self.bits[word_off], position % 64)
}
pub fn iter1s_even(&self) -> impl Iterator<Item = Bit1> + '_ {
self.iter1s(0, 1)
}
pub fn iter1s_odd(&self) -> impl Iterator<Item = Bit1> + '_ {
self.iter1s(1, 1)
}
pub fn iter1s_merged_even<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = Bit1> + 'a {
self.iter1s_merged(other, 0, 1)
}
pub fn iter1s_merged_odd<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = Bit1> + 'a {
self.iter1s_merged(other, 1, 1)
}
fn iter1s(&self, start: usize, step: usize) -> impl Iterator<Item = Bit1> + '_ {
iter1s(self.bits.iter().cloned(), start, step)
}
fn iter1s_merged<'a>(
&'a self,
other: &'a Self,
start: usize,
step: usize,
) -> impl Iterator<Item = Bit1> + 'a {
match self.bits.len().cmp(&other.bits.len()) {
Ordering::Equal => Either::Left(iter1s(
self.bits.iter().zip(&other.bits).map(|(a, b)| a | b),
start,
step,
)),
Ordering::Less => Either::Right(Either::Left(iter1s(
self.bits.iter().chain(iter::repeat(&0)).zip(&other.bits).map(|(a, b)| a | b),
start,
step,
))),
Ordering::Greater => Either::Right(Either::Right(iter1s(
self.bits
.iter()
.zip(other.bits.iter().chain(iter::repeat(&0)))
.map(|(a, b)| a | b),
start,
step,
))),
}
}
}
fn iter1s<'a, I>(iter: I, start: usize, step: usize) -> impl Iterator<Item = Bit1> + 'a
where
I: Iterator<Item = u64> + 'a,
{
debug_assert!(start < 64 && step < 7);
let steps = (64 >> step) - (start >> step);
iter.enumerate().flat_map(move |(i, word)| {
let n = if word == 0 { 0 } else { steps };
(0..n).filter_map(move |j| {
let bit_pos = start + (j << step);
if test_bit(word, bit_pos) {
Some(Bit1 { position: i * 64 + bit_pos })
} else {
None
}
})
})
}
fn test_bit(word: u64, position: usize) -> bool {
let mask = 1 << (63 - position);
word & mask == mask
}
impl BitOr<&Bitfield> for Bitfield {
type Output = Bitfield;
fn bitor(mut self, rhs: &Bitfield) -> Self::Output {
self.merge(rhs);
self
}
}
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
pub struct Bit1 {
pub position: usize,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::std::iter;
use quickcheck::*;
impl Arbitrary for Bitfield {
fn arbitrary(g: &mut Gen) -> Bitfield {
let n = usize::arbitrary(g) % g.size();
let mut b = iter::from_fn(|| Some(u64::arbitrary(g))).take(n).collect::<Vec<_>>();
while let Some(0) = b.last() {
b.pop();
}
Bitfield::from(b)
}
}
#[test]
fn set_bit() {
fn prop(mut a: Bitfield, idx: usize) -> bool {
let idx = idx.min(1 << 24);
a.set_bit(idx).test_bit(idx)
}
quickcheck(prop as fn(_, _) -> _)
}
#[test]
fn bitor() {
fn prop(a: Bitfield, b: Bitfield) -> bool {
let c = a.clone() | &b;
let mut c_bits = c.iter1s(0, 0);
c_bits.all(|bit| a.test_bit(bit.position) || b.test_bit(bit.position))
}
quickcheck(prop as fn(_, _) -> _)
}
#[test]
fn bitor_commutative() {
fn prop(a: Bitfield, b: Bitfield) -> bool {
a.clone() | &b == b | &a
}
quickcheck(prop as fn(_, _) -> _)
}
#[test]
fn bitor_associative() {
fn prop(a: Bitfield, b: Bitfield, c: Bitfield) -> bool {
(a.clone() | &b) | &c == a | &(b | &c)
}
quickcheck(prop as fn(_, _, _) -> _)
}
#[test]
fn iter1s() {
fn all(a: Bitfield) {
let mut b = Bitfield::new();
for Bit1 { position } in a.iter1s(0, 0) {
b.set_bit(position);
}
assert_eq!(a, b);
}
fn even_odd(a: Bitfield) {
let mut b = Bitfield::new();
for Bit1 { position } in a.iter1s_even() {
assert!(!b.test_bit(position));
assert!(position % 2 == 0);
b.set_bit(position);
}
for Bit1 { position } in a.iter1s_odd() {
assert!(!b.test_bit(position));
assert!(position % 2 == 1);
b.set_bit(position);
}
assert_eq!(a, b);
}
quickcheck(all as fn(_));
quickcheck(even_odd as fn(_));
}
#[test]
fn iter1s_merged() {
fn all(mut a: Bitfield, b: Bitfield) {
let mut c = Bitfield::new();
for bit1 in a.iter1s_merged(&b, 0, 0) {
c.set_bit(bit1.position);
}
assert_eq!(&c, a.merge(&b))
}
fn even_odd(mut a: Bitfield, b: Bitfield) {
let mut c = Bitfield::new();
for Bit1 { position } in a.iter1s_merged_even(&b) {
assert!(!c.test_bit(position));
assert!(position % 2 == 0);
c.set_bit(position);
}
for Bit1 { position } in a.iter1s_merged_odd(&b) {
assert!(!c.test_bit(position));
assert!(position % 2 == 1);
c.set_bit(position);
}
assert_eq!(&c, a.merge(&b));
}
quickcheck(all as fn(_, _));
quickcheck(even_odd as fn(_, _));
}
}