use crate::integer::Integer;
use crate::natural::Natural;
use crate::natural::logic::bit_iterable::NaturalBitIterator;
use core::ops::Index;
use malachite_base::num::logic::traits::{BitAccess, BitIterable};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct NegativeBitIterator<'a> {
pub(crate) bits: NaturalBitIterator<'a>,
i: u64,
j: u64,
first_true_index: Option<u64>,
}
impl Iterator for NegativeBitIterator<'_> {
type Item = bool;
fn next(&mut self) -> Option<bool> {
let previous_i = self.i;
self.bits.next().map(|bit| {
self.i += 1;
if let Some(first_true_index) = self.first_true_index {
if previous_i <= first_true_index {
bit
} else {
!bit
}
} else {
if bit {
self.first_true_index = Some(previous_i);
}
bit
}
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.bits.size_hint()
}
}
impl DoubleEndedIterator for NegativeBitIterator<'_> {
fn next_back(&mut self) -> Option<bool> {
let previous_j = self.j;
self.bits.next_back().map(|bit| {
if self.j != 0 {
self.j -= 1;
}
if self.first_true_index.is_none() {
let mut i = 0;
while !self.bits[i] {
i += 1;
}
self.first_true_index = Some(i);
}
let first_true_index = self.first_true_index.unwrap();
if previous_j <= first_true_index {
bit
} else {
!bit
}
})
}
}
impl ExactSizeIterator for NegativeBitIterator<'_> {}
trait SignExtendedBitIterator: DoubleEndedIterator<Item = bool> {
const EXTENSION: bool;
fn needs_sign_extension(&self) -> bool;
fn iterate_forward(&mut self, extension_checked: &mut bool) -> Option<bool> {
let next = self.next();
if next.is_none() {
if *extension_checked {
None
} else {
*extension_checked = true;
if self.needs_sign_extension() {
Some(Self::EXTENSION)
} else {
None
}
}
} else {
next
}
}
fn iterate_backward(&mut self, extension_checked: &mut bool) -> Option<bool> {
if !*extension_checked {
*extension_checked = true;
if self.needs_sign_extension() {
return Some(Self::EXTENSION);
}
}
self.next_back()
}
}
impl SignExtendedBitIterator for NaturalBitIterator<'_> {
const EXTENSION: bool = false;
fn needs_sign_extension(&self) -> bool {
self[self.significant_bits - 1]
}
}
impl SignExtendedBitIterator for NegativeBitIterator<'_> {
const EXTENSION: bool = true;
fn needs_sign_extension(&self) -> bool {
let mut i = 0;
while !self.bits[i] {
i += 1;
}
let last_bit_index = self.bits.significant_bits - 1;
if i == last_bit_index {
!self.bits[last_bit_index]
} else {
self.bits[last_bit_index]
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum IntegerBitIterator<'a> {
Zero,
Positive(NaturalBitIterator<'a>, bool),
Negative(NegativeBitIterator<'a>, bool),
}
impl Iterator for IntegerBitIterator<'_> {
type Item = bool;
fn next(&mut self) -> Option<bool> {
match self {
Self::Zero => None,
Self::Positive(bits, extension_checked) => bits.iterate_forward(extension_checked),
Self::Negative(bits, extension_checked) => bits.iterate_forward(extension_checked),
}
}
}
impl DoubleEndedIterator for IntegerBitIterator<'_> {
fn next_back(&mut self) -> Option<bool> {
match self {
Self::Zero => None,
Self::Positive(bits, extension_checked) => bits.iterate_backward(extension_checked),
Self::Negative(bits, extension_checked) => bits.iterate_backward(extension_checked),
}
}
}
impl Index<u64> for IntegerBitIterator<'_> {
type Output = bool;
fn index(&self, index: u64) -> &bool {
let bit = match self {
Self::Zero => false,
Self::Positive(bits, _) => bits.limbs.n.get_bit(index),
Self::Negative(bits, _) => bits.bits.limbs.n.get_bit_neg(index),
};
if bit { &true } else { &false }
}
}
impl Natural {
fn negative_bits(&self) -> NegativeBitIterator<'_> {
assert_ne!(*self, 0, "Cannot get negative bits of 0.");
let bits = self.bits();
NegativeBitIterator {
bits,
first_true_index: None,
i: 0,
j: bits.significant_bits - 1,
}
}
}
impl<'a> BitIterable for &'a Integer {
type BitIterator = IntegerBitIterator<'a>;
fn bits(self) -> IntegerBitIterator<'a> {
if *self == 0 {
IntegerBitIterator::Zero
} else if self.sign {
IntegerBitIterator::Positive(self.abs.bits(), false)
} else {
IntegerBitIterator::Negative(self.abs.negative_bits(), false)
}
}
}