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);