reefer 0.3.0

Optimizing proc-macro for geometric algebra
Documentation
use core::cmp::Ordering;
use core::fmt::Debug;
use core::ops::{
    BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Shl, ShlAssign, Shr, ShrAssign,
};
use num_traits::{ConstOne, ConstZero, One, PrimInt};

pub trait Mask:
    Clone
    + Copy
    + PartialEq
    + Eq
    + Debug
    + Shl<Output = Self>
    + ShlAssign
    + Shr<Output = Self>
    + ShrAssign
    + BitAnd<Output = Self>
    + BitAndAssign
    + BitOr<Output = Self>
    + BitOrAssign
    + BitXor<Output = Self>
    + BitXorAssign
    + ConstZero
    + ConstOne
    + PrimInt
    + Ord
    + One
{
    const BITS: u32;
    fn ones(width: usize, offset: usize) -> Self {
        assert!(
            width + offset <= Self::BITS as usize,
            "width + offset exceed bit size of mask",
        );
        match width.cmp(&(Self::BITS as usize)) {
            Ordering::Less => ((Self::ONE << width) - Self::ONE) << offset,
            Ordering::Equal => !Self::ZERO,
            Ordering::Greater => panic!("Width exceeds bit size"),
        }
    }
    fn parity(&self) -> bool;
    #[allow(dead_code)]
    fn sym_diff(self, other: Self) -> Self;
}

macro_rules! impl_mask_for_unsigned {
    ($($ty:ty),*) => {
        $(impl crate::clifford::mask::Mask for $ty {
            const BITS: u32 = <$ty>::BITS;
            #[inline]
            fn parity(&self) -> bool {
                self.count_ones() & 1 == 1
            }
            #[inline]
            fn sym_diff(self, other: Self) -> Self {
                self ^ other
            }
        })*
    };
}

impl_mask_for_unsigned!(u8, u16, u32, u64, u128);