// Copyright © 2024 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See .
use malachite_base::num::basic::traits::{One, Zero};
use malachite_base::num::conversion::traits::Digits;
use malachite_base::rational_sequences::RationalSequence;
use malachite_base::vecs::vec_from_str;
use malachite_nz::natural::Natural;
use malachite_nz::test_util::generators::{
large_type_gen_var_25, natural_vec_natural_pair_gen_var_2,
};
use malachite_q::Rational;
use std::str::FromStr;
#[test]
fn test_from_digits() {
let test = |base: &str, before: &str, after_nr: &str, after_r: &str, out: &str| {
let base = Natural::from_str(base).unwrap();
let before: Vec = vec_from_str(before).unwrap();
let after_nr: Vec = vec_from_str(after_nr).unwrap();
let after_r: Vec = vec_from_str(after_r).unwrap();
let x = Rational::from_digits_ref(
&base,
&before,
&RationalSequence::from_slices(&after_nr, &after_r),
);
assert!(x.is_valid());
assert_eq!(x.to_string(), out);
assert_eq!(
Rational::from_digits(
&base,
before,
RationalSequence::from_vecs(after_nr, after_r)
),
x
);
};
test("3", "[]", "[]", "[]", "0");
test("10", "[]", "[]", "[]", "0");
test("3", "[1]", "[]", "[]", "1");
test("10", "[1]", "[]", "[]", "1");
test("3", "[]", "[]", "[1]", "1/2");
test("10", "[]", "[5]", "[]", "1/2");
test("3", "[]", "[1]", "[]", "1/3");
test("10", "[]", "[]", "[3]", "1/3");
test("3", "[1]", "[0]", "[1]", "7/6");
test("10", "[1]", "[1]", "[6]", "7/6");
test("3", "[0, 1]", "[]", "[0, 1, 0, 2, 1, 2]", "22/7");
test("10", "[3]", "[]", "[1, 4, 2, 8, 5, 7]", "22/7");
test(
"3",
"[1, 2, 2, 1, 0, 0, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 0, 2, 1]",
"[]",
"[1, 0, 1, 1, 0, 1, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 2, 1, 0, 2, 0, \
2, 0, 0, 1, 1, 2, 2, 2, 1, 2, 2, 0, 0, 2, 0, 2, 2, 0, 0, 2, 1, 2, 2, 1, 1, 1, 0, 2, 0, 2, \
2, 2, 1, 0, 1, 0, 2, 2, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 2, 1, 0, 2, 2, 0, 2, 0, 2, 1, 1, \
0, 1, 2, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 1, 2, 0, 1, 2, 1, 0, 1, 0, 0, 1, 2, 1, 2, 1, 2, 1, \
2, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 0, 2, 0, 0, 1, 0, 1, 0, 2, 1, 0, 0, 2, 1, 1, 1, 2, 1, 1, \
1, 2, 2, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 2, 0, 0, 2, 1, 0, 0, 1, 2, 2, 2, 2, 0, 2, 0, 1, 2, \
2, 1, 1, 1, 2, 1, 0, 0, 0, 1, 2, 1, 0, 1, 1, 2, 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, 1, 1, 2, 0, \
1, 2, 1, 1, 2, 2, 0, 2, 2, 0, 0, 1, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 2, 1, 2, 1, 1, 1, 0, 0, \
0, 2, 0, 1, 0, 2, 2, 0, 2, 2, 1, 0, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 0, 2, 0, 1, 1, 0, 0, \
2, 1, 2, 1, 2, 2, 2, 0, 1, 1, 1, 2, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 2, 0, 2, 1, \
0, 1, 0, 0, 0, 0, 2, 2, 1, 0, 0, 1, 0, 2, 1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 0, 0, 1, 0, 1, \
0, 0, 2, 1, 0, 1, 2, 0, 1, 0, 0, 2, 1, 2, 0, 1, 0, 1, 2, 2, 0, 0, 2, 2, 1, 1, 0, 1, 2, 0, \
0, 1, 2, 0, 1, 1, 0, 2, 2, 2, 2, 0, 0, 0, 1, 0, 1, 1, 0, 2, 2, 1, 0, 0, 2, 2, 1, 2, 0, 2, \
0, 0, 2, 0, 1, 1, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 1, 0, 1, 1, 1, 1, 2, 1, \
2, 2, 0, 0, 0, 2, 0, 1, 2, 1, 1, 1, 0, 1, 2, 1, 0, 2, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, \
2, 0, 1, 0, 1, 2, 0, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 2, 0, \
2, 1, 1, 1, 0, 1, 0, 2, 1, 1, 2, 1, 1, 2, 1, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2, 1, 2, 2, \
0, 2, 2, 1, 2, 0, 0, 1, 1, 1, 2, 2, 0, 2, 0, 1, 1, 0, 2, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 1, \
2, 1, 2, 1, 0, 2, 2, 2, 2, 1, 1, 2, 1, 1, 0, 2, 1, 2, 0, 0, 0, 1, 1, 1, 1, 2, 0, 0, 2, 2, \
2, 1, 0, 2, 2, 1, 2, 1, 0, 1, 2, 2, 1, 1, 0, 0, 1, 2, 2, 1, 0, 1, 1, 2, 2, 1, 1, 2, 0, 2, \
2, 0, 1, 1, 0, 1, 2, 2, 0, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 0, 2, 1, 0, 0, 0, 2, 2, 1, 1, 2, \
0]",
"936851431250/1397",
);
test(
"10",
"[9, 2, 6, 6, 1, 6, 0, 7, 6]",
"[]",
"[3, 8, 4, 3, 9, 5, 1, 3, 2, 4, 2, 6, 6, 2, 8, 4, 8, 9, 6, 2, 0, 6, 1, 5, 6, 0, 4, 8, 6, \
7, 5, 7, 3, 3, 7, 1, 5, 1, 0, 3, 7, 9]",
"936851431250/1397",
);
}
#[test]
#[should_panic]
fn from_digits_fail_1() {
Rational::from_digits(
&Natural::ONE,
Vec::new(),
RationalSequence::from_vec(Vec::new()),
);
}
#[test]
#[should_panic]
fn from_digits_fail_2() {
Rational::from_digits(
&Natural::ZERO,
Vec::new(),
RationalSequence::from_vec(Vec::new()),
);
}
#[test]
#[should_panic]
fn from_digits_ref_fail_1() {
Rational::from_digits_ref(&Natural::ONE, &[], &RationalSequence::from_vec(Vec::new()));
}
#[test]
#[should_panic]
fn from_digits_ref_fail_2() {
Rational::from_digits_ref(&Natural::ZERO, &[], &RationalSequence::from_vec(Vec::new()));
}
#[test]
fn from_digits_properties() {
large_type_gen_var_25().test_properties(|(base, before_point, after_point)| {
let x = Rational::from_digits(&base, before_point.clone(), after_point.clone());
assert!(x.is_valid());
assert_eq!(
Rational::from_digits_ref(&base, &before_point, &after_point),
x
);
assert!(x >= 0u32);
if before_point.last() != Some(&Natural::ZERO)
&& after_point.slices_ref().1 != [Natural::ZERO]
&& after_point.slices_ref().1 != [&base - Natural::ONE]
&& !(after_point.slices_ref().1.is_empty()
&& after_point.slices_ref().0.last() == Some(&Natural::ZERO))
{
assert_eq!(x.into_digits(&base), (before_point, after_point));
}
});
natural_vec_natural_pair_gen_var_2().test_properties(|(digits, base)| {
assert_eq!(
Natural::from_digits_asc(&base, digits.iter().cloned()).unwrap(),
Rational::from_digits(
&base,
digits.to_vec(),
RationalSequence::from_vec(Vec::new())
)
);
});
}