// 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::{FloorLogBase, UnsignedAbs};
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::signeds::PrimitiveSigned;
use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
use malachite_base::num::conversion::string::options::{
FromSciStringOptions, SciSizeOptions, ToSciOptions,
};
use malachite_base::rounding_modes::RoundingMode::*;
use malachite_base::strings::string_is_subset;
use malachite_base::test_util::generators::{
signed_gen, signed_to_sci_options_pair_gen_var_1, unsigned_gen,
unsigned_to_sci_options_pair_gen_var_1,
};
use malachite_base::test_util::num::conversion::string::from_sci_string::DECIMAL_SCI_STRING_CHARS;
use std::collections::HashMap;
use std::panic::catch_unwind;
#[test]
pub fn test_to_sci() {
fn test(x: T, out: &str) {
assert_eq!(x.to_sci().to_string(), out);
assert_eq!(
x.to_sci_with_options(ToSciOptions::default()).to_string(),
out
);
}
test::(0, "0");
test::(1, "1");
test::(10, "10");
test::(100, "100");
test::(1000, "1000");
test::(10000, "10000");
test::(100000, "100000");
test::(1000000, "1000000");
test::(10000000, "10000000");
test::(100000000, "100000000");
test::(1000000000, "1000000000");
test::(10000000000, "10000000000");
test::(100000000000, "100000000000");
test::(1000000000000, "1000000000000");
test::(10000000000000, "10000000000000");
test::(100000000000000, "100000000000000");
test::(1000000000000000, "1000000000000000");
test::(10000000000000000, "1e16");
test::(100000000000000000, "1e17");
test::(u64::MAX, "1.844674407370955e19");
test::(u128::MAX, "3.402823669209385e38");
test::(999999999999999, "999999999999999");
test::(9999999999999999, "9999999999999999");
test::(99999999999999999, "1e17");
test::(999999999999999999, "1e18");
test::(0, "0");
test::(1, "1");
test::(10, "10");
test::(100, "100");
test::(1000, "1000");
test::(10000, "10000");
test::(100000, "100000");
test::(1000000, "1000000");
test::(10000000, "10000000");
test::(100000000, "100000000");
test::(1000000000, "1000000000");
test::(10000000000, "10000000000");
test::(100000000000, "100000000000");
test::(1000000000000, "1000000000000");
test::(10000000000000, "10000000000000");
test::(100000000000000, "100000000000000");
test::(1000000000000000, "1000000000000000");
test::(10000000000000000, "1e16");
test::(100000000000000000, "1e17");
test::(i64::MAX, "9.223372036854776e18");
test::(i128::MAX, "1.701411834604692e38");
test::(-1, "-1");
test::(-10, "-10");
test::(-100, "-100");
test::(-1000, "-1000");
test::(-10000, "-10000");
test::(-100000, "-100000");
test::(-1000000, "-1000000");
test::(-10000000, "-10000000");
test::(-100000000, "-100000000");
test::(-1000000000, "-1000000000");
test::(-10000000000, "-10000000000");
test::(-100000000000, "-100000000000");
test::(-1000000000000, "-1000000000000");
test::(-10000000000000, "-10000000000000");
test::(-100000000000000, "-100000000000000");
test::(-1000000000000000, "-1000000000000000");
test::(-10000000000000000, "-1e16");
test::(-100000000000000000, "-1e17");
test::(i64::MIN, "-9.223372036854776e18");
test::(i128::MIN, "-1.701411834604692e38");
test::(999999999999999, "999999999999999");
test::(9999999999999999, "9999999999999999");
test::(99999999999999999, "1e17");
test::(999999999999999999, "1e18");
}
#[test]
pub fn test_to_sci_with_options() {
fn test(x: T, options: ToSciOptions, out: &str) {
assert_eq!(x.to_sci_with_options(options).to_string(), out);
}
// For tests with the default options, see `test_to_sci`
let mut options = ToSciOptions::default();
options.set_include_trailing_zeros(true);
test::(0, options, "0.000000000000000");
test::(1, options, "1.000000000000000");
test::(10, options, "10.00000000000000");
test::(100, options, "100.0000000000000");
test::(1000, options, "1000.000000000000");
test::(10000, options, "10000.00000000000");
test::(100000, options, "100000.0000000000");
test::(1000000, options, "1000000.000000000");
test::(10000000, options, "10000000.00000000");
test::(100000000, options, "100000000.0000000");
test::(1000000000, options, "1000000000.000000");
test::(10000000000, options, "10000000000.00000");
test::(100000000000, options, "100000000000.0000");
test::(1000000000000, options, "1000000000000.000");
test::(10000000000000, options, "10000000000000.00");
test::(100000000000000, options, "100000000000000.0");
test::(1000000000000000, options, "1000000000000000");
test::(10000000000000000, options, "1.000000000000000e16");
test::(100000000000000000, options, "1.000000000000000e17");
test::(u64::MAX, options, "1.844674407370955e19");
test::(u128::MAX, options, "3.402823669209385e38");
test::(999999999999999, options, "999999999999999.0");
test::(9999999999999999, options, "9999999999999999");
test::(99999999999999999, options, "1.000000000000000e17");
test::(999999999999999999, options, "1.000000000000000e18");
options = ToSciOptions::default();
options.set_base(2);
test::(u128::MAX, options, "1e128");
options.set_base(3);
test::(u128::MAX, options, "2.022011021210021e80");
options.set_base(4);
test::(u128::MAX, options, "1e64");
options.set_base(5);
test::(u128::MAX, options, "1.103111044120131e55");
options.set_base(8);
test::(u128::MAX, options, "4e42");
// When base >= 15, there is a mandatory sign after the exponent indicator "e", to distinguish
// it from the digit "e"
options.set_base(16);
test::(u128::MAX, options, "1e+32");
options.set_base(32);
test::(u128::MAX, options, "8e+25");
options.set_base(36);
test::(u128::MAX, options, "f.5lxx1zz5pnorynqe+24");
// The sign can be forced in other cases too
options.set_base(3);
options.set_force_exponent_plus_sign(true);
test::(u128::MAX, options, "2.022011021210021e+80");
// The digits can be uppercase, and so can the exponent indicator
options = ToSciOptions::default();
options.set_base(36);
options.set_uppercase();
test::(u128::MAX, options, "F.5LXX1ZZ5PNORYNQe+24");
options.set_lowercase();
options.set_e_uppercase();
test::(u128::MAX, options, "f.5lxx1zz5pnorynqE+24");
options.set_uppercase();
test::(u128::MAX, options, "F.5LXX1ZZ5PNORYNQE+24");
options = ToSciOptions::default();
options.set_size_complete();
options.set_base(2);
test::(
u128::MAX,
options,
"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\
111111111111111111111111111111111111111",
);
options.set_base(3);
test::(
u128::MAX,
options,
"202201102121002021012000211012011021221022212021111001022110211020010021100121010",
);
options.set_base(4);
test::(
u128::MAX,
options,
"3333333333333333333333333333333333333333333333333333333333333333",
);
options.set_base(5);
test::(
u128::MAX,
options,
"11031110441201303134210404233413032443021130230130231310",
);
options.set_base(8);
test::(
u128::MAX,
options,
"3777777777777777777777777777777777777777777",
);
options.set_base(16);
test::(u128::MAX, options, "ffffffffffffffffffffffffffffffff");
options.set_base(32);
test::(u128::MAX, options, "7vvvvvvvvvvvvvvvvvvvvvvvvv");
options.set_base(36);
test::(u128::MAX, options, "f5lxx1zz5pnorynqglhzmsp33");
options = ToSciOptions::default();
options.set_precision(4);
options.set_include_trailing_zeros(true);
test::(0, options, "0.000");
test::(1, options, "1.000");
test::(10, options, "10.00");
test::(100, options, "100.0");
test::(1000, options, "1000");
test::(10000, options, "1.000e4");
test::(9, options, "9.000");
test::(99, options, "99.00");
test::(999, options, "999.0");
test::(9999, options, "9999");
test::(99999, options, "1.000e5");
options.set_include_trailing_zeros(false);
test::(0, options, "0");
test::(1, options, "1");
test::(10, options, "10");
test::(100, options, "100");
test::(1000, options, "1000");
test::(10000, options, "1e4");
test::(9, options, "9");
test::(99, options, "99");
test::(999, options, "999");
test::(9999, options, "9999");
test::(99999, options, "1e5");
options = ToSciOptions::default();
options.set_precision(1);
options.set_include_trailing_zeros(true); // doesn't matter when precision is 1
test::(0, options, "0");
test::(1, options, "1");
test::(10, options, "1e1");
test::(100, options, "1e2");
test::(1000, options, "1e3");
test::(10000, options, "1e4");
test::(9, options, "9");
test::(99, options, "1e2");
test::(999, options, "1e3");
test::(9999, options, "1e4");
test::(99999, options, "1e5");
options.set_include_trailing_zeros(false);
test::(0, options, "0");
test::(1, options, "1");
test::(10, options, "1e1");
test::(100, options, "1e2");
test::(1000, options, "1e3");
test::(10000, options, "1e4");
test::(9, options, "9");
test::(99, options, "1e2");
test::(999, options, "1e3");
test::(9999, options, "1e4");
test::(99999, options, "1e5");
options = ToSciOptions::default();
options.set_scale(2);
options.set_include_trailing_zeros(true);
test::(0, options, "0.00");
test::(1, options, "1.00");
test::(10, options, "10.00");
test::(100, options, "100.00");
test::(1000, options, "1000.00");
test::(10000, options, "10000.00");
test::(9, options, "9.00");
test::(99, options, "99.00");
test::(999, options, "999.00");
test::(9999, options, "9999.00");
test::(99999, options, "99999.00");
options.set_include_trailing_zeros(false);
test::(0, options, "0");
test::(1, options, "1");
test::(10, options, "10");
test::(100, options, "100");
test::(1000, options, "1000");
test::(10000, options, "10000");
test::(9, options, "9");
test::(99, options, "99");
test::(999, options, "999");
test::(9999, options, "9999");
test::(99999, options, "99999");
options = ToSciOptions::default();
options.set_scale(0);
options.set_include_trailing_zeros(true); // doesn't matter when scale is 0
test::(0, options, "0");
test::(1, options, "1");
test::(10, options, "10");
test::(100, options, "100");
test::(1000, options, "1000");
test::(10000, options, "10000");
test::(9, options, "9");
test::(99, options, "99");
test::(999, options, "999");
test::(9999, options, "9999");
test::(99999, options, "99999");
options.set_include_trailing_zeros(false);
test::(0, options, "0");
test::(1, options, "1");
test::(10, options, "10");
test::(100, options, "100");
test::(1000, options, "1000");
test::(10000, options, "10000");
test::(9, options, "9");
test::(99, options, "99");
test::(999, options, "999");
test::(9999, options, "9999");
test::(99999, options, "99999");
options = ToSciOptions::default();
options.set_precision(2);
options.set_rounding_mode(Nearest); // This is the default
test::(123, options, "1.2e2");
options.set_rounding_mode(Down);
test::(123, options, "1.2e2");
options.set_rounding_mode(Floor);
test::(123, options, "1.2e2");
options.set_rounding_mode(Up);
test::(123, options, "1.3e2");
options.set_rounding_mode(Ceiling);
test::(123, options, "1.3e2");
options.set_rounding_mode(Nearest);
test::(135, options, "1.4e2");
options.set_rounding_mode(Down);
test::(135, options, "1.3e2");
options.set_rounding_mode(Floor);
test::(135, options, "1.3e2");
options.set_rounding_mode(Up);
test::(135, options, "1.4e2");
options.set_rounding_mode(Ceiling);
test::(135, options, "1.4e2");
options.set_rounding_mode(Exact);
test::(140, options, "1.4e2");
options.set_rounding_mode(Nearest);
test::(999, options, "1e3");
options.set_rounding_mode(Down);
test::(999, options, "9.9e2");
options.set_rounding_mode(Floor);
test::(999, options, "9.9e2");
options.set_rounding_mode(Up);
test::(999, options, "1e3");
options.set_rounding_mode(Ceiling);
test::(999, options, "1e3");
let mut options = ToSciOptions::default();
options.set_include_trailing_zeros(true);
test::(0, options, "0.000000000000000");
test::(1, options, "1.000000000000000");
test::(10, options, "10.00000000000000");
test::(100, options, "100.0000000000000");
test::(1000, options, "1000.000000000000");
test::(10000, options, "10000.00000000000");
test::(100000, options, "100000.0000000000");
test::(1000000, options, "1000000.000000000");
test::(10000000, options, "10000000.00000000");
test::(100000000, options, "100000000.0000000");
test::(1000000000, options, "1000000000.000000");
test::(10000000000, options, "10000000000.00000");
test::(100000000000, options, "100000000000.0000");
test::(1000000000000, options, "1000000000000.000");
test::(10000000000000, options, "10000000000000.00");
test::(100000000000000, options, "100000000000000.0");
test::(1000000000000000, options, "1000000000000000");
test::(10000000000000000, options, "1.000000000000000e16");
test::(100000000000000000, options, "1.000000000000000e17");
test::(i64::MAX, options, "9.223372036854776e18");
test::(i128::MAX, options, "1.701411834604692e38");
test::(-1, options, "-1.000000000000000");
test::(-10, options, "-10.00000000000000");
test::(-100, options, "-100.0000000000000");
test::(-1000, options, "-1000.000000000000");
test::(-10000, options, "-10000.00000000000");
test::(-100000, options, "-100000.0000000000");
test::(-1000000, options, "-1000000.000000000");
test::(-10000000, options, "-10000000.00000000");
test::(-100000000, options, "-100000000.0000000");
test::(-1000000000, options, "-1000000000.000000");
test::(-10000000000, options, "-10000000000.00000");
test::(-100000000000, options, "-100000000000.0000");
test::