use crate::Rational;
use crate::arithmetic::denominators_in_closed_interval::DenominatorsInClosedRationalInterval;
use crate::arithmetic::traits::DenominatorsInClosedInterval;
use core::iter::{Chain, Once, once};
use core::mem::swap;
use malachite_base::num::arithmetic::traits::{CoprimeWith, UnsignedAbs};
use malachite_base::num::basic::traits::{One, Zero};
use malachite_base::num::conversion::traits::RoundingFrom;
use malachite_base::num::iterators::{RulerSequence, ruler_sequence};
use malachite_base::rounding_modes::RoundingMode::*;
use malachite_base::tuples::exhaustive::{
ExhaustiveDependentPairs, ExhaustiveDependentPairsYsGenerator, exhaustive_dependent_pairs,
};
use malachite_nz::integer::Integer;
use malachite_nz::integer::exhaustive::{
ExhaustiveIntegerRange, ExhaustiveIntegerRangeToInfinity,
ExhaustiveIntegerRangeToNegativeInfinity, exhaustive_integer_range,
exhaustive_integer_range_to_infinity, exhaustive_integer_range_to_negative_infinity,
};
use malachite_nz::natural::Natural;
use malachite_nz::natural::exhaustive::{
ExhaustiveNaturalRangeToInfinity, exhaustive_positive_naturals,
};
#[derive(Clone, Debug)]
pub struct ExhaustivePositiveRationals {
pred_pred: Natural,
pred: Natural,
}
impl Iterator for ExhaustivePositiveRationals {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
let mut anm1 = Natural::ZERO;
swap(&mut self.pred_pred, &mut anm1);
swap(&mut self.pred, &mut self.pred_pred);
let k = &anm1 / &self.pred_pred; self.pred = ((k << 1u32) | Natural::ONE) * &self.pred_pred - anm1;
Some(Rational {
sign: true,
numerator: self.pred_pred.clone(),
denominator: self.pred.clone(),
})
}
}
pub const fn exhaustive_positive_rationals() -> ExhaustivePositiveRationals {
ExhaustivePositiveRationals {
pred_pred: Natural::ZERO,
pred: Natural::ONE,
}
}
pub fn exhaustive_non_negative_rationals() -> Chain<Once<Rational>, ExhaustivePositiveRationals> {
once(Rational::ZERO).chain(exhaustive_positive_rationals())
}
#[derive(Clone, Debug)]
pub struct ExhaustiveNegativeRationals {
xs: ExhaustivePositiveRationals,
}
impl Iterator for ExhaustiveNegativeRationals {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
self.xs.next().map(|mut q| {
q.sign = false;
q
})
}
}
pub const fn exhaustive_negative_rationals() -> ExhaustiveNegativeRationals {
ExhaustiveNegativeRationals {
xs: exhaustive_positive_rationals(),
}
}
#[derive(Clone, Debug)]
pub struct ExhaustiveNonzeroRationals {
xs: ExhaustivePositiveRationals,
x: Option<Rational>,
sign: bool,
}
impl Iterator for ExhaustiveNonzeroRationals {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
if self.sign {
self.sign = false;
let mut x = None;
swap(&mut self.x, &mut x);
let mut x = x.unwrap();
x.sign = false;
Some(x)
} else {
self.sign = true;
self.x = self.xs.next();
Some(self.x.clone().unwrap())
}
}
}
pub const fn exhaustive_nonzero_rationals() -> ExhaustiveNonzeroRationals {
ExhaustiveNonzeroRationals {
xs: exhaustive_positive_rationals(),
x: None,
sign: false,
}
}
pub fn exhaustive_rationals() -> Chain<Once<Rational>, ExhaustiveNonzeroRationals> {
once(Rational::ZERO).chain(exhaustive_nonzero_rationals())
}
#[derive(Clone, Debug)]
pub struct RationalsWithDenominator<I: Iterator<Item = Integer>> {
pub(crate) numerators: I,
pub(crate) denominator: Natural,
}
impl<I: Iterator<Item = Integer>> Iterator for RationalsWithDenominator<I> {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
loop {
let n = self.numerators.next()?;
if n.unsigned_abs_ref().coprime_with(&self.denominator) {
return Some(Rational {
sign: n >= 0u32,
numerator: n.unsigned_abs(),
denominator: self.denominator.clone(),
});
}
}
}
}
pub fn exhaustive_rationals_with_denominator_range_to_infinity(
d: Natural,
a: Rational,
) -> RationalsWithDenominator<ExhaustiveIntegerRangeToInfinity> {
assert_ne!(d, 0u32);
RationalsWithDenominator {
numerators: exhaustive_integer_range_to_infinity(
Integer::rounding_from(a * Rational::from(&d), Ceiling).0,
),
denominator: d,
}
}
pub fn exhaustive_rationals_with_denominator_range_to_negative_infinity(
d: Natural,
a: Rational,
) -> RationalsWithDenominator<ExhaustiveIntegerRangeToNegativeInfinity> {
assert_ne!(d, 0u32);
RationalsWithDenominator {
numerators: exhaustive_integer_range_to_negative_infinity(
Integer::rounding_from(a * Rational::from(&d), Floor).0,
),
denominator: d,
}
}
pub fn exhaustive_rationals_with_denominator_range(
d: Natural,
a: Rational,
b: Rational,
) -> RationalsWithDenominator<ExhaustiveIntegerRange> {
assert_ne!(d, 0u32);
assert!(a < b);
let q_d = Rational::from(&d);
let a_i = Integer::rounding_from(a * &q_d, Ceiling).0;
let upper_included = b.denominator_ref() == &d;
let mut b_i = Integer::rounding_from(b * q_d, Floor).0;
if !upper_included {
b_i += Integer::ONE;
}
RationalsWithDenominator {
numerators: exhaustive_integer_range(a_i, b_i),
denominator: d,
}
}
pub fn exhaustive_rationals_with_denominator_inclusive_range(
d: Natural,
a: Rational,
b: Rational,
) -> RationalsWithDenominator<ExhaustiveIntegerRange> {
assert_ne!(d, 0u32);
assert!(a <= b);
let q_d = Rational::from(&d);
let a_i = Integer::rounding_from(a * &q_d, Ceiling).0;
let b_i = Integer::rounding_from(b * q_d, Floor).0 + Integer::ONE;
RationalsWithDenominator {
numerators: exhaustive_integer_range(a_i, b_i),
denominator: d,
}
}
#[derive(Clone, Debug)]
struct ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator {
a: Rational,
}
impl
ExhaustiveDependentPairsYsGenerator<
Natural,
Rational,
RationalsWithDenominator<ExhaustiveIntegerRangeToInfinity>,
> for ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator
{
#[inline]
fn get_ys(&self, d: &Natural) -> RationalsWithDenominator<ExhaustiveIntegerRangeToInfinity> {
exhaustive_rationals_with_denominator_range_to_infinity(d.clone(), self.a.clone())
}
}
#[inline]
const fn exhaustive_rational_range_to_infinity_helper(
a: Rational,
) -> ExhaustiveDependentPairs<
Natural,
Rational,
RulerSequence<usize>,
ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator,
ExhaustiveNaturalRangeToInfinity,
RationalsWithDenominator<ExhaustiveIntegerRangeToInfinity>,
> {
exhaustive_dependent_pairs(
ruler_sequence(),
exhaustive_positive_naturals(),
ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator { a },
)
}
#[derive(Clone, Debug)]
pub struct ExhaustiveRationalRangeToInfinity(
ExhaustiveDependentPairs<
Natural,
Rational,
RulerSequence<usize>,
ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator,
ExhaustiveNaturalRangeToInfinity,
RationalsWithDenominator<ExhaustiveIntegerRangeToInfinity>,
>,
);
impl Iterator for ExhaustiveRationalRangeToInfinity {
type Item = Rational;
#[inline]
fn next(&mut self) -> Option<Rational> {
self.0.next().map(|p| p.1)
}
}
#[inline]
pub const fn exhaustive_rational_range_to_infinity(
a: Rational,
) -> ExhaustiveRationalRangeToInfinity {
ExhaustiveRationalRangeToInfinity(exhaustive_rational_range_to_infinity_helper(a))
}
#[derive(Clone, Debug)]
struct ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator {
a: Rational,
}
impl
ExhaustiveDependentPairsYsGenerator<
Natural,
Rational,
RationalsWithDenominator<ExhaustiveIntegerRangeToNegativeInfinity>,
> for ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator
{
#[inline]
fn get_ys(
&self,
d: &Natural,
) -> RationalsWithDenominator<ExhaustiveIntegerRangeToNegativeInfinity> {
exhaustive_rationals_with_denominator_range_to_negative_infinity(d.clone(), self.a.clone())
}
}
#[inline]
const fn exhaustive_rational_range_to_negative_infinity_helper(
a: Rational,
) -> ExhaustiveDependentPairs<
Natural,
Rational,
RulerSequence<usize>,
ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator,
ExhaustiveNaturalRangeToInfinity,
RationalsWithDenominator<ExhaustiveIntegerRangeToNegativeInfinity>,
> {
exhaustive_dependent_pairs(
ruler_sequence(),
exhaustive_positive_naturals(),
ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator { a },
)
}
#[derive(Clone, Debug)]
pub struct ExhaustiveRationalRangeToNegativeInfinity(
ExhaustiveDependentPairs<
Natural,
Rational,
RulerSequence<usize>,
ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator,
ExhaustiveNaturalRangeToInfinity,
RationalsWithDenominator<ExhaustiveIntegerRangeToNegativeInfinity>,
>,
);
impl Iterator for ExhaustiveRationalRangeToNegativeInfinity {
type Item = Rational;
#[inline]
fn next(&mut self) -> Option<Rational> {
self.0.next().map(|p| p.1)
}
}
#[inline]
pub const fn exhaustive_rational_range_to_negative_infinity(
a: Rational,
) -> ExhaustiveRationalRangeToNegativeInfinity {
ExhaustiveRationalRangeToNegativeInfinity(
exhaustive_rational_range_to_negative_infinity_helper(a),
)
}
#[derive(Clone, Debug)]
struct ExhaustiveRationalsWithDenominatorRangeGenerator {
a: Rational,
b: Rational,
}
impl
ExhaustiveDependentPairsYsGenerator<
Natural,
Rational,
RationalsWithDenominator<ExhaustiveIntegerRange>,
> for ExhaustiveRationalsWithDenominatorRangeGenerator
{
#[inline]
fn get_ys(&self, d: &Natural) -> RationalsWithDenominator<ExhaustiveIntegerRange> {
exhaustive_rationals_with_denominator_range(d.clone(), self.a.clone(), self.b.clone())
}
}
#[inline]
fn exhaustive_rational_range_helper(
a: Rational,
b: Rational,
) -> ExhaustiveDependentPairs<
Natural,
Rational,
RulerSequence<usize>,
ExhaustiveRationalsWithDenominatorRangeGenerator,
DenominatorsInClosedRationalInterval,
RationalsWithDenominator<ExhaustiveIntegerRange>,
> {
exhaustive_dependent_pairs(
ruler_sequence(),
Rational::denominators_in_closed_interval(a.clone(), b.clone()),
ExhaustiveRationalsWithDenominatorRangeGenerator { a, b },
)
}
#[allow(private_interfaces, clippy::large_enum_variant)]
#[derive(Clone, Debug)]
pub enum ExhaustiveRationalRange {
Empty,
Nonempty(
ExhaustiveDependentPairs<
Natural,
Rational,
RulerSequence<usize>,
ExhaustiveRationalsWithDenominatorRangeGenerator,
DenominatorsInClosedRationalInterval,
RationalsWithDenominator<ExhaustiveIntegerRange>,
>,
),
}
impl Iterator for ExhaustiveRationalRange {
type Item = Rational;
#[inline]
fn next(&mut self) -> Option<Rational> {
match self {
Self::Empty => None,
Self::Nonempty(xs) => xs.next().map(|p| p.1),
}
}
}
#[inline]
pub fn exhaustive_rational_range(a: Rational, b: Rational) -> ExhaustiveRationalRange {
if a == b {
ExhaustiveRationalRange::Empty
} else {
ExhaustiveRationalRange::Nonempty(exhaustive_rational_range_helper(a, b))
}
}
#[derive(Clone, Debug)]
struct ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator {
a: Rational,
b: Rational,
}
impl
ExhaustiveDependentPairsYsGenerator<
Natural,
Rational,
RationalsWithDenominator<ExhaustiveIntegerRange>,
> for ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator
{
#[inline]
fn get_ys(&self, d: &Natural) -> RationalsWithDenominator<ExhaustiveIntegerRange> {
exhaustive_rationals_with_denominator_inclusive_range(
d.clone(),
self.a.clone(),
self.b.clone(),
)
}
}
#[inline]
fn exhaustive_rational_inclusive_range_helper(
a: Rational,
b: Rational,
) -> ExhaustiveDependentPairs<
Natural,
Rational,
RulerSequence<usize>,
ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator,
DenominatorsInClosedRationalInterval,
RationalsWithDenominator<ExhaustiveIntegerRange>,
> {
exhaustive_dependent_pairs(
ruler_sequence(),
Rational::denominators_in_closed_interval(a.clone(), b.clone()),
ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator { a, b },
)
}
#[allow(private_interfaces, clippy::large_enum_variant)]
#[derive(Clone, Debug)]
pub enum ExhaustiveRationalInclusiveRange {
Single(bool, Rational),
Many(
ExhaustiveDependentPairs<
Natural,
Rational,
RulerSequence<usize>,
ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator,
DenominatorsInClosedRationalInterval,
RationalsWithDenominator<ExhaustiveIntegerRange>,
>,
),
}
impl Iterator for ExhaustiveRationalInclusiveRange {
type Item = Rational;
#[inline]
fn next(&mut self) -> Option<Rational> {
match self {
Self::Single(done, x) => {
if *done {
None
} else {
*done = true;
Some(x.clone())
}
}
Self::Many(xs) => xs.next().map(|p| p.1),
}
}
}
#[inline]
pub fn exhaustive_rational_inclusive_range(
a: Rational,
b: Rational,
) -> ExhaustiveRationalInclusiveRange {
if a == b {
ExhaustiveRationalInclusiveRange::Single(false, a)
} else {
ExhaustiveRationalInclusiveRange::Many(exhaustive_rational_inclusive_range_helper(a, b))
}
}