use itertools::Itertools;
use malachite_base::iterators::comparison::is_strictly_ascending;
use malachite_base::iterators::prefix_to_string;
use malachite_base::num::basic::traits::{One, Zero};
use malachite_nz::natural::exhaustive::exhaustive_positive_naturals;
use malachite_nz::natural::Natural;
use malachite_q::arithmetic::traits::DenominatorsInClosedInterval;
use malachite_q::exhaustive::exhaustive_rationals_with_denominator_inclusive_range;
use malachite_q::test_util::generators::{rational_gen, rational_pair_gen_var_3};
use malachite_q::Rational;
use std::str::FromStr;
#[test]
fn test_denominators_in_closed_interval() {
let test = |a, b, out| {
let a = Rational::from_str(a).unwrap();
let b = Rational::from_str(b).unwrap();
assert_eq!(
prefix_to_string(Rational::denominators_in_closed_interval(&a, &b), 20),
out
);
};
test(
"0",
"2",
"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...]",
);
test(
"1/3",
"1/2",
"[2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, ...]",
);
test(
"99/100",
"101/100",
"[1, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, \
117, 118, ...]",
);
test(
"1/1000000000001",
"1/1000000000000",
"[1000000000000, 1000000000001, 3000000000001, 3000000000002, 4000000000001, \
4000000000003, 5000000000001, 5000000000002, 5000000000003, 5000000000004, 6000000000001, \
6000000000005, 7000000000001, 7000000000002, 7000000000003, 7000000000004, 7000000000005, \
7000000000006, 8000000000001, 8000000000003, ...]",
);
test(
"268876667/98914198",
"245850922/78256779",
"[1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, ...]",
);
}
#[test]
#[should_panic]
fn denominators_in_closed_interval_fail_1() {
Rational::denominators_in_closed_interval(&Rational::ONE, &Rational::ONE);
}
#[test]
#[should_panic]
fn denominators_in_closed_interval_fail_2() {
Rational::denominators_in_closed_interval(&Rational::ONE, &Rational::ZERO);
}
#[test]
fn simplest_denominators_in_closed_interval_properties() {
rational_pair_gen_var_3().test_properties(|(a, b)| {
let ds = Rational::denominators_in_closed_interval(&a, &b)
.take(20)
.collect_vec();
assert!(is_strictly_ascending(ds.iter()));
for d in &ds {
assert!(
exhaustive_rationals_with_denominator_inclusive_range(d, a.clone(), b.clone(),)
.next()
.is_some()
);
}
for d in 1u32..=20 {
let d = Natural::from(d);
if !ds.contains(&d) {
assert!(exhaustive_rationals_with_denominator_inclusive_range(
&d,
a.clone(),
b.clone(),
)
.next()
.is_none());
}
}
});
rational_gen().test_properties(|a| {
assert!(
Rational::denominators_in_closed_interval(&a, &(&a + Rational::ONE))
.take(20)
.eq(exhaustive_positive_naturals().take(20))
);
});
}