binar 0.1.1

High-performance binary arithmetic.
Documentation
use crate::{BitLength, BitwiseMut, IntoBitIterator};

pub trait BitwisePairViaIter<Other: ?Sized>
where
    Self: BitLength,
    Other: BitLength,
    for<'life> &'life Self: IntoBitIterator,
    for<'life> &'life Other: IntoBitIterator,
{
    #[inline]
    fn dot(&self, other: &Other) -> bool {
        self.iter_bits()
            .zip(other.iter_bits())
            .map(|(a, b)| usize::from(a & b))
            .sum::<usize>()
            % 2
            == 1
    }
    #[inline]
    fn and_weight(&self, other: &Other) -> usize {
        self.iter_bits()
            .zip(other.iter_bits())
            .map(|(a, b)| usize::from(a & b))
            .sum::<usize>()
    }
    #[inline]
    fn or_weight(&self, other: &Other) -> usize {
        self.iter_bits()
            .zip(other.iter_bits())
            .map(|(a, b)| usize::from(a | b))
            .sum::<usize>()
    }
    #[inline]
    fn xor_weight(&self, other: &Other) -> usize {
        self.iter_bits()
            .zip(other.iter_bits())
            .map(|(a, b)| usize::from(a ^ b))
            .sum::<usize>()
    }
}

impl<T: ?Sized, Other: ?Sized> BitwisePairViaIter<Other> for T
where
    Self: BitLength,
    Other: BitLength,
    for<'life> &'life Self: IntoBitIterator<BitIterator: 'life>,
    for<'life> &'life Other: IntoBitIterator<BitIterator: 'life>,
{
}

fn assert_length_at_least<T1: BitLength + ?Sized, T2: BitLength + ?Sized>(left: &T1, right: &T2) {
    assert!(
        left.bit_len() >= right.bit_len(),
        "Left-hand side ({} bits) to be at least as long as the right-hand side ({} bits)",
        left.bit_len(),
        right.bit_len()
    );
}

pub trait BitwisePairMutViaIter<Other: ?Sized>
where
    Self: BitwiseMut + BitLength,
    Other: BitLength,
    for<'life> &'life Other: IntoBitIterator,
{
    #[inline]
    fn assign(&mut self, other: &Other) {
        assert_length_at_least(self, other);
        for (index, bit) in other.iter_bits().enumerate() {
            self.assign_index(index, bit);
        }
    }
    #[inline]
    fn bitxor_assign(&mut self, other: &Other) {
        assert_length_at_least(self, other);
        for (index, bit) in other.iter_bits().enumerate() {
            if bit {
                self.negate_index(index);
            }
        }
    }
    #[inline]
    fn bitand_assign(&mut self, other: &Other) {
        assert_length_at_least(self, other);
        for (index, bit) in other.iter_bits().enumerate() {
            if !bit {
                self.assign_index(index, false);
            }
        }
    }
    #[inline]
    fn bitor_assign(&mut self, other: &Other) {
        assert_length_at_least(self, other);
        for (index, bit) in other.iter_bits().enumerate() {
            if bit {
                self.assign_index(index, true);
            }
        }
    }
}

impl<Bits: ?Sized, Other: ?Sized> BitwisePairMutViaIter<Other> for Bits
where
    Bits: BitwiseMut + BitLength,
    Other: BitLength,
    for<'life> &'life Other: IntoBitIterator,
{
}