use crate::Bits;
use crate::IntoBits;
macro_rules! mask {
($Type:ty, $Range:expr) => {
(((1 as $Type) << $Range.end()) - ((1 as $Type) << $Range.start()))
| ((1 as $Type) << $Range.end())
};
}
pub trait BitsOps<T> {
#[must_use = "set function dosen't modify the self in place, you should assign to it explicitly"]
fn set(&self) -> T;
#[must_use = "clr function dosen't modify the self in place, you should assign to it explicitly"]
fn clr(&self) -> T;
#[must_use = "revert function dosen't modify the self in place, you should assign to it explicitly"]
fn revert(&self) -> T;
#[must_use = "write function dosen't modify the self in place, you should assign to it explicitly"]
fn write(&self, value: T) -> T;
fn read(&self) -> T;
fn is_clr(&self) -> bool;
fn is_set(&self) -> bool;
fn count_ones(&self) -> u32;
fn msb(&self) -> bool;
fn lsb(&self) -> bool;
}
macro_rules! impl_bitsops {
($($Type:ty) *) => {
$(impl BitsOps<$Type> for Bits<$Type> {
#[inline]
fn msb(&self) -> bool {
self.value.bits(*self.range.end() ..= *self.range.end()).is_set()
}
#[inline]
fn lsb(&self) -> bool {
self.value.bits(*self.range.start() ..= *self.range.start()).is_set()
}
#[inline]
fn set(&self) -> $Type {
let mask = mask!($Type, self.range);
self.value | mask
}
#[inline]
fn clr(&self) -> $Type {
let mask = mask!($Type, self.range);
self.value & (!mask)
}
#[inline]
fn revert(&self) -> $Type {
let mask = mask!($Type, self.range);
self.value ^ mask
}
#[inline]
fn write(&self, value: $Type) -> $Type {
let mask = mask!($Type, self.range);
(self.value & (!mask)) | ((value << self.range.start()) & mask)
}
#[inline]
fn read(&self) -> $Type {
let mask = mask!($Type, self.range);
(self.value & mask) >> self.range.start()
}
#[inline]
fn is_clr(&self) -> bool {
self.read() == 0
}
#[inline]
fn is_set(&self) -> bool {
let mask = mask!($Type, self.range);
(self.value & mask) == mask
}
#[inline]
fn count_ones(&self) -> u32 {
use core::convert::TryInto;
let mut ret = self.read();
let mut i = 1;
while i <= core::mem::size_of::<$Type>() * 4 {
let max = !(0 as $Type);
let div = (1 << i) + 1;
let a:$Type = max / div;
let b:$Type = a << i;
ret = (a & ret) + ((b & ret) >> i);
i = i << 1;
}
ret.try_into().unwrap()
}
})*
};
}
impl_bitsops!(u8 u16 u32 u64 u128 usize);
#[inline]
fn __count_ones_u8(data: u8) -> u32 {
let x1 = data & 0b0101_0101;
let x2 = (data & 0b1010_1010) >> 1;
let y = x1 + x2;
let y1 = (y & 0b1100_1100) >> 2;
let y2 = y & 0b0011_0011;
let z = y1 + y2;
let z1 = z & 0b0000_1111;
let z2 = (z & 0b1111_0000) >> 4;
return (z2 + z1) as u32;
}
#[no_mangle]
fn __count_ones_u16(data: u16) -> u32 {
let x1 = __count_ones_u8(data.to_ne_bytes()[1]);
let x2 = __count_ones_u8(data.to_ne_bytes()[0]);
x1 + x2
}