use crate::num::basic::signeds::PrimitiveSigned;
use crate::num::basic::unsigneds::PrimitiveUnsigned;
use crate::num::conversion::traits::{ExactFrom, WrappingFrom};
use crate::num::logic::traits::BitIterable;
use core::cmp::Ordering::*;
use core::cmp::min;
use core::marker::PhantomData;
use core::ops::Index;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct PrimitiveUnsignedBitIterator<T: PrimitiveUnsigned> {
pub(crate) value: T,
pub(crate) remaining: usize,
pub(crate) i_mask: T,
pub(crate) j_mask: T,
}
impl<T: PrimitiveUnsigned> Iterator for PrimitiveUnsignedBitIterator<T> {
type Item = bool;
fn next(&mut self) -> Option<bool> {
if self.remaining != 0 {
let bit = self.value & self.i_mask != T::ZERO;
self.i_mask <<= 1;
self.remaining -= 1;
Some(bit)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T: PrimitiveUnsigned> DoubleEndedIterator for PrimitiveUnsignedBitIterator<T> {
fn next_back(&mut self) -> Option<bool> {
if self.remaining != 0 {
let bit = self.value & self.j_mask != T::ZERO;
self.j_mask >>= 1;
self.remaining -= 1;
Some(bit)
} else {
None
}
}
}
impl<T: PrimitiveUnsigned> ExactSizeIterator for PrimitiveUnsignedBitIterator<T> {}
impl<T: PrimitiveUnsigned> Index<u64> for PrimitiveUnsignedBitIterator<T> {
type Output = bool;
fn index(&self, index: u64) -> &bool {
if self.value.get_bit(index) {
&true
} else {
&false
}
}
}
fn bits_unsigned<T: PrimitiveUnsigned>(x: T) -> PrimitiveUnsignedBitIterator<T> {
let significant_bits = x.significant_bits();
PrimitiveUnsignedBitIterator {
value: x,
remaining: usize::exact_from(significant_bits),
i_mask: T::ONE,
j_mask: T::power_of_2(significant_bits.saturating_sub(1)),
}
}
macro_rules! impl_bit_iterable_unsigned {
($t:ident) => {
impl BitIterable for $t {
type BitIterator = PrimitiveUnsignedBitIterator<$t>;
#[inline]
fn bits(self) -> PrimitiveUnsignedBitIterator<$t> {
bits_unsigned(self)
}
}
};
}
apply_to_unsigneds!(impl_bit_iterable_unsigned);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct PrimitiveSignedBitIterator<U: PrimitiveUnsigned, S: PrimitiveSigned> {
phantom: PhantomData<*const S>,
xs: PrimitiveUnsignedBitIterator<U>,
}
impl<U: PrimitiveUnsigned, S: PrimitiveSigned> Iterator for PrimitiveSignedBitIterator<U, S> {
type Item = bool;
#[inline]
fn next(&mut self) -> Option<bool> {
self.xs.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.xs.size_hint()
}
}
impl<U: PrimitiveUnsigned, S: PrimitiveSigned> DoubleEndedIterator
for PrimitiveSignedBitIterator<U, S>
{
#[inline]
fn next_back(&mut self) -> Option<bool> {
self.xs.next_back()
}
}
impl<U: PrimitiveUnsigned, S: PrimitiveSigned> ExactSizeIterator
for PrimitiveSignedBitIterator<U, S>
{
}
impl<U: PrimitiveUnsigned, S: PrimitiveSigned> Index<u64> for PrimitiveSignedBitIterator<U, S> {
type Output = bool;
fn index(&self, index: u64) -> &bool {
if self.xs[min(index, U::WIDTH - 1)] {
&true
} else {
&false
}
}
}
fn bits_signed<U: PrimitiveUnsigned + WrappingFrom<S>, S: PrimitiveSigned>(
x: S,
) -> PrimitiveSignedBitIterator<U, S> {
let unsigned = U::wrapping_from(x);
let significant_bits = match x.sign() {
Equal => 0,
Greater => unsigned.significant_bits() + 1,
Less => (!unsigned).significant_bits() + 1,
};
PrimitiveSignedBitIterator {
phantom: PhantomData,
xs: PrimitiveUnsignedBitIterator {
value: unsigned,
remaining: usize::exact_from(significant_bits),
i_mask: U::ONE,
j_mask: U::power_of_2(significant_bits.saturating_sub(1)),
},
}
}
macro_rules! impl_bit_iterable_signed {
($u:ident, $s:ident) => {
impl BitIterable for $s {
type BitIterator = PrimitiveSignedBitIterator<$u, $s>;
#[inline]
fn bits(self) -> PrimitiveSignedBitIterator<$u, $s> {
bits_signed::<$u, $s>(self)
}
}
};
}
apply_to_unsigned_signed_pairs!(impl_bit_iterable_signed);