use crate::natural::Natural;
use crate::natural::arithmetic::shr::limbs_slice_shr_in_place;
use crate::platform::Limb;
use alloc::vec::Vec;
use itertools::Itertools;
use malachite_base::num::arithmetic::traits::Parity;
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::traits::Zero;
use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
use malachite_base::num::logic::traits::{BitAccess, BitConvertible};
impl BitConvertible for Natural {
fn to_bits_asc(&self) -> Vec<bool> {
let mut bits = Vec::new();
if *self == 0 {
return bits;
}
let limbs = self.limbs();
let last_index = usize::exact_from(self.limb_count()) - 1;
let mut last = limbs[last_index];
for limb in limbs.take(last_index) {
for i in 0..Limb::WIDTH {
bits.push(limb.get_bit(i));
}
}
while last != 0 {
bits.push(last.odd());
last >>= 1;
}
bits
}
fn to_bits_desc(&self) -> Vec<bool> {
let mut bits = self.to_bits_asc();
bits.reverse();
bits
}
fn from_bits_asc<I: Iterator<Item = bool>>(xs: I) -> Self {
Self::from_owned_limbs_asc(
xs.chunks(usize::wrapping_from(Limb::WIDTH))
.into_iter()
.map(Limb::from_bits_asc)
.collect(),
)
}
fn from_bits_desc<I: Iterator<Item = bool>>(xs: I) -> Self {
let mut out = Vec::new();
let mut last_width = 0;
for chunk in &xs.chunks(usize::exact_from(Limb::WIDTH)) {
let mut x = 0;
let mut i = 0;
for bit in chunk {
x <<= 1;
if bit {
x |= 1;
}
i += 1;
}
last_width = i;
out.push(x);
}
match out.len() {
0 => Self::ZERO,
1 => Self::from(out[0]),
_ => {
out.reverse();
if last_width != Limb::WIDTH {
let out_0 = out[0];
out[0] = 0;
limbs_slice_shr_in_place(&mut out, Limb::WIDTH - last_width);
out[0] |= out_0;
}
Self::from_owned_limbs_asc(out)
}
}
}
}