// 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::arithmetic::traits::{Abs, FloorLogBase}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::string::from_sci_string::preprocess_sci_string; use malachite_base::num::conversion::string::options::{FromSciStringOptions, ToSciOptions}; use malachite_base::num::conversion::traits::{ExactFrom, FromSciString, ToSci}; use malachite_base::test_util::generators::{ string_from_sci_string_options_pair_gen_var_2, string_from_sci_string_options_pair_gen_var_3, string_gen_var_14, string_gen_var_15, }; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_7, rational_unsigned_pair_gen_var_6, }; use malachite_q::Rational; use std::str::FromStr; #[test] pub fn test_from_sci_string() { fn test(s: &str, out: Option<&'static str>) { let out = out.map(|s| Rational::from_str(s).unwrap()); assert_eq!(Rational::from_sci_string(s), out); assert_eq!( Rational::from_sci_string_with_options(s, FromSciStringOptions::default()), out ); } test("0", Some("0")); test("00", Some("0")); test("+0", Some("0")); test("-0", Some("0")); test("0.00", Some("0")); test("0e1", Some("0")); test("0e+1", Some("0")); test("0e-1", Some("0")); test("+0e+1", Some("0")); test("-0e+1", Some("0")); test("+0.0e+1", Some("0")); test("-0.0e+1", Some("0")); test(".0", Some("0")); test(".00", Some("0")); test(".00e0", Some("0")); test(".00e1", Some("0")); test(".00e-1", Some("0")); test("-.0", Some("0")); test("-.00", Some("0")); test("-.00e0", Some("0")); test("-.00e1", Some("0")); test("-.00e-1", Some("0")); test("+.0", Some("0")); test("+.00", Some("0")); test("+.00e0", Some("0")); test("+.00e1", Some("0")); test("+.00e-1", Some("0")); test("123", Some("123")); test("00123", Some("123")); test("+123", Some("123")); test("123.00", Some("123")); test("123e0", Some("123")); test("12.3e1", Some("123")); test("1.23e2", Some("123")); test("1.23E2", Some("123")); test("1.23e+2", Some("123")); test("1.23E+2", Some("123")); test(".123e3", Some("123")); test("0.123e3", Some("123")); test("+0.123e3", Some("123")); test("0.0123e4", Some("123")); test("1230e-1", Some("123")); test("12300e-2", Some("123")); test("12300E-2", Some("123")); test("-123", Some("-123")); test("-00123", Some("-123")); test("-123.00", Some("-123")); test("-123e0", Some("-123")); test("-12.3e1", Some("-123")); test("-1.23e2", Some("-123")); test("-1.23E2", Some("-123")); test("-1.23e+2", Some("-123")); test("-1.23E+2", Some("-123")); test("-.123e3", Some("-123")); test("-0.123e3", Some("-123")); test("-0.0123e4", Some("-123")); test("-1230e-1", Some("-123")); test("-12300e-2", Some("-123")); test("-12300E-2", Some("-123")); test("123.4", Some("617/5")); test("123.8", Some("619/5")); test("123.5", Some("247/2")); test("124.5", Some("249/2")); test("127.49", Some("12749/100")); test("-123.4", Some("-617/5")); test("-123.8", Some("-619/5")); test("-123.5", Some("-247/2")); test("-124.5", Some("-249/2")); test("-127.49", Some("-12749/100")); test("-127.5", Some("-255/2")); test("0.5", Some("1/2")); test( "0.3333333333333333", Some("3333333333333333/10000000000000000"), ); test("0.25", Some("1/4")); test("0.2", Some("1/5")); test( "0.1666666666666667", Some("1666666666666667/10000000000000000"), ); test( "0.1428571428571429", Some("1428571428571429/10000000000000000"), ); test("0.125", Some("1/8")); test( "0.1111111111111111", Some("1111111111111111/10000000000000000"), ); test("0.1", Some("1/10")); test( "0.09090909090909091", Some("9090909090909091/100000000000000000"), ); test("0.0", Some("0")); test("0.1", Some("1/10")); test("0.2", Some("1/5")); test("0.3", Some("3/10")); test("0.4", Some("2/5")); test("0.5", Some("1/2")); test("0.6", Some("3/5")); test("0.7", Some("7/10")); test("0.8", Some("4/5")); test("0.9", Some("9/10")); test("0.00", Some("0")); test("0.10", Some("1/10")); test("0.20", Some("1/5")); test("0.30", Some("3/10")); test("0.40", Some("2/5")); test("0.50", Some("1/2")); test("0.60", Some("3/5")); test("0.70", Some("7/10")); test("0.80", Some("4/5")); test("0.90", Some("9/10")); test("123.456456456456", Some("15432057057057/125000000000")); test( "1.4142135623730951", Some("14142135623730951/10000000000000000"), ); test( "3.141592653589793", Some("3141592653589793/1000000000000000"), ); test("2.718281828459045", Some("543656365691809/200000000000000")); test("", None); test("+", None); test("-", None); test("10e", None); test("++1", None); test("1.0.0", None); test("1e++1", None); test("1e0.1", None); test("--.0", None); test("++.0", None); test(".+2", None); test(".-2", None); test("0.000a", None); test("0.00ae-10", None); test("0e10000000000000000000000000000", None); test("0e-10000000000000000000000000000", None); } #[test] pub fn test_from_sci_string_with_options() { fn test(s: &str, options: FromSciStringOptions, out: Option<&str>) { let out = out.map(|s| Rational::from_str(s).unwrap()); assert_eq!(Rational::from_sci_string_with_options(s, options), out); } fn test_i(s: &str, options: FromSciStringOptions, out: Option) where Rational: From, { let out = out.map(Rational::from); assert_eq!(Rational::from_sci_string_with_options(s, options), out); } // For tests with the default options, see `test_from_sci_string` let mut options = FromSciStringOptions::default(); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", options, Some(u128::MAX), ); options.set_base(3); test_i( "202201102121002021012000211012011021221022212021111001022110211020010021100121010", options, Some(u128::MAX), ); options.set_base(4); test_i( "3333333333333333333333333333333333333333333333333333333333333333", options, Some(u128::MAX), ); options.set_base(5); test_i( "11031110441201303134210404233413032443021130230130231310", options, Some(u128::MAX), ); options.set_base(8); test_i( "3777777777777777777777777777777777777777777", options, Some(u128::MAX), ); options.set_base(16); test_i("ffffffffffffffffffffffffffffffff", options, Some(u128::MAX)); options.set_base(32); test_i("7vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(u128::MAX)); options.set_base(36); test_i("f5lxx1zz5pnorynqglhzmsp33", options, Some(u128::MAX)); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); test_i( "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(3); test_i( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); test_i( "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", options, Some(i128::MIN), ); options.set_base(4); test_i( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(5); test_i( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); test_i( "-3013030220323124042102424341431241221233040112312340403", options, Some(i128::MIN), ); options.set_base(8); test_i( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(16); test_i("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); test_i( "-80000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(32); test_i("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); test_i("-40000000000000000000000000", options, Some(i128::MIN)); options.set_base(36); test_i("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); test_i("-7ksyyizzkutudzbv8aqztecjk", options, Some(i128::MIN)); options.set_base(2); test("1e+5", options, Some("32")); test("1e5", options, Some("32")); options.set_base(3); test("1e+5", options, Some("243")); test("1e5", options, Some("243")); options.set_base(4); test("1e+5", options, Some("1024")); test("1e5", options, Some("1024")); options.set_base(5); test("1e+5", options, Some("3125")); test("1e5", options, Some("3125")); options.set_base(8); test("1e+5", options, Some("32768")); test("1e5", options, Some("32768")); options.set_base(16); test("1e+5", options, Some("1048576")); test("1e5", options, Some("485")); options.set_base(32); test("1e+5", options, Some("33554432")); test("1e5", options, Some("1477")); options.set_base(36); test("1e+5", options, Some("60466176")); test("1E+5", options, Some("60466176")); test("1e5", options, Some("1805")); options.set_base(16); test("ff", options, Some("255")); test("fF", options, Some("255")); test("Ff", options, Some("255")); test("FF", options, Some("255")); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("1.01", options, Some("5/4")); test("1.1", options, Some("3/2")); test("1.11", options, Some("7/4")); test("0.01", options, Some("1/4")); test("0.1", options, Some("1/2")); test("0.11", options, Some("3/4")); options.set_base(3); // 1/2 is 0.111... test("1.1", options, Some("4/3")); test("1.11", options, Some("13/9")); test("1.111", options, Some("40/27")); test("1.112", options, Some("41/27")); test("0.1", options, Some("1/3")); test("0.11", options, Some("4/9")); test("0.111", options, Some("13/27")); test("0.112", options, Some("14/27")); options = FromSciStringOptions::default(); options.set_base(2); test("2", options, None); test("102", options, None); test("12e4", options, None); test("12e-4", options, None); test("1.2", options, None); test("0.2", options, None); test("0.002", options, None); options.set_base(2); test("-1e+5", options, Some("-32")); test("-1e5", options, Some("-32")); options.set_base(3); test("-1e+5", options, Some("-243")); test("-1e5", options, Some("-243")); options.set_base(4); test("-1e+5", options, Some("-1024")); test("-1e5", options, Some("-1024")); options.set_base(5); test("-1e+5", options, Some("-3125")); test("-1e5", options, Some("-3125")); options.set_base(8); test("-1e+5", options, Some("-32768")); test("-1e5", options, Some("-32768")); options.set_base(16); test("-1e+5", options, Some("-1048576")); test("-1e5", options, Some("-485")); options.set_base(32); test("-1e+5", options, Some("-33554432")); test("-1e5", options, Some("-1477")); options.set_base(36); test("-1e+5", options, Some("-60466176")); test("-1E+5", options, Some("-60466176")); test("-1e5", options, Some("-1805")); options.set_base(16); test("-ff", options, Some("-255")); test("-fF", options, Some("-255")); test("-Ff", options, Some("-255")); test("-FF", options, Some("-255")); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("-1.01", options, Some("-5/4")); test("-1.1", options, Some("-3/2")); test("-1.11", options, Some("-7/4")); test("-0.01", options, Some("-1/4")); test("-0.1", options, Some("-1/2")); test("-0.11", options, Some("-3/4")); options.set_base(3); // 1/2 is 0.111... test("-1.1", options, Some("-4/3")); test("-1.11", options, Some("-13/9")); test("-1.111", options, Some("-40/27")); test("-1.112", options, Some("-41/27")); test("-0.1", options, Some("-1/3")); test("-0.11", options, Some("-4/9")); test("-0.111", options, Some("-13/27")); test("-0.112", options, Some("-14/27")); options = FromSciStringOptions::default(); options.set_base(2); test("-2", options, None); test("-102", options, None); test("-12e4", options, None); test("-12e-4", options, None); test("-1.2", options, None); test("-0.2", options, None); test("-0.002", options, None); test("0.1111111111", options, Some("1023/1024")); options.set_base(3); test("0.1111111111", options, Some("29524/59049")); options.set_base(4); test("0.1111111111", options, Some("349525/1048576")); options.set_base(16); test("0.1111111111", options, Some("73300775185/1099511627776")); options.set_base(32); test( "0.1111111111", options, Some("36319351833633/1125899906842624"), ); options.set_base(36); test( "0.1111111111", options, Some("104461669716085/3656158440062976"), ); } #[test] pub fn test_from_sci_string_simplest() { fn test(s: &str, out: Option<&'static str>) { let out = out.map(|s| Rational::from_str(s).unwrap()); assert_eq!(Rational::from_sci_string_simplest(s), out); assert_eq!( Rational::from_sci_string_simplest_with_options(s, FromSciStringOptions::default()), out ); } test("0", Some("0")); test("00", Some("0")); test("+0", Some("0")); test("-0", Some("0")); test("0.00", Some("0")); test("0e1", Some("0")); test("0e+1", Some("0")); test("0e-1", Some("0")); test("+0e+1", Some("0")); test("-0e+1", Some("0")); test("+0.0e+1", Some("0")); test("-0.0e+1", Some("0")); test(".0", Some("0")); test(".00", Some("0")); test(".00e0", Some("0")); test(".00e1", Some("0")); test(".00e-1", Some("0")); test("-.0", Some("0")); test("-.00", Some("0")); test("-.00e0", Some("0")); test("-.00e1", Some("0")); test("-.00e-1", Some("0")); test("+.0", Some("0")); test("+.00", Some("0")); test("+.00e0", Some("0")); test("+.00e1", Some("0")); test("+.00e-1", Some("0")); test("123", Some("123")); test("00123", Some("123")); test("+123", Some("123")); test("123.00", Some("123")); test("123e0", Some("123")); test("12.3e1", Some("123")); test("1.23e2", Some("123")); test("1.23E2", Some("123")); test("1.23e+2", Some("123")); test("1.23E+2", Some("123")); test(".123e3", Some("123")); test("0.123e3", Some("123")); test("+0.123e3", Some("123")); test("0.0123e4", Some("123")); test("1230e-1", Some("123")); test("12300e-2", Some("123")); test("12300E-2", Some("123")); test("-123", Some("-123")); test("-00123", Some("-123")); test("-123.00", Some("-123")); test("-123e0", Some("-123")); test("-12.3e1", Some("-123")); test("-1.23e2", Some("-123")); test("-1.23E2", Some("-123")); test("-1.23e+2", Some("-123")); test("-1.23E+2", Some("-123")); test("-.123e3", Some("-123")); test("-0.123e3", Some("-123")); test("-0.0123e4", Some("-123")); test("-1230e-1", Some("-123")); test("-12300e-2", Some("-123")); test("-12300E-2", Some("-123")); test("123.4", Some("617/5")); test("123.8", Some("495/4")); test("123.5", Some("247/2")); test("124.5", Some("249/2")); test("127.49", Some("4462/35")); test("-123.4", Some("-617/5")); test("-123.8", Some("-495/4")); test("-123.5", Some("-247/2")); test("-124.5", Some("-249/2")); test("-127.49", Some("-4462/35")); test("-127.5", Some("-255/2")); test("0.5", Some("1/2")); test("0.3333333333333333", Some("1/3")); test("0.25", Some("1/4")); test("0.2", Some("1/4")); test("0.1666666666666667", Some("1/6")); test("0.1428571428571429", Some("1/7")); test("0.125", Some("1/8")); test("0.1111111111111111", Some("1/9")); test("0.1", Some("1/7")); test("0.09090909090909091", Some("1/11")); test("0.0", Some("0")); test("0.1", Some("1/7")); test("0.2", Some("1/4")); test("0.3", Some("1/3")); test("0.4", Some("2/5")); test("0.5", Some("1/2")); test("0.6", Some("3/5")); test("0.7", Some("2/3")); test("0.8", Some("3/4")); test("0.9", Some("6/7")); test("0.00", Some("0")); test("0.10", Some("1/10")); test("0.20", Some("1/5")); test("0.30", Some("3/10")); test("0.40", Some("2/5")); test("0.50", Some("1/2")); test("0.60", Some("3/5")); test("0.70", Some("7/10")); test("0.80", Some("4/5")); test("0.90", Some("9/10")); test("123.456456456456", Some("41111/333")); test("1.4142135623730951", Some("131836323/93222358")); test("3.141592653589793", Some("80143857/25510582")); test("2.718281828459045", Some("212385209/78132152")); test("", None); test("+", None); test("-", None); test("10e", None); test("++1", None); test("1.0.0", None); test("1e++1", None); test("1e0.1", None); test("--.0", None); test("++.0", None); test(".+2", None); test(".-2", None); test("0.000a", None); test("0.00ae-10", None); test("0e10000000000000000000000000000", None); test("0e-10000000000000000000000000000", None); } #[test] pub fn test_from_sci_string_simplest_with_options() { fn test(s: &str, options: FromSciStringOptions, out: Option<&str>) { let out = out.map(|s| Rational::from_str(s).unwrap()); assert_eq!( Rational::from_sci_string_simplest_with_options(s, options), out ); } fn test_i(s: &str, options: FromSciStringOptions, out: Option) where Rational: From, { let out = out.map(Rational::from); assert_eq!( Rational::from_sci_string_simplest_with_options(s, options), out ); } // For tests with the default options, see `test_from_sci_string` let mut options = FromSciStringOptions::default(); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", options, Some(u128::MAX), ); options.set_base(3); test_i( "202201102121002021012000211012011021221022212021111001022110211020010021100121010", options, Some(u128::MAX), ); options.set_base(4); test_i( "3333333333333333333333333333333333333333333333333333333333333333", options, Some(u128::MAX), ); options.set_base(5); test_i( "11031110441201303134210404233413032443021130230130231310", options, Some(u128::MAX), ); options.set_base(8); test_i( "3777777777777777777777777777777777777777777", options, Some(u128::MAX), ); options.set_base(16); test_i("ffffffffffffffffffffffffffffffff", options, Some(u128::MAX)); options.set_base(32); test_i("7vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(u128::MAX)); options.set_base(36); test_i("f5lxx1zz5pnorynqglhzmsp33", options, Some(u128::MAX)); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); test_i( "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(3); test_i( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); test_i( "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", options, Some(i128::MIN), ); options.set_base(4); test_i( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(5); test_i( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); test_i( "-3013030220323124042102424341431241221233040112312340403", options, Some(i128::MIN), ); options.set_base(8); test_i( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(16); test_i("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); test_i( "-80000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(32); test_i("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); test_i("-40000000000000000000000000", options, Some(i128::MIN)); options.set_base(36); test_i("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); test_i("-7ksyyizzkutudzbv8aqztecjk", options, Some(i128::MIN)); options.set_base(2); test("1e+5", options, Some("32")); test("1e5", options, Some("32")); options.set_base(3); test("1e+5", options, Some("243")); test("1e5", options, Some("243")); options.set_base(4); test("1e+5", options, Some("1024")); test("1e5", options, Some("1024")); options.set_base(5); test("1e+5", options, Some("3125")); test("1e5", options, Some("3125")); options.set_base(8); test("1e+5", options, Some("32768")); test("1e5", options, Some("32768")); options.set_base(16); test("1e+5", options, Some("1048576")); test("1e5", options, Some("485")); options.set_base(32); test("1e+5", options, Some("33554432")); test("1e5", options, Some("1477")); options.set_base(36); test("1e+5", options, Some("60466176")); test("1E+5", options, Some("60466176")); test("1e5", options, Some("1805")); options.set_base(16); test("ff", options, Some("255")); test("fF", options, Some("255")); test("Ff", options, Some("255")); test("FF", options, Some("255")); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("1.01", options, Some("4/3")); test("1.1", options, Some("3/2")); test("1.11", options, Some("5/3")); test("0.01", options, Some("1/3")); test("0.1", options, Some("1/2")); test("0.11", options, Some("2/3")); options.set_base(3); // 1/2 is 0.111... test("1.1", options, Some("3/2")); test("1.11", options, Some("3/2")); test("1.111", options, Some("3/2")); test("1.112", options, Some("3/2")); test("0.1", options, Some("1/2")); test("0.11", options, Some("1/2")); test("0.111", options, Some("1/2")); test("0.112", options, Some("1/2")); options = FromSciStringOptions::default(); options.set_base(2); test("2", options, None); test("102", options, None); test("12e4", options, None); test("12e-4", options, None); test("1.2", options, None); test("0.2", options, None); test("0.002", options, None); options.set_base(2); test("-1e+5", options, Some("-32")); test("-1e5", options, Some("-32")); options.set_base(3); test("-1e+5", options, Some("-243")); test("-1e5", options, Some("-243")); options.set_base(4); test("-1e+5", options, Some("-1024")); test("-1e5", options, Some("-1024")); options.set_base(5); test("-1e+5", options, Some("-3125")); test("-1e5", options, Some("-3125")); options.set_base(8); test("-1e+5", options, Some("-32768")); test("-1e5", options, Some("-32768")); options.set_base(16); test("-1e+5", options, Some("-1048576")); test("-1e5", options, Some("-485")); options.set_base(32); test("-1e+5", options, Some("-33554432")); test("-1e5", options, Some("-1477")); options.set_base(36); test("-1e+5", options, Some("-60466176")); test("-1E+5", options, Some("-60466176")); test("-1e5", options, Some("-1805")); options.set_base(16); test("-ff", options, Some("-255")); test("-fF", options, Some("-255")); test("-Ff", options, Some("-255")); test("-FF", options, Some("-255")); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("-1.01", options, Some("-4/3")); test("-1.1", options, Some("-3/2")); test("-1.11", options, Some("-5/3")); test("-0.01", options, Some("-1/3")); test("-0.1", options, Some("-1/2")); test("-0.11", options, Some("-2/3")); options.set_base(3); // 1/2 is 0.111... test("-1.1", options, Some("-3/2")); test("-1.11", options, Some("-3/2")); test("-1.111", options, Some("-3/2")); test("-1.112", options, Some("-3/2")); test("-0.1", options, Some("-1/2")); test("-0.11", options, Some("-1/2")); test("-0.111", options, Some("-1/2")); test("-0.112", options, Some("-1/2")); options = FromSciStringOptions::default(); options.set_base(2); test("-2", options, None); test("-102", options, None); test("-12e4", options, None); test("-12e-4", options, None); test("-1.2", options, None); test("-0.2", options, None); test("-0.002", options, None); test("0.1111111111", options, Some("682/683")); options.set_base(3); test("0.1111111111", options, Some("1/2")); options.set_base(4); test("0.1111111111", options, Some("1/3")); options.set_base(16); test("0.1111111111", options, Some("1/15")); options.set_base(32); test("0.1111111111", options, Some("1/31")); options.set_base(36); test("0.1111111111", options, Some("1/35")); } fn from_sci_string_helper(s: &str) { if let Some(x) = Rational::from_sci_string(s) { assert!(x.is_valid()); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); let mut to_options = ToSciOptions::default(); to_options.set_size_complete(); let s_alt = x.to_sci_with_options(to_options).to_string(); assert_eq!(Rational::from_sci_string(&s_alt).unwrap(), x); } } #[test] fn from_sci_string_properties() { string_gen_var_14().test_properties(|s| { from_sci_string_helper(&s); }); string_gen_var_15().test_properties(|s| { from_sci_string_helper(&s); }); } fn from_sci_string_with_options_helper(s: &str, options: FromSciStringOptions) { if let Some(x) = Rational::from_sci_string_with_options(s, options) { assert!(x.is_valid()); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); let mut to_options = ToSciOptions::default(); to_options.set_base(options.get_base()); to_options.set_size_complete(); let s_alt = x.to_sci_with_options(to_options).to_string(); assert_eq!( Rational::from_sci_string_with_options(&s_alt, options).unwrap(), x ); } } #[test] fn from_sci_string_with_options_properties() { string_from_sci_string_options_pair_gen_var_2().test_properties(|(s, options)| { from_sci_string_with_options_helper(&s, options); }); string_from_sci_string_options_pair_gen_var_3().test_properties(|(s, options)| { from_sci_string_with_options_helper(&s, options); }); let mut options = ToSciOptions::default(); options.set_size_complete(); rational_gen().test_properties(|x| { if x.fmt_sci_valid(options) { assert_eq!( Rational::from_sci_string(&x.to_sci_with_options(options).to_string()).unwrap(), x ); } }); } fn string_precision(s: &str, base: u8) -> u64 { let mut options = FromSciStringOptions::default(); options.set_base(base); let mut s = preprocess_sci_string(s, options).unwrap().0; if s[0] == b'+' || s[0] == b'-' { s.remove(0); } let mut leading_zeros = 0; for &c in &s { if c != b'0' { break; } leading_zeros += 1; } u64::exact_from(s.len()) - leading_zeros } fn from_sci_string_simplest_helper(s: &str) { let mut from_options = FromSciStringOptions::default(); from_options.set_base(10); if let Some(x) = Rational::from_sci_string_simplest(s) { assert!(x.is_valid()); if x != 0u32 { let mut options = ToSciOptions::default(); let precision = string_precision(s, 10); options.set_precision(precision); let s_alt = x.to_sci_with_options(options).to_string(); let x_1 = Rational::from_sci_string_with_options(s, from_options).unwrap(); let x_2 = Rational::from_sci_string_with_options(&s_alt, from_options).unwrap(); // Usually x_1 == x_2. However... if x_1 != x_2 { let diff_1 = x_1 - &x; let diff_2 = x_2 - &x; assert_eq!(diff_1, -diff_2); let scale = u64::exact_from( i64::exact_from(precision) - x.abs().floor_log_base(&Rational::from(10)) - 1, ); let mut options_2 = ToSciOptions::default(); options_2.set_scale(scale); assert_eq!(diff_1.abs().to_sci_with_options(options_2).to_string(), "0"); } } } } #[test] fn from_sci_string_simplest_properties() { string_gen_var_14().test_properties(|s| { from_sci_string_simplest_helper(&s); }); string_gen_var_15().test_properties(|s| { from_sci_string_simplest_helper(&s); }); let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); rational_gen_var_7().test_properties(|q| { assert_eq!( Rational::from_sci_string_simplest(&q.to_sci_with_options(options).to_string()) .unwrap(), q ); }); } fn from_sci_string_simplest_with_options_helper(s: &str, options: FromSciStringOptions) { if let Some(x) = Rational::from_sci_string_simplest_with_options(s, options) { assert!(x.is_valid()); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); if x != 0u32 { let base = options.get_base(); let mut to_options = ToSciOptions::default(); to_options.set_base(base); let precision = string_precision(s, base); to_options.set_precision(precision); let mut from_options = FromSciStringOptions::default(); from_options.set_base(base); let s_alt = x.to_sci_with_options(to_options).to_string(); let x_1 = Rational::from_sci_string_with_options(s, from_options).unwrap(); let x_2 = Rational::from_sci_string_with_options(&s_alt, from_options).unwrap(); // Usually x_1 == x_2. However... if x_1 != x_2 { let diff_1 = x_1 - &x; let diff_2 = x_2 - &x; assert_eq!(diff_1, -diff_2); let scale = u64::exact_from( i64::exact_from(precision) - x.abs().floor_log_base(&Rational::from(base)) - 1, ); let mut options_2 = ToSciOptions::default(); options_2.set_base(base); options_2.set_scale(scale); assert_eq!(diff_1.abs().to_sci_with_options(options_2).to_string(), "0"); } } } } #[test] fn from_sci_string_simplest_with_options_properties() { string_from_sci_string_options_pair_gen_var_2().test_properties(|(s, options)| { from_sci_string_simplest_with_options_helper(&s, options); }); string_from_sci_string_options_pair_gen_var_3().test_properties(|(s, options)| { from_sci_string_simplest_with_options_helper(&s, options); }); rational_unsigned_pair_gen_var_6().test_properties(|(q, base)| { let mut to_options = ToSciOptions::default(); to_options.set_include_trailing_zeros(true); to_options.set_base(base); let mut from_options = FromSciStringOptions::default(); from_options.set_base(base); assert_eq!( Rational::from_sci_string_simplest_with_options( &q.to_sci_with_options(to_options).to_string(), from_options ) .unwrap(), q ); }); }