binar 0.1.1

High-performance binary arithmetic.
Documentation
use binar::vec::AlignedBitVec;
use binar::{BitLength, Bitwise, BitwiseMut, BitwisePair, BitwisePairMut};
use proptest::prelude::*;

proptest! {
    #[test]
    fn from_iter(bits in prop::collection::vec(any::<bool>(), 0..2000)) {
        let bitvec = AlignedBitVec::from_iter(bits.clone());
        let actual: Vec<bool> = bitvec.into_iter().collect();
        assert_eq!(bits.support().collect::<Vec<usize>>(), actual.support().collect::<Vec<usize>>());
    }

    #[test]
    fn index(bits in prop::collection::vec(any::<bool>(), 0..2000)) {
        let bitvec = AlignedBitVec::from_iter(bits.clone());
        for (index, expected) in bits.iter().enumerate() {
            assert_eq!(bitvec.index(index), *expected);
        }
    }

    #[test]
    fn weight(bits in arbitrary_bitvec(2000)) {
        let ones = bits.into_iter().filter(|bit| *bit);
        assert_eq!(ones.count(), bits.weight());
    }

    #[test]
    fn support(bits in arbitrary_bitvec(2000)) {
        let support: Vec<usize> = bits.support().collect();
        assert_eq!(support.len(), bits.weight());
        for index in support {
            assert!(bits.index(index));
        }
    }

    #[test]
    fn assign(bits in prop::collection::vec(any::<bool>(), 0..10)) {
        let mut bitvec = AlignedBitVec::of_length(bits.len());
        for (index, bit) in bits.iter().enumerate() {
            bitvec.assign_index(index, *bit);
        }
        let actual: Vec<bool> = bitvec.into_iter().take(bits.len()).collect();
        assert_eq!(bits, actual);
    }

    #[test]
    fn bitxor_assign((left, right) in equal_length_bitvecs(2000)) {
        let mut xored = left.clone();
        xored.bitxor_assign(&right);
        for (index, result) in xored.into_iter().enumerate() {
            assert_eq!(result, left.index(index) ^ right.index(index));
        }
    }

    #[test]
    fn and_weight((left, right) in equal_length_bitvecs(2000)) {
        let expected = (0..left.bit_len())
            .filter(|&i| left.index(i) && right.index(i))
            .count();
        assert_eq!(left.and_weight(&right), expected);
    }

    #[test]
    fn or_weight((left, right) in equal_length_bitvecs(2000)) {
        let expected = (0..left.bit_len())
            .filter(|&i| left.index(i) || right.index(i))
            .count();
        assert_eq!(left.or_weight(&right), expected);
    }

    #[test]
    fn xor_weight((left, right) in equal_length_bitvecs(2000)) {
        let expected = (0..left.bit_len())
            .filter(|&i| left.index(i) ^ right.index(i))
            .count();
        assert_eq!(left.xor_weight(&right), expected);
    }

    #[test]
    fn dot_product((left, right) in equal_length_bitvecs(2000)) {
        let common_bits = (0..left.bit_len())
            .filter(|&i| left.index(i) && right.index(i))
            .count();
        let expected = (common_bits % 2) == 1;
        assert_eq!(left.dot(&right), expected);
    }

}

fn arbitrary_bitvec(max_length: usize) -> impl Strategy<Value = AlignedBitVec> {
    prop::collection::vec(any::<bool>(), 0..max_length).prop_map(AlignedBitVec::from_iter)
}

fn equal_length_bitvecs(max_length: usize) -> impl Strategy<Value = (AlignedBitVec, AlignedBitVec)> {
    (0..max_length).prop_flat_map(|length| {
        (
            prop::collection::vec(any::<bool>(), length).prop_map(AlignedBitVec::from_iter),
            prop::collection::vec(any::<bool>(), length).prop_map(AlignedBitVec::from_iter),
        )
    })
}