// 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 itertools::Itertools; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::vecs::vec_from_str; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{integer_gen, natural_vec_integer_pair_gen_var_1}; use malachite_q::conversion::traits::ContinuedFraction; use malachite_q::test_util::conversion::continued_fraction::from_continued_fraction::*; use malachite_q::Rational; use std::str::FromStr; #[test] fn test_from_continued_fraction() { let test = |floor: &str, xs: &str, out: &str| { let floor = Integer::from_str(floor).unwrap(); let xs: Vec = vec_from_str(xs).unwrap(); let x = Rational::from_continued_fraction(floor.clone(), xs.iter().cloned()); assert!(x.is_valid()); assert_eq!(Rational::from_continued_fraction_ref(&floor, xs.iter()), x); assert_eq!(from_continued_fraction_alt(floor, xs), x); assert_eq!(x.to_string(), out); }; test("0", "[]", "0"); test("3", "[7]", "22/7"); test("3", "[6, 1]", "22/7"); test("-4", "[1, 6]", "-22/7"); test( "3", "[7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2]", "14885392687/4738167652", ); } #[test] #[should_panic] fn from_continued_fraction_fail_1() { Rational::from_continued_fraction(Integer::ONE, std::iter::once(Natural::ZERO)); } #[test] #[should_panic] fn from_continued_fraction_fail_2() { Rational::from_continued_fraction( Integer::ONE, vec![Natural::from(3u32), Natural::ZERO, Natural::ONE].into_iter(), ); } #[test] #[should_panic] fn from_continued_fraction_ref_fail_1() { Rational::from_continued_fraction_ref(&Integer::ONE, [Natural::ZERO].iter()); } #[test] #[should_panic] fn from_continued_fraction_ref_fail_2() { Rational::from_continued_fraction_ref( &Integer::ONE, [Natural::from(3u32), Natural::ZERO, Natural::ONE].iter(), ); } #[test] fn from_continued_fraction_properties() { natural_vec_integer_pair_gen_var_1().test_properties(|(xs, floor)| { let x = Rational::from_continued_fraction(floor.clone(), xs.iter().cloned()); assert!(x.is_valid()); assert_eq!(Rational::from_continued_fraction_ref(&floor, xs.iter()), x); assert_eq!(from_continued_fraction_alt(floor.clone(), xs.clone()), x); if xs.last() != Some(&Natural::ONE) { let (floor_alt, cf) = (&x).continued_fraction(); let xs_alt = cf.collect_vec(); assert_eq!(floor_alt, floor); assert_eq!(xs_alt, xs); } if !xs.is_empty() { let mut alt_xs = xs; let last = alt_xs.last_mut().unwrap(); if *last > 1u32 { *last -= Natural::ONE; alt_xs.push(Natural::ONE); assert_eq!( Rational::from_continued_fraction(floor, alt_xs.into_iter()), x ); } } }); integer_gen().test_properties(|x| { assert_eq!( Rational::from_continued_fraction_ref(&x, std::iter::empty()), x ); }); }