use crate::Float;
use malachite_base::num::arithmetic::traits::Pow;
use malachite_base::num::basic::traits::{One, Zero};
use malachite_base::num::conversion::traits::ExactFrom;
use malachite_base::rounding_modes::RoundingMode;
use malachite_nz::natural::Natural;
use malachite_q::Rational;
use std::cmp::Ordering::{self, *};
use std::iter::repeat;
pub fn non_dyadic_from_digits_prec_round_naive<I: Iterator<Item = u64>>(
mut digits: I,
base: u64,
prec: u64,
rm: RoundingMode,
) -> (Float, Ordering) {
let mut ds: Vec<u64> = Vec::new();
let mut count = prec + 64;
loop {
while u64::exact_from(ds.len()) < count {
ds.push(digits.next().unwrap());
}
let mut num = Natural::ZERO;
for &d in &ds {
num = num * Natural::from(base) + Natural::from(d);
}
let den = Natural::from(base).pow(count);
let lo = Rational::from_naturals(num.clone(), den.clone());
let hi = Rational::from_naturals(num + Natural::ONE, den);
let f_lo = Float::from_rational_prec_round(lo.clone(), prec, rm).0;
let f_hi = Float::from_rational_prec_round(hi.clone(), prec, rm).0;
if f_lo == f_hi {
let q = Rational::exact_from(&f_lo);
if q <= lo {
return (f_lo, Less);
}
if q >= hi {
return (f_lo, Greater);
}
}
count *= 2;
}
}
pub fn non_dyadic_from_bits_prec_round_naive<I: Iterator<Item = bool>>(
bits: I,
prec: u64,
rm: RoundingMode,
) -> (Float, Ordering) {
non_dyadic_from_digits_prec_round_naive(bits.map(u64::from), 2, prec, rm)
}
#[derive(Clone)]
pub struct SparseBits {
b: bool,
k: usize,
j: usize,
}
impl Iterator for SparseBits {
type Item = bool;
fn next(&mut self) -> Option<bool> {
Some(if self.b {
self.b = false;
self.j = self.k;
true
} else {
self.j -= 1;
if self.j == 0 {
self.k += 1;
self.b = true;
}
false
})
}
}
pub const fn sparse_bits() -> SparseBits {
SparseBits {
b: true,
k: 1,
j: 1,
}
}
pub fn non_dyadic_fraction(q: &Rational) -> Rational {
let (n, d) = q.numerator_and_denominator_ref();
Rational::from_naturals(
n * Natural::from(3u32) + Natural::ONE,
(n + d) * Natural::from(3u32),
)
}
pub fn fraction_bits(x: &Rational) -> impl Iterator<Item = bool> + Clone {
fraction_power_of_2_digits(x, 1).map(|d| d == 1)
}
pub fn fraction_digits(x: &Rational, base: u64) -> impl Iterator<Item = u64> + Clone {
x.digits(&Natural::from(base))
.1
.map(|d| u64::exact_from(&d))
.chain(repeat(0))
}
pub fn fraction_power_of_2_digits(
x: &Rational,
log_base: u64,
) -> impl Iterator<Item = u64> + Clone {
x.power_of_2_digits(log_base)
.1
.map(|d| u64::exact_from(&d))
.chain(repeat(0))
}