use crate::Float;
use malachite_base::num::arithmetic::traits::Pow;
use malachite_base::num::basic::traits::Zero;
use malachite_base::num::conversion::traits::{Digits, ExactFrom};
use malachite_base::num::factorization::traits::Primes;
use malachite_base::rounding_modes::RoundingMode;
use malachite_nz::natural::Natural;
use malachite_q::Rational;
use std::cmp::Ordering::{self, *};
pub fn digit_constant_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::from(1u32), den);
let (f_lo, _) = Float::from_rational_prec_round(lo.clone(), prec, rm);
let (f_hi, _) = Float::from_rational_prec_round(hi.clone(), prec, rm);
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 liouvilles_digits_naive() -> impl Iterator<Item = u64> {
let mut position = 0u64;
let mut factorial = 1u64;
let mut index = 1u64;
std::iter::from_fn(move || {
position += 1;
Some(if position == factorial {
index += 1;
factorial = factorial.saturating_mul(index);
1
} else {
0
})
})
}
pub fn liouvilles_constant_base_prec_round_naive(
base: u64,
prec: u64,
rm: RoundingMode,
) -> (Float, Ordering) {
digit_constant_prec_round_naive(liouvilles_digits_naive(), base, prec, rm)
}
pub fn champernowne_constant_base_prec_round_naive(
base: u64,
prec: u64,
rm: RoundingMode,
) -> (Float, Ordering) {
digit_constant_prec_round_naive(
(1u64..).flat_map(move |n| n.to_digits_desc(&base)),
base,
prec,
rm,
)
}
pub fn copeland_erdos_constant_base_prec_round_naive(
base: u64,
prec: u64,
rm: RoundingMode,
) -> (Float, Ordering) {
digit_constant_prec_round_naive(
u64::primes().flat_map(move |p| p.to_digits_desc(&base)),
base,
prec,
rm,
)
}