use smallvec::SmallVec;
#[cfg(feature = "logicsim_unstable")]
pub fn word_mask_64(index: usize) -> (usize, u64) {
let word = unsafe { std::intrinsics::unchecked_div(index, 64) };
let mask = unsafe {
std::intrinsics::unchecked_shl(1u64, std::intrinsics::unchecked_rem(index, 64) as u64)
};
(word, mask)
}
#[cfg(not(feature = "logicsim_unstable"))]
pub fn word_mask_64(index: usize) -> (usize, u64) {
let word = index / 64;
let mask = 1 << (index % 64);
(word, mask)
}
pub fn word_mask_8(index: usize) -> (usize, u8) {
let word = index / 8;
let mask = 1 << (index % 8);
(word, mask)
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct BitIter {
item: SmallVec<[u8; 8]>,
i: u16,
}
impl BitIter {
pub fn new<T: Copy + Sized + 'static>(item: T) -> Self {
let byte_size = std::mem::size_of::<T>();
let bit_size = byte_size * 8;
assert!(
bit_size <= std::u16::MAX as usize,
"Item too big to bit iterate, If this is ever hit change the i to u32, bit_size: {}",
bit_size
);
let as_u8s: &[u8] =
unsafe { std::slice::from_raw_parts(std::mem::transmute(&item), byte_size) };
Self {
item: SmallVec::from_slice(as_u8s),
i: 0,
}
}
pub fn is_zero(&self) -> bool {
for byte in &self.item {
if *byte != 0 {
return false;
}
}
true
}
}
impl Iterator for BitIter {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
if self.i == self.item.len() as u16 * 8 {
return None;
}
let (word_index, word_mask) = word_mask_8(self.i as usize);
let result = self.item[word_index] & word_mask != 0;
self.i += 1;
Some(result)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_u8() {
let n = 0b101u8;
let result = [true, false, true];
let mut iterations = 0;
for (i, set) in BitIter::new(n).enumerate() {
assert_eq!(set, *result.get(i).unwrap_or(&false));
iterations = iterations + 1;
}
assert_eq!(iterations, std::mem::size_of_val(&n) * 8);
}
#[test]
fn test_u128() {
let n = 0b110u128;
let result = [false, true, true];
let mut iterations = 0;
for (i, set) in BitIter::new(n).enumerate() {
assert_eq!(set, *result.get(i).unwrap_or(&false));
iterations = iterations + 1;
}
assert_eq!(iterations, std::mem::size_of_val(&n) * 8);
}
#[test]
fn test_struct() {
#[repr(C)]
#[derive(Copy, Clone)]
struct Example {
a: u8,
b: u8,
}
let n = Example { a: 0b1011, b: 0b1 };
let result = [true, true, false, true, false, false, false, false, true];
let mut iterations = 0;
for (i, set) in BitIter::new(n).enumerate() {
iterations = iterations + 1;
assert_eq!(set, *result.get(i).unwrap_or(&false));
}
assert_eq!(iterations, std::mem::size_of_val(&n) * 8);
}
#[test]
fn test_is_zero() {
assert_eq!(BitIter::new(8).is_zero(), false);
assert_eq!(BitIter::new(0u8).is_zero(), true);
assert_eq!(BitIter::new(0i16).is_zero(), true);
assert_eq!(BitIter::new(0f32).is_zero(), true);
assert_eq!(BitIter::new(12.2f64).is_zero(), false);
assert_eq!(BitIter::new(-0f64).is_zero(), false);
}
}