From 48e6f04610f9f462f87dd0b3f53841c98568a392 Mon Sep 17 00:00:00 2001 From: Mikhail Hogrefe Date: Thu, 5 Sep 2024 00:57:41 -0400 Subject: [PATCH] added Float division --- Cargo.lock | 52 +- Cargo.toml | 8 +- additional-lints.py | 16 +- docs/index.md | 8 +- malachite-base/Cargo.toml | 2 +- malachite-base/src/bools/random.rs | 4 +- .../src/num/arithmetic/reciprocal.rs | 20 +- malachite-base/src/num/random/geometric.rs | 4 +- malachite-base/src/num/random/mod.rs | 86 +- .../src/rational_sequences/conversion.rs | 4 +- .../src/rational_sequences/exhaustive.rs | 2 +- malachite-base/src/slices/mod.rs | 2 +- .../src/test_util/generators/random.rs | 30 +- .../test_util/generators/special_random.rs | 4 +- .../bools/random/get_weighted_random_bool.rs | 10 +- .../tests/num/arithmetic/mod_add.rs | 11 +- .../tests/num/arithmetic/mod_inverse.rs | 8 +- .../tests/num/arithmetic/mod_mul.rs | 12 +- .../tests/num/arithmetic/mod_neg.rs | 6 +- .../tests/num/arithmetic/mod_pow.rs | 13 +- .../tests/num/arithmetic/mod_shl.rs | 19 +- .../tests/num/arithmetic/mod_shr.rs | 10 +- .../tests/num/arithmetic/mod_square.rs | 6 +- .../tests/num/arithmetic/mod_sub.rs | 12 +- ...tric_random_signed_from_inclusive_range.rs | 12 +- .../next_bit_chunk.rs | 8 +- .../variable_range_generator/next_bool.rs | 4 +- .../next_in_inclusive_range.rs | 6 +- .../variable_range_generator/next_in_range.rs | 6 +- .../next_less_than.rs | 6 +- malachite-criterion-bench/Cargo.toml | 6 +- malachite-float/Cargo.toml | 8 +- malachite-float/src/arithmetic/add.rs | 451 +- malachite-float/src/arithmetic/div.rs | 6268 ++++++ .../src/arithmetic/is_power_of_2.rs | 20 + malachite-float/src/arithmetic/mod.rs | 13 +- malachite-float/src/arithmetic/mul.rs | 1065 +- malachite-float/src/arithmetic/reciprocal.rs | 867 + malachite-float/src/arithmetic/square.rs | 141 +- malachite-float/src/arithmetic/sub.rs | 436 +- malachite-float/src/basic/constants.rs | 16 +- malachite-float/src/basic/get_and_set.rs | 216 +- .../bin_util/demo_and_bench/arithmetic/add.rs | 149 +- .../bin_util/demo_and_bench/arithmetic/div.rs | 3663 ++++ .../bin_util/demo_and_bench/arithmetic/mod.rs | 4 + .../bin_util/demo_and_bench/arithmetic/mul.rs | 265 +- .../demo_and_bench/arithmetic/reciprocal.rs | 781 + .../demo_and_bench/arithmetic/square.rs | 74 +- .../bin_util/demo_and_bench/arithmetic/sub.rs | 147 +- .../demo_and_bench/basic/constants.rs | 8 +- .../demo_and_bench/basic/get_and_set.rs | 187 +- .../bin_util/demo_and_bench/constants/mod.rs | 17 + .../constants/prime_constant.rs | 129 + .../constants/thue_morse_constant.rs | 134 + .../demo_and_bench/conversion/from_integer.rs | 73 + .../demo_and_bench/conversion/from_natural.rs | 73 + .../conversion/from_primitive_int.rs | 188 +- .../conversion/from_rational.rs | 65 + .../src/bin_util/demo_and_bench/mod.rs | 2 + malachite-float/src/constants/mod.rs | 14 + .../src/constants/prime_constant.rs | 116 + .../src/constants/thue_morse_constant.rs | 183 + malachite-float/src/conversion/from_bits.rs | 262 + .../src/conversion/from_integer.rs | 142 +- .../src/conversion/from_natural.rs | 368 +- .../src/conversion/from_primitive_int.rs | 208 +- .../src/conversion/from_rational.rs | 252 +- malachite-float/src/conversion/mod.rs | 2 + malachite-float/src/lib.rs | 3 + .../src/test_util/arithmetic/add.rs | 85 +- .../src/test_util/arithmetic/div.rs | 158 + .../src/test_util/arithmetic/mod.rs | 2 + .../src/test_util/arithmetic/mul.rs | 87 +- .../src/test_util/arithmetic/reciprocal.rs | 43 + .../src/test_util/arithmetic/square.rs | 22 +- .../src/test_util/arithmetic/sub.rs | 94 +- .../src/test_util/bench/bucketers.rs | 126 + .../src/test_util/constants/mod.rs | 10 + .../src/test_util/constants/prime_constant.rs | 16 + .../constants/thue_morse_constant.rs | 16 + .../src/test_util/generators/common.rs | 68 + .../src/test_util/generators/exhaustive.rs | 610 +- .../src/test_util/generators/mod.rs | 558 +- .../src/test_util/generators/random.rs | 591 +- .../test_util/generators/special_random.rs | 653 +- malachite-float/src/test_util/mod.rs | 1 + malachite-float/tests/arithmetic/add.rs | 217 +- malachite-float/tests/arithmetic/div.rs | 16263 ++++++++++++++++ malachite-float/tests/arithmetic/mul.rs | 386 +- .../tests/arithmetic/reciprocal.rs | 2803 +++ malachite-float/tests/arithmetic/shl.rs | 2 + malachite-float/tests/arithmetic/shr.rs | 17 +- malachite-float/tests/arithmetic/square.rs | 45 +- malachite-float/tests/arithmetic/sub.rs | 215 +- malachite-float/tests/basic/get_and_set.rs | 63 +- .../tests/constants/prime_constant.rs | 338 + .../tests/constants/thue_morse_constant.rs | 338 + .../tests/conversion/from_integer.rs | 47 + .../tests/conversion/from_natural.rs | 116 + .../tests/conversion/from_primitive_int.rs | 154 +- .../tests/conversion/from_rational.rs | 116 + malachite-float/tests/lib.rs | 7 +- malachite-nz/Cargo.toml | 4 +- malachite-nz/src/integer/random/mod.rs | 362 +- .../src/natural/arithmetic/float_add.rs | 22 - .../src/natural/arithmetic/float_div.rs | 1782 ++ .../src/natural/arithmetic/float_extras.rs | 57 + .../src/natural/arithmetic/float_mul.rs | 2 +- .../natural/arithmetic/float_reciprocal.rs | 885 + .../src/natural/arithmetic/float_sub.rs | 2 +- .../src/natural/arithmetic/log_base.rs | 2 +- malachite-nz/src/natural/arithmetic/mod.rs | 4 + malachite-nz/src/natural/random/mod.rs | 156 +- .../src/test_util/generators/random.rs | 6 +- ...t_random_integer_from_range_to_infinity.rs | 90 +- ...integer_from_range_to_negative_infinity.rs | 95 +- ...ped_random_integer_from_inclusive_range.rs | 141 + .../get_striped_random_integer_from_range.rs | 129 + ...d_random_integer_from_range_to_infinity.rs | 167 + ...integer_from_range_to_negative_infinity.rs | 158 + ...orm_random_integer_from_inclusive_range.rs | 64 + .../get_uniform_random_integer_from_range.rs | 56 + ...iform_random_integer_in_inclusive_range.rs | 44 - .../get_uniform_random_integer_in_range.rs | 44 - malachite-nz/tests/lib.rs | 10 +- .../random/get_random_natural_less_than.rs | 45 +- .../random/get_random_natural_with_bits.rs | 70 +- .../get_random_natural_with_up_to_bits.rs | 74 +- ...ped_random_natural_from_inclusive_range.rs | 118 + .../get_striped_random_natural_from_range.rs | 117 + .../get_striped_random_natural_with_bits.rs | 208 +- ..._striped_random_natural_with_up_to_bits.rs | 205 +- malachite-q/Cargo.toml | 6 +- malachite-q/src/arithmetic/log_base.rs | 2 +- .../src/conversion/string/from_sci_string.rs | 10 +- malachite-q/src/random/mod.rs | 264 +- .../src/test_util/generators/random.rs | 1 - malachite-q/tests/lib.rs | 2 + ...riped_random_rational_range_to_infinity.rs | 429 + ...dom_rational_range_to_negative_infinity.rs | 429 + malachite/Cargo.toml | 10 +- 141 files changed, 46093 insertions(+), 1853 deletions(-) create mode 100644 malachite-float/src/arithmetic/div.rs create mode 100644 malachite-float/src/arithmetic/reciprocal.rs create mode 100644 malachite-float/src/bin_util/demo_and_bench/arithmetic/div.rs create mode 100644 malachite-float/src/bin_util/demo_and_bench/arithmetic/reciprocal.rs create mode 100644 malachite-float/src/bin_util/demo_and_bench/constants/mod.rs create mode 100644 malachite-float/src/bin_util/demo_and_bench/constants/prime_constant.rs create mode 100644 malachite-float/src/bin_util/demo_and_bench/constants/thue_morse_constant.rs create mode 100644 malachite-float/src/constants/mod.rs create mode 100644 malachite-float/src/constants/prime_constant.rs create mode 100644 malachite-float/src/constants/thue_morse_constant.rs create mode 100644 malachite-float/src/conversion/from_bits.rs create mode 100644 malachite-float/src/test_util/arithmetic/div.rs create mode 100644 malachite-float/src/test_util/arithmetic/reciprocal.rs create mode 100644 malachite-float/src/test_util/constants/mod.rs create mode 100644 malachite-float/src/test_util/constants/prime_constant.rs create mode 100644 malachite-float/src/test_util/constants/thue_morse_constant.rs create mode 100644 malachite-float/tests/arithmetic/div.rs create mode 100644 malachite-float/tests/arithmetic/reciprocal.rs create mode 100644 malachite-float/tests/constants/prime_constant.rs create mode 100644 malachite-float/tests/constants/thue_morse_constant.rs create mode 100644 malachite-nz/src/natural/arithmetic/float_div.rs create mode 100644 malachite-nz/src/natural/arithmetic/float_reciprocal.rs create mode 100644 malachite-nz/tests/integer/random/get_striped_random_integer_from_inclusive_range.rs create mode 100644 malachite-nz/tests/integer/random/get_striped_random_integer_from_range.rs create mode 100644 malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_infinity.rs create mode 100644 malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_negative_infinity.rs create mode 100644 malachite-nz/tests/integer/random/get_uniform_random_integer_from_inclusive_range.rs create mode 100644 malachite-nz/tests/integer/random/get_uniform_random_integer_from_range.rs delete mode 100644 malachite-nz/tests/integer/random/get_uniform_random_integer_in_inclusive_range.rs delete mode 100644 malachite-nz/tests/integer/random/get_uniform_random_integer_in_range.rs create mode 100644 malachite-nz/tests/natural/random/get_striped_random_natural_from_inclusive_range.rs create mode 100644 malachite-nz/tests/natural/random/get_striped_random_natural_from_range.rs create mode 100644 malachite-q/tests/random/striped_random_rational_range_to_infinity.rs create mode 100644 malachite-q/tests/random/striped_random_rational_range_to_negative_infinity.rs diff --git a/Cargo.lock b/Cargo.lock index 8819566c5..9de0e7fc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -387,9 +387,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.157" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374af5f94e54fa97cf75e945cce8a6b201e88a1a07e688b47dfd2a59c66dbd86" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libm" @@ -415,7 +415,7 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "malachite" -version = "0.4.15" +version = "0.4.16" dependencies = [ "embed-doc-image", "malachite-base", @@ -427,7 +427,7 @@ dependencies = [ [[package]] name = "malachite-base" -version = "0.4.15" +version = "0.4.16" dependencies = [ "clap", "getrandom", @@ -447,7 +447,7 @@ dependencies = [ [[package]] name = "malachite-criterion-bench" -version = "0.4.15" +version = "0.4.16" dependencies = [ "criterion", "malachite-base", @@ -458,7 +458,7 @@ dependencies = [ [[package]] name = "malachite-float" -version = "0.4.15" +version = "0.4.16" dependencies = [ "itertools 0.11.0", "malachite-base", @@ -473,7 +473,7 @@ dependencies = [ [[package]] name = "malachite-nz" -version = "0.4.15" +version = "0.4.16" dependencies = [ "embed-doc-image", "indoc", @@ -491,7 +491,7 @@ dependencies = [ [[package]] name = "malachite-q" -version = "0.4.15" +version = "0.4.16" dependencies = [ "itertools 0.11.0", "malachite-base", @@ -746,7 +746,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -759,14 +759,14 @@ dependencies = [ "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -856,9 +856,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rug" -version = "1.25.0" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d157703b9f96e9be75c739e7030d1d81be377d882d93046670309381517772" +checksum = "9f86bdefce0edcc5493a2c5a2c87e57a40c78c772a7e6c48f25550e89815772b" dependencies = [ "az", "gmp-mpfr-sys", @@ -890,9 +890,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] @@ -909,20 +909,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -965,9 +965,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -1092,7 +1092,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-shared", ] @@ -1114,7 +1114,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1266,5 +1266,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] diff --git a/Cargo.toml b/Cargo.toml index 8f1d99320..21fb4889c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" rust-version = "1.74.0" [workspace.dependencies] -malachite-base = { version = "0.4.15", path = 'malachite-base' } -malachite-nz = { version = "0.4.15", path = 'malachite-nz', default_features = false } -malachite-q = { version = "0.4.15", path = 'malachite-q' } -malachite-float = { version = "0.4.15", path = 'malachite-float' } +malachite-base = { version = "0.4.16", path = 'malachite-base' } +malachite-nz = { version = "0.4.16", path = 'malachite-nz', default_features = false } +malachite-q = { version = "0.4.16", path = 'malachite-q' } +malachite-float = { version = "0.4.16", path = 'malachite-float' } [profile.release] lto = "fat" diff --git a/additional-lints.py b/additional-lints.py index 143697787..90bc6e23c 100644 --- a/additional-lints.py +++ b/additional-lints.py @@ -20,7 +20,7 @@ ('./malachite-base/src/num/exhaustive/mod.rs', 1074), ('./malachite-float/src/conversion/mantissa_and_exponent.rs', 452), ('./malachite-float/src/conversion/mantissa_and_exponent.rs', 641), - ('./malachite-float/src/conversion/mod.rs', 225), + ('./malachite-float/src/conversion/mod.rs', 227), ('./malachite-float/src/lib.rs', 24), ('./malachite-nz/src/integer/arithmetic/mod.rs', 39), ('./malachite-nz/src/integer/arithmetic/mod.rs', 40), @@ -37,13 +37,13 @@ ('./malachite-nz/src/natural/arithmetic/mod.rs', 46), ('./malachite-nz/src/natural/arithmetic/mod.rs', 47), ('./malachite-nz/src/natural/arithmetic/mod.rs', 48), - ('./malachite-nz/src/natural/arithmetic/mod.rs', 154), - ('./malachite-nz/src/natural/arithmetic/mod.rs', 155), - ('./malachite-nz/src/natural/arithmetic/mod.rs', 178), - ('./malachite-nz/src/natural/arithmetic/mod.rs', 179), - ('./malachite-nz/src/natural/arithmetic/mod.rs', 180), - ('./malachite-nz/src/natural/arithmetic/mod.rs', 563), - ('./malachite-nz/src/natural/arithmetic/mod.rs', 565), + ('./malachite-nz/src/natural/arithmetic/mod.rs', 158), + ('./malachite-nz/src/natural/arithmetic/mod.rs', 159), + ('./malachite-nz/src/natural/arithmetic/mod.rs', 182), + ('./malachite-nz/src/natural/arithmetic/mod.rs', 183), + ('./malachite-nz/src/natural/arithmetic/mod.rs', 184), + ('./malachite-nz/src/natural/arithmetic/mod.rs', 567), + ('./malachite-nz/src/natural/arithmetic/mod.rs', 569), ('./malachite-nz/src/natural/conversion/digits/power_of_2_digit_iterable.rs', 528), ('./malachite-nz/src/natural/conversion/digits/power_of_2_digit_iterable.rs', 530), ('./malachite-nz/src/natural/conversion/digits/power_of_2_digit_iterable.rs', 833), diff --git a/docs/index.md b/docs/index.md index f7c8a59d8..901049a27 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,8 +3,8 @@

Malachite is an arbitrary-precision arithmetic library for [Rust](https://www.rust-lang.org/). It -achieves high performance in part by using algorithms derived from [GMP](https://gmplib.org/) and -[FLINT](https://www.flintlib.org/). +achieves high performance in part by using algorithms derived from [GMP](https://gmplib.org/), +[FLINT](https://www.flintlib.org/), and [MPFR](https://www.mpfr.org/). ```rust use malachite::num::arithmetic::traits::Factorial; @@ -53,14 +53,14 @@ Malachite uses `no_std`, unless the `random`, `test_build`, or `bin_build` featu To use Malachite, add the following to your project's `Cargo.toml` file: ```yaml [dependencies.malachite] -version = "0.4.15" +version = "0.4.16" ``` By default, all of Malachite's features are included, but you can opt out of some of them. For example, if you want to use `Natural` and `Integer` but not `Rational`, you can instead use ```yaml [dependencies.malachite] -version = "0.4.15" +version = "0.4.16" default-features = false features = [ "naturals_and_integers" ] ``` diff --git a/malachite-base/Cargo.toml b/malachite-base/Cargo.toml index 7e94e30aa..271ae9e29 100644 --- a/malachite-base/Cargo.toml +++ b/malachite-base/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "malachite-base" -version = "0.4.15" +version = "0.4.16" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true diff --git a/malachite-base/src/bools/random.rs b/malachite-base/src/bools/random.rs index d10f2adb7..af00b5e35 100644 --- a/malachite-base/src/bools/random.rs +++ b/malachite-base/src/bools/random.rs @@ -157,11 +157,11 @@ pub fn weighted_random_bools( /// # Examples /// ``` /// use malachite_base::bools::random::get_weighted_random_bool; -/// use malachite_base::num::random::variable_range_generator; +/// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( -/// get_weighted_random_bool(&mut variable_range_generator(EXAMPLE_SEED), 1, 10), +/// get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 10), /// false /// ); /// ``` diff --git a/malachite-base/src/num/arithmetic/reciprocal.rs b/malachite-base/src/num/arithmetic/reciprocal.rs index a5e3106eb..2825ec0d8 100644 --- a/malachite-base/src/num/arithmetic/reciprocal.rs +++ b/malachite-base/src/num/arithmetic/reciprocal.rs @@ -16,15 +16,15 @@ macro_rules! impl_reciprocal { /// Takes the reciprocal of a floating-point number. /// /// $$ - /// f(x) = 1/x+\epsilon. + /// f(x) = 1/x+\varepsilon. /// $$ /// Let $p$ be the precision of the input float (typically 24 for `f32`s and 53 for /// `f64`s, unless the float is subnormal). - /// - If $1/x$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be - /// 0. - /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to + /// be 0. + /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$. - /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < + /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. @@ -50,13 +50,13 @@ macro_rules! impl_reciprocal { impl ReciprocalAssign for $t { /// Takes the reciprocal of a floating-point number, in place. /// - /// $x \gets 1/x+\epsilon$. Let $p$ be the precision of the input float (typically 24 + /// $x \gets 1/x+\varepsilon$. Let $p$ be the precision of the input float (typically 24 /// for `f32`s and 53 for `f64`s, unless the float is subnormal). - /// - If $1/x$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be - /// 0. - /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to + /// be 0. + /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$. - /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < + /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// See the `reciprocal` documentation for information on special cases. diff --git a/malachite-base/src/num/random/geometric.rs b/malachite-base/src/num/random/geometric.rs index 6ebc60984..c7d446977 100644 --- a/malachite-base/src/num/random/geometric.rs +++ b/malachite-base/src/num/random/geometric.rs @@ -1450,12 +1450,12 @@ pub fn geometric_random_signed_inclusive_range( /// # Examples /// ``` /// use malachite_base::num::random::geometric::get_geometric_random_signed_from_inclusive_range; -/// use malachite_base::num::random::variable_range_generator; +/// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// get_geometric_random_signed_from_inclusive_range::( -/// &mut variable_range_generator(EXAMPLE_SEED), +/// &mut VariableRangeGenerator::new(EXAMPLE_SEED), /// -100, /// 99, /// 30, diff --git a/malachite-base/src/num/random/mod.rs b/malachite-base/src/num/random/mod.rs index 49646a9de..e189637ec 100644 --- a/malachite-base/src/num/random/mod.rs +++ b/malachite-base/src/num/random/mod.rs @@ -1473,7 +1473,7 @@ pub fn special_random_positive_finite_primitive_floats( mean_sci_exponent_denominator, ), range_map: HashMap::new(), - ranges: variable_range_generator(seed.fork("ranges")), + ranges: VariableRangeGenerator::new(seed.fork("ranges")), mean_precision_n: mean_precision_numerator, mean_precision_d: mean_precision_denominator, phantom: PhantomData, @@ -2110,7 +2110,7 @@ fn special_random_positive_finite_float_inclusive_range( mean_precision_numerator, mean_precision_denominator, ), - ranges: variable_range_generator(seed.fork("ranges")), + ranges: VariableRangeGenerator::new(seed.fork("ranges")), } } @@ -2470,7 +2470,7 @@ pub fn special_random_primitive_float_inclusive_range( /// Generates unsigneds sampled from ranges. A single generator can sample from different ranges of /// different types. /// -/// This `struct` is created by [`variable_range_generator`]; see its documentation for more. +/// This `struct` is created by [`VariableRangeGenerator::new`]; see its documentation for more. #[derive(Clone, Debug)] pub struct VariableRangeGenerator { xs: RandomPrimitiveInts, @@ -2480,6 +2480,36 @@ pub struct VariableRangeGenerator { } impl VariableRangeGenerator { + /// Generates unsigneds sampled from ranges. A single generator can sample from different ranges + /// of different types. + /// + /// If you only need to generate values from a single range, it is slightly more efficient to + /// use [`random_unsigned_bit_chunks`], [`random_unsigneds_less_than`], + /// [`random_unsigned_range`], or [`random_unsigned_inclusive_range`]. + /// + /// # Worst-case complexity + /// Constant time and additional memory. + /// + /// # Examples + /// ``` + /// use malachite_base::num::random::VariableRangeGenerator; + /// use malachite_base::random::EXAMPLE_SEED; + /// + /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); + /// assert_eq!(generator.next_bit_chunk::(10), 881); + /// assert_eq!(generator.next_less_than::(100), 34); + /// assert_eq!(generator.next_in_range::(10, 20), 16); + /// assert_eq!(generator.next_in_inclusive_range::(10, 20), 14); + /// ``` + pub fn new(seed: Seed) -> VariableRangeGenerator { + VariableRangeGenerator { + xs: random_primitive_ints(seed), + x: 0, + in_inner_loop: false, + remaining_x_bits: 0, + } + } + /// Uniformly generates a `bool`. /// /// $$ @@ -2491,11 +2521,11 @@ impl VariableRangeGenerator { /// /// # Examples /// ``` - /// use malachite_base::num::random::variable_range_generator; + /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); - /// let mut generator = variable_range_generator(EXAMPLE_SEED); + /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_bool()); /// } @@ -2526,11 +2556,11 @@ impl VariableRangeGenerator { /// /// # Examples /// ``` - /// use malachite_base::num::random::variable_range_generator; + /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); - /// let mut generator = variable_range_generator(EXAMPLE_SEED); + /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_bit_chunk::(3)); /// } @@ -2585,11 +2615,11 @@ impl VariableRangeGenerator { /// /// # Examples /// ``` - /// use malachite_base::num::random::variable_range_generator; + /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); - /// let mut generator = variable_range_generator(EXAMPLE_SEED); + /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_less_than(10u8)); /// } @@ -2630,11 +2660,11 @@ impl VariableRangeGenerator { /// /// # Examples /// ``` - /// use malachite_base::num::random::variable_range_generator; + /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); - /// let mut generator = variable_range_generator(EXAMPLE_SEED); + /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_in_range(10u8, 20)); /// } @@ -2663,11 +2693,11 @@ impl VariableRangeGenerator { /// /// # Examples /// ``` - /// use malachite_base::num::random::variable_range_generator; + /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); - /// let mut generator = variable_range_generator(EXAMPLE_SEED); + /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_in_inclusive_range(10u8, 19)); /// } @@ -2682,36 +2712,6 @@ impl VariableRangeGenerator { } } -/// Generates unsigneds sampled from ranges. A single generator can sample from different ranges of -/// different types. -/// -/// If you only need to generate values from a single range, it is slightly more efficient to use -/// [`random_unsigned_bit_chunks`], [`random_unsigneds_less_than`], [`random_unsigned_range`], or -/// [`random_unsigned_inclusive_range`]. -/// -/// # Worst-case complexity -/// Constant time and additional memory. -/// -/// # Examples -/// ``` -/// use malachite_base::num::random::variable_range_generator; -/// use malachite_base::random::EXAMPLE_SEED; -/// -/// let mut generator = variable_range_generator(EXAMPLE_SEED); -/// assert_eq!(generator.next_bit_chunk::(10), 881); -/// assert_eq!(generator.next_less_than::(100), 34); -/// assert_eq!(generator.next_in_range::(10, 20), 16); -/// assert_eq!(generator.next_in_inclusive_range::(10, 20), 14); -/// ``` -pub fn variable_range_generator(seed: Seed) -> VariableRangeGenerator { - VariableRangeGenerator { - xs: random_primitive_ints(seed), - x: 0, - in_inner_loop: false, - remaining_x_bits: 0, - } -} - /// Iterators that generate primitive integers from geometric-like distributions. pub mod geometric; diff --git a/malachite-base/src/rational_sequences/conversion.rs b/malachite-base/src/rational_sequences/conversion.rs index b79bff4ff..5de346427 100644 --- a/malachite-base/src/rational_sequences/conversion.rs +++ b/malachite-base/src/rational_sequences/conversion.rs @@ -37,7 +37,7 @@ impl RationalSequence { /// nonrepeating part and the second is the repeating part. /// /// # Worst-case complexity - /// $T(n, m) = O(n + m^{1+\epsilon})$ for all $\epsilon > 0$ + /// $T(n, m) = O(n + m^{1+\varepsilon})$ for all $\varepsilon > 0$ /// /// $M(n, m) = O(1)$ /// @@ -147,7 +147,7 @@ impl RationalSequence { /// part and the second is the repeating part. /// /// # Worst-case complexity - /// $T(n, m) = O(n + m^{1+\epsilon})$ for all $\epsilon > 0$ + /// $T(n, m) = O(n + m^{1+\varepsilon})$ for all $\varepsilon > 0$ /// /// $M(n, m) = O(n + m)$ /// diff --git a/malachite-base/src/rational_sequences/exhaustive.rs b/malachite-base/src/rational_sequences/exhaustive.rs index 2f17b62f4..933ddef47 100644 --- a/malachite-base/src/rational_sequences/exhaustive.rs +++ b/malachite-base/src/rational_sequences/exhaustive.rs @@ -47,7 +47,7 @@ where /// The output length is 1 if the input iterator is empty, and infinite otherwise. /// /// # Worst-case complexity per iteration -/// $T(i) = O(T^\prime(i) + (\log i)^{1+\epsilon})$ for all $\epsilon > 0$ +/// $T(i) = O(T^\prime(i) + (\log i)^{1+\varepsilon})$ for all $\varepsilon > 0$ /// /// $M(i) = O((\log i) M^\prime(i))$ /// diff --git a/malachite-base/src/slices/mod.rs b/malachite-base/src/slices/mod.rs index 86b78ee60..899447d4d 100644 --- a/malachite-base/src/slices/mod.rs +++ b/malachite-base/src/slices/mod.rs @@ -467,7 +467,7 @@ pub fn random_slice_permutations(seed: Seed, xs: &[T]) -> RandomSlicePermutat /// Typically $\ell = n$. /// /// # Worst-case complexity -/// $T(n) = O(n^{1+\epsilon})$ for all $\epsilon > 0$ +/// $T(n) = O(n^{1+\varepsilon})$ for all $\varepsilon > 0$ /// /// $M(n) = O(n)$ /// diff --git a/malachite-base/src/test_util/generators/random.rs b/malachite-base/src/test_util/generators/random.rs index ff31dc067..45db2f596 100644 --- a/malachite-base/src/test_util/generators/random.rs +++ b/malachite-base/src/test_util/generators/random.rs @@ -49,9 +49,9 @@ use crate::num::random::{ special_random_nonzero_finite_primitive_floats, special_random_positive_finite_primitive_floats, special_random_primitive_float_inclusive_range, special_random_primitive_float_range, - special_random_primitive_floats, variable_range_generator, RandomPrimitiveInts, - RandomUnsignedBitChunks, RandomUnsignedInclusiveRange, RandomUnsignedRange, - SpecialRandomNonzeroFiniteFloats, VariableRangeGenerator, + special_random_primitive_floats, RandomPrimitiveInts, RandomUnsignedBitChunks, + RandomUnsignedInclusiveRange, RandomUnsignedRange, SpecialRandomNonzeroFiniteFloats, + VariableRangeGenerator, }; use crate::random::{Seed, EXAMPLE_SEED}; use crate::rational_sequences::random::random_rational_sequences; @@ -224,7 +224,7 @@ fn random_positive_natural_floats( mean_exponent_numerator, mean_exponent_denominator, ), - ranges: variable_range_generator(seed.fork("mantissas")), + ranges: VariableRangeGenerator::new(seed.fork("mantissas")), phantom: PhantomData, } } @@ -3722,7 +3722,7 @@ pub fn random_unsigned_pair_gen_var_21(_config: &GenConfig T::WIDTH >> 1, 1, ), - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom: PhantomData, }) } @@ -3848,7 +3848,7 @@ pub fn random_unsigned_pair_gen_var_31(config: &GenConfig) config.get_or("mean_m_n", 4), config.get_or("mean_m_d", 1), ), - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), ms_to_n_limit: HashMap::new(), phantom: PhantomData::<*const T>, }) @@ -4371,7 +4371,7 @@ impl Iterator for DigitStringGenerator { pub fn random_unsigned_string_pair_gen_var_1(config: &GenConfig) -> It<(u8, String)> { Box::new(DigitStringGenerator { - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), @@ -4420,7 +4420,7 @@ impl Iterator for TargetedIntegerFromStringBaseInputs { pub fn random_unsigned_string_pair_gen_var_3(config: &GenConfig) -> It<(u8, String)> { Box::new(TargetedIntegerFromStringBaseInputs { uss: Box::new(DigitStringGenerator { - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), @@ -4892,7 +4892,7 @@ pub fn random_string_from_sci_string_options_pair_gen_var_1( ) -> It<(String, FromSciStringOptions)> { Box::new(SciDigitStringGenerator { options: random_from_sci_string_options(EXAMPLE_SEED.fork("options")), - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), @@ -4927,7 +4927,7 @@ pub fn random_string_from_sci_string_options_pair_gen_var_3( Box::new( SciDigitStringGenerator { options: random_from_sci_string_options(EXAMPLE_SEED.fork("options")), - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), @@ -4961,7 +4961,7 @@ pub fn random_string_unsigned_pair_gen_var_1(config: &GenConfig) -> It<(String, pub fn random_string_unsigned_pair_gen_var_2(config: &GenConfig) -> It<(String, u8)> { Box::new( SciDigitStringGenerator2 { - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), @@ -7455,7 +7455,7 @@ pub fn random_unsigned_vec_unsigned_pair_gen_var_1 It<(Vec, T)> { Box::new(DigitsDesc:: { - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom_t: PhantomData, phantom_u: PhantomData, }) @@ -7630,7 +7630,7 @@ pub fn random_unsigned_vec_unsigned_pair_gen_var_7( config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom: PhantomData, }) } diff --git a/malachite-base/src/test_util/generators/special_random.rs b/malachite-base/src/test_util/generators/special_random.rs index e6ed6936f..b155ac030 100644 --- a/malachite-base/src/test_util/generators/special_random.rs +++ b/malachite-base/src/test_util/generators/special_random.rs @@ -55,7 +55,7 @@ use crate::num::random::{ random_finite_primitive_floats, random_nonzero_finite_primitive_floats, random_positive_finite_primitive_floats, random_primitive_float_inclusive_range, random_primitive_float_range, random_primitive_floats, random_unsigneds_less_than, - variable_range_generator, RandomPrimitiveFloatInclusiveRange, VariableRangeGenerator, + RandomPrimitiveFloatInclusiveRange, VariableRangeGenerator, }; use crate::random::{Seed, EXAMPLE_SEED}; use crate::rational_sequences::random::random_rational_sequences; @@ -6425,7 +6425,7 @@ pub fn special_random_unsigned_vec_unsigned_pair_gen_var_1< config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), - ranges: variable_range_generator(EXAMPLE_SEED.fork("ranges")), + ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom_t: PhantomData, phantom_u: PhantomData, }) diff --git a/malachite-base/tests/bools/random/get_weighted_random_bool.rs b/malachite-base/tests/bools/random/get_weighted_random_bool.rs index 90a7c7004..f539b9767 100644 --- a/malachite-base/tests/bools/random/get_weighted_random_bool.rs +++ b/malachite-base/tests/bools/random/get_weighted_random_bool.rs @@ -7,12 +7,12 @@ // 3 of the License, or (at your option) any later version. See . use malachite_base::bools::random::get_weighted_random_bool; -use malachite_base::num::random::variable_range_generator; +use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; fn get_weighted_random_bool_helper(n: u64, d: u64, out: bool) { assert_eq!( - get_weighted_random_bool(&mut variable_range_generator(EXAMPLE_SEED), n, d), + get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), n, d), out ); } @@ -29,17 +29,17 @@ fn test_get_weighted_random_bool() { #[test] #[should_panic] fn get_weighted_random_bool_fail_1() { - get_weighted_random_bool(&mut variable_range_generator(EXAMPLE_SEED), 0, 0); + get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), 0, 0); } #[test] #[should_panic] fn get_weighted_random_bool_fail_2() { - get_weighted_random_bool(&mut variable_range_generator(EXAMPLE_SEED), 1, 0); + get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 0); } #[test] #[should_panic] fn get_weighted_random_bool_fail_3() { - get_weighted_random_bool(&mut variable_range_generator(EXAMPLE_SEED), 2, 1); + get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), 2, 1); } diff --git a/malachite-base/tests/num/arithmetic/mod_add.rs b/malachite-base/tests/num/arithmetic/mod_add.rs index 0ad450987..d9ea047b4 100644 --- a/malachite-base/tests/num/arithmetic/mod_add.rs +++ b/malachite-base/tests/num/arithmetic/mod_add.rs @@ -8,7 +8,8 @@ use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ - unsigned_pair_gen_var_16, unsigned_quadruple_gen_var_4, unsigned_triple_gen_var_12, + unsigned_pair_gen_var_16, unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_4, + unsigned_triple_gen_var_12, }; use std::panic::catch_unwind; @@ -102,6 +103,14 @@ fn mod_add_properties_helper() { assert_eq!(x.mod_add(x.mod_neg(m), m), T::ZERO); }); + unsigned_pair_gen_var_27::().test_properties(|(x, y)| { + assert_panic!(x.mod_add(y, T::ZERO)); + assert_panic!({ + let mut x = x; + x.mod_add_assign(y, T::ZERO); + }); + }); + unsigned_quadruple_gen_var_4::().test_properties(|(x, y, z, m)| { assert_eq!(x.mod_add(y, m).mod_add(z, m), x.mod_add(y.mod_add(z, m), m)); }); diff --git a/malachite-base/tests/num/arithmetic/mod_inverse.rs b/malachite-base/tests/num/arithmetic/mod_inverse.rs index ac3852338..06aa5ad75 100644 --- a/malachite-base/tests/num/arithmetic/mod_inverse.rs +++ b/malachite-base/tests/num/arithmetic/mod_inverse.rs @@ -10,7 +10,9 @@ use malachite_base::num::arithmetic::mod_inverse::mod_inverse_binary; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; -use malachite_base::test_util::generators::{unsigned_gen_var_6, unsigned_pair_gen_var_38}; +use malachite_base::test_util::generators::{ + unsigned_gen, unsigned_gen_var_6, unsigned_pair_gen_var_38, +}; use malachite_base::test_util::num::arithmetic::mod_inverse::mod_inverse_euclidean; use std::panic::catch_unwind; @@ -74,6 +76,10 @@ fn mod_inverse_properties_helper< assert_eq!(U::ONE.mod_inverse(m), Some(U::ONE)); assert_eq!((m - U::ONE).mod_inverse(m), Some(m - U::ONE)); }); + + unsigned_gen::().test_properties(|x| { + assert_panic!(x.mod_inverse(U::ZERO)); + }); } #[test] diff --git a/malachite-base/tests/num/arithmetic/mod_mul.rs b/malachite-base/tests/num/arithmetic/mod_mul.rs index 12237b1a0..a57eacf03 100644 --- a/malachite-base/tests/num/arithmetic/mod_mul.rs +++ b/malachite-base/tests/num/arithmetic/mod_mul.rs @@ -15,8 +15,8 @@ use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::test_util::generators::{ - unsigned_gen_var_12, unsigned_pair_gen_var_16, unsigned_quadruple_gen_var_4, - unsigned_quadruple_gen_var_5, unsigned_triple_gen_var_12, + unsigned_gen_var_12, unsigned_pair_gen_var_16, unsigned_pair_gen_var_27, + unsigned_quadruple_gen_var_4, unsigned_quadruple_gen_var_5, unsigned_triple_gen_var_12, }; use malachite_base::test_util::num::arithmetic::mod_mul::limbs_invert_limb_naive; use std::panic::catch_unwind; @@ -236,6 +236,14 @@ fn mod_mul_properties_helper() { } }); + unsigned_pair_gen_var_27::().test_properties(|(x, y)| { + assert_panic!(x.mod_mul(y, T::ZERO)); + assert_panic!({ + let mut x = x; + x.mod_mul_assign(y, T::ZERO); + }); + }); + unsigned_quadruple_gen_var_4::().test_properties(|(x, y, z, m)| { assert_eq!(x.mod_mul(y, m).mod_mul(z, m), x.mod_mul(y.mod_mul(z, m), m)); assert_eq!( diff --git a/malachite-base/tests/num/arithmetic/mod_neg.rs b/malachite-base/tests/num/arithmetic/mod_neg.rs index 028043994..30e11e001 100644 --- a/malachite-base/tests/num/arithmetic/mod_neg.rs +++ b/malachite-base/tests/num/arithmetic/mod_neg.rs @@ -8,7 +8,7 @@ use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ - unsigned_gen_var_1, unsigned_gen_var_6, unsigned_pair_gen_var_16, + unsigned_gen, unsigned_gen_var_1, unsigned_gen_var_6, unsigned_pair_gen_var_16, }; use std::panic::catch_unwind; @@ -82,6 +82,10 @@ fn mod_neg_properties_helper() { assert_eq!(T::ONE.mod_neg(m), m - T::ONE); assert_eq!((m - T::ONE).mod_neg(m), T::ONE); }); + + unsigned_gen::().test_properties(|x| { + assert_panic!(x.mod_neg(T::ZERO)); + }); } #[test] diff --git a/malachite-base/tests/num/arithmetic/mod_pow.rs b/malachite-base/tests/num/arithmetic/mod_pow.rs index e45f128aa..718c0c2fb 100644 --- a/malachite-base/tests/num/arithmetic/mod_pow.rs +++ b/malachite-base/tests/num/arithmetic/mod_pow.rs @@ -11,8 +11,9 @@ use malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ - unsigned_pair_gen_var_12, unsigned_pair_gen_var_16, unsigned_quadruple_gen_var_6, - unsigned_quadruple_gen_var_7, unsigned_triple_gen_var_14, unsigned_triple_gen_var_15, + unsigned_pair_gen, unsigned_pair_gen_var_12, unsigned_pair_gen_var_16, + unsigned_quadruple_gen_var_6, unsigned_quadruple_gen_var_7, unsigned_triple_gen_var_14, + unsigned_triple_gen_var_15, }; use malachite_base::test_util::num::arithmetic::mod_pow::naive_mod_pow; use std::panic::catch_unwind; @@ -143,6 +144,14 @@ fn mod_pow_properties_helper() { assert_eq!(x.mod_pow(2, m), x.mod_mul(x, m)); }); + unsigned_pair_gen::().test_properties(|(x, y)| { + assert_panic!(x.mod_pow(y, T::ZERO)); + assert_panic!({ + let mut x = x; + x.mod_pow_assign(y, T::ZERO); + }); + }); + unsigned_quadruple_gen_var_6::().test_properties(|(x, y, exp, m)| { assert_eq!( x.mod_mul(y, m).mod_pow(exp, m), diff --git a/malachite-base/tests/num/arithmetic/mod_shl.rs b/malachite-base/tests/num/arithmetic/mod_shl.rs index 9d2618b50..7ce68a4cb 100644 --- a/malachite-base/tests/num/arithmetic/mod_shl.rs +++ b/malachite-base/tests/num/arithmetic/mod_shl.rs @@ -13,7 +13,8 @@ use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{ signed_gen_var_5, signed_unsigned_pair_gen_var_13, unsigned_gen_var_5, - unsigned_pair_gen_var_16, unsigned_pair_gen_var_25, unsigned_signed_unsigned_triple_gen_var_2, + unsigned_pair_gen_var_16, unsigned_pair_gen_var_2, unsigned_pair_gen_var_25, + unsigned_signed_pair_gen_var_1, unsigned_signed_unsigned_triple_gen_var_2, unsigned_triple_gen_var_18, }; use std::panic::catch_unwind; @@ -100,6 +101,14 @@ fn mod_shl_properties_unsigned_unsigned_helper< assert_eq!(T::ZERO.mod_shl(u, m), T::ZERO); }); + unsigned_pair_gen_var_2::().test_properties(|(n, u)| { + assert_panic!(n.mod_shl(u, T::ZERO)); + assert_panic!({ + let mut n = n; + n.mod_shl_assign(u, T::ZERO); + }); + }); + unsigned_gen_var_5::().test_properties(|u| { assert_eq!(T::ZERO.mod_shl(u, T::ONE), T::ZERO); }); @@ -140,6 +149,14 @@ fn mod_shl_properties_unsigned_signed_helper< assert_eq!(T::ZERO.mod_shl(i, m), T::ZERO); }); + unsigned_signed_pair_gen_var_1::().test_properties(|(n, i)| { + assert_panic!(n.mod_shl(i, T::ZERO)); + assert_panic!({ + let mut n = n; + n.mod_shl_assign(i, T::ZERO); + }); + }); + signed_gen_var_5::().test_properties(|i| { assert_eq!(T::ZERO.mod_shl(i, T::ONE), T::ZERO); }); diff --git a/malachite-base/tests/num/arithmetic/mod_shr.rs b/malachite-base/tests/num/arithmetic/mod_shr.rs index 5dceecc62..c143be9b6 100644 --- a/malachite-base/tests/num/arithmetic/mod_shr.rs +++ b/malachite-base/tests/num/arithmetic/mod_shr.rs @@ -13,7 +13,7 @@ use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{ signed_gen_var_5, signed_unsigned_pair_gen_var_13, unsigned_pair_gen_var_16, - unsigned_signed_unsigned_triple_gen_var_2, + unsigned_signed_pair_gen_var_1, unsigned_signed_unsigned_triple_gen_var_2, }; use std::panic::catch_unwind; @@ -105,6 +105,14 @@ fn mod_shr_properties_helper< assert_eq!(T::ZERO.mod_shr(i, m), T::ZERO); }); + unsigned_signed_pair_gen_var_1::().test_properties(|(n, i)| { + assert_panic!(n.mod_shr(i, T::ZERO)); + assert_panic!({ + let mut n = n; + n.mod_shr_assign(i, T::ZERO); + }); + }); + signed_gen_var_5::().test_properties(|i| { assert_eq!(T::ZERO.mod_shl(i, T::ONE), T::ZERO); }); diff --git a/malachite-base/tests/num/arithmetic/mod_square.rs b/malachite-base/tests/num/arithmetic/mod_square.rs index bdf9ac738..15ec0665e 100644 --- a/malachite-base/tests/num/arithmetic/mod_square.rs +++ b/malachite-base/tests/num/arithmetic/mod_square.rs @@ -9,7 +9,7 @@ use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ - unsigned_gen_var_1, unsigned_pair_gen_var_16, unsigned_triple_gen_var_12, + unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_16, unsigned_triple_gen_var_12, }; use std::panic::catch_unwind; @@ -105,6 +105,10 @@ fn mod_square_properties_helper() { x.mod_square(m).mod_mul(y.mod_square(m), m) ); }); + + unsigned_gen::().test_properties(|x| { + assert_panic!(x.mod_square(T::ZERO)); + }); } #[test] diff --git a/malachite-base/tests/num/arithmetic/mod_sub.rs b/malachite-base/tests/num/arithmetic/mod_sub.rs index 877441564..5580b8d7a 100644 --- a/malachite-base/tests/num/arithmetic/mod_sub.rs +++ b/malachite-base/tests/num/arithmetic/mod_sub.rs @@ -7,7 +7,9 @@ // 3 of the License, or (at your option) any later version. See . use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; -use malachite_base::test_util::generators::{unsigned_pair_gen_var_16, unsigned_triple_gen_var_12}; +use malachite_base::test_util::generators::{ + unsigned_pair_gen_var_16, unsigned_pair_gen_var_27, unsigned_triple_gen_var_12, +}; use std::panic::catch_unwind; fn mod_sub_helper() { @@ -94,6 +96,14 @@ fn mod_sub_properties_helper() { assert_eq!(T::ZERO.mod_sub(x, m), x.mod_neg(m)); assert_eq!(x.mod_sub(x, m), T::ZERO); }); + + unsigned_pair_gen_var_27::().test_properties(|(x, y)| { + assert_panic!(x.mod_sub(y, T::ZERO)); + assert_panic!({ + let mut x = x; + x.mod_sub_assign(y, T::ZERO); + }); + }); } #[test] diff --git a/malachite-base/tests/num/random/geometric/get_geometric_random_signed_from_inclusive_range.rs b/malachite-base/tests/num/random/geometric/get_geometric_random_signed_from_inclusive_range.rs index 5f1aa8e1b..6cb136c05 100644 --- a/malachite-base/tests/num/random/geometric/get_geometric_random_signed_from_inclusive_range.rs +++ b/malachite-base/tests/num/random/geometric/get_geometric_random_signed_from_inclusive_range.rs @@ -7,7 +7,7 @@ // 3 of the License, or (at your option) any later version. See . use malachite_base::num::random::geometric::get_geometric_random_signed_from_inclusive_range; -use malachite_base::num::random::variable_range_generator; +use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; fn get_geometric_random_signed_from_inclusive_range_helper( @@ -19,7 +19,7 @@ fn get_geometric_random_signed_from_inclusive_range_helper( ) { assert_eq!( get_geometric_random_signed_from_inclusive_range( - &mut variable_range_generator(EXAMPLE_SEED), + &mut VariableRangeGenerator::new(EXAMPLE_SEED), a, b, abs_um_numerator, @@ -47,7 +47,7 @@ fn test_get_geometric_random_signed_from_inclusive_range() { #[should_panic] fn get_geometric_random_signed_from_inclusive_range_fail_1() { get_geometric_random_signed_from_inclusive_range( - &mut variable_range_generator(EXAMPLE_SEED), + &mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 0, 1, @@ -59,7 +59,7 @@ fn get_geometric_random_signed_from_inclusive_range_fail_1() { #[should_panic] fn get_geometric_random_signed_from_inclusive_range_fail_2() { get_geometric_random_signed_from_inclusive_range( - &mut variable_range_generator(EXAMPLE_SEED), + &mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 2, 1, @@ -71,7 +71,7 @@ fn get_geometric_random_signed_from_inclusive_range_fail_2() { #[should_panic] fn get_geometric_random_signed_from_inclusive_range_fail_3() { get_geometric_random_signed_from_inclusive_range( - &mut variable_range_generator(EXAMPLE_SEED), + &mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 2, 0, @@ -83,7 +83,7 @@ fn get_geometric_random_signed_from_inclusive_range_fail_3() { #[should_panic] fn get_geometric_random_signed_from_inclusive_range_fail_4() { get_geometric_random_signed_from_inclusive_range( - &mut variable_range_generator(EXAMPLE_SEED), + &mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 2, 1, diff --git a/malachite-base/tests/num/random/variable_range_generator/next_bit_chunk.rs b/malachite-base/tests/num/random/variable_range_generator/next_bit_chunk.rs index ac68d58db..1cd294807 100644 --- a/malachite-base/tests/num/random/variable_range_generator/next_bit_chunk.rs +++ b/malachite-base/tests/num/random/variable_range_generator/next_bit_chunk.rs @@ -7,12 +7,12 @@ // 3 of the License, or (at your option) any later version. See . use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; -use malachite_base::num::random::variable_range_generator; +use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; use std::panic::catch_unwind; fn next_bit_chunk_helper(chunk_size: u64, expected_values: &[T]) { - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(20); for _ in 0..20 { xs.push(range_generator.next_bit_chunk::(chunk_size)); @@ -49,11 +49,11 @@ fn test_next_bit_chunk() { fn next_bit_chunk_fail_helper() { assert_panic!({ - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_bit_chunk::(0) }); assert_panic!({ - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_bit_chunk::(T::WIDTH + 1) }); } diff --git a/malachite-base/tests/num/random/variable_range_generator/next_bool.rs b/malachite-base/tests/num/random/variable_range_generator/next_bool.rs index bc8e84536..adf91b5d6 100644 --- a/malachite-base/tests/num/random/variable_range_generator/next_bool.rs +++ b/malachite-base/tests/num/random/variable_range_generator/next_bool.rs @@ -6,12 +6,12 @@ // 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::random::variable_range_generator; +use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; #[test] fn test_next_bool() { - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(100); for _ in 0..100 { xs.push(range_generator.next_bool()); diff --git a/malachite-base/tests/num/random/variable_range_generator/next_in_inclusive_range.rs b/malachite-base/tests/num/random/variable_range_generator/next_in_inclusive_range.rs index bb8a04be7..47aa8c4aa 100644 --- a/malachite-base/tests/num/random/variable_range_generator/next_in_inclusive_range.rs +++ b/malachite-base/tests/num/random/variable_range_generator/next_in_inclusive_range.rs @@ -7,12 +7,12 @@ // 3 of the License, or (at your option) any later version. See . use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; -use malachite_base::num::random::variable_range_generator; +use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; use std::panic::catch_unwind; fn next_in_inclusive_range_helper(a: T, b: T, expected_values: &[T]) { - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(20); for _ in 0..20 { xs.push(range_generator.next_in_inclusive_range(a, b)); @@ -45,7 +45,7 @@ fn test_next_in_inclusive_range() { fn next_in_inclusive_range_fail_helper() { assert_panic!({ - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_in_inclusive_range(T::TWO, T::ONE); }); } diff --git a/malachite-base/tests/num/random/variable_range_generator/next_in_range.rs b/malachite-base/tests/num/random/variable_range_generator/next_in_range.rs index c99288e6b..c88119301 100644 --- a/malachite-base/tests/num/random/variable_range_generator/next_in_range.rs +++ b/malachite-base/tests/num/random/variable_range_generator/next_in_range.rs @@ -7,12 +7,12 @@ // 3 of the License, or (at your option) any later version. See . use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; -use malachite_base::num::random::variable_range_generator; +use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; use std::panic::catch_unwind; fn next_in_range_helper(a: T, b: T, expected_values: &[T]) { - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(20); for _ in 0..20 { xs.push(range_generator.next_in_range(a, b)); @@ -45,7 +45,7 @@ fn test_next_in_range() { fn next_in_range_fail_helper() { assert_panic!({ - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_in_range(T::TWO, T::TWO); }); } diff --git a/malachite-base/tests/num/random/variable_range_generator/next_less_than.rs b/malachite-base/tests/num/random/variable_range_generator/next_less_than.rs index 878f7d1c9..d615402aa 100644 --- a/malachite-base/tests/num/random/variable_range_generator/next_less_than.rs +++ b/malachite-base/tests/num/random/variable_range_generator/next_less_than.rs @@ -7,12 +7,12 @@ // 3 of the License, or (at your option) any later version. See . use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; -use malachite_base::num::random::variable_range_generator; +use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; use std::panic::catch_unwind; fn next_less_than_helper(limit: T, expected_values: &[T]) { - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(20); for _ in 0..20 { xs.push(range_generator.next_less_than(limit)); @@ -43,7 +43,7 @@ fn test_next_less_than() { fn next_less_than_fail_helper() { assert_panic!({ - let mut range_generator = variable_range_generator(EXAMPLE_SEED); + let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_less_than(T::ZERO); }); } diff --git a/malachite-criterion-bench/Cargo.toml b/malachite-criterion-bench/Cargo.toml index 2538128d2..2c34b2868 100644 --- a/malachite-criterion-bench/Cargo.toml +++ b/malachite-criterion-bench/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "malachite-criterion-bench" -version = "0.4.15" +version = "0.4.16" authors = ["Mikhail Hogrefe "] autobenches = false rust-version.workspace = true edition.workspace = true [dependencies] -malachite-base = { version = "0.4.15" } -malachite-nz = { version = "0.4.15", default-features = false } +malachite-base = { version = "0.4.16" } +malachite-nz = { version = "0.4.16", default-features = false } num = "0.4.1" rug = { version = "1.21.0", default-features = false, features = ["integer", "serde"] } diff --git a/malachite-float/Cargo.toml b/malachite-float/Cargo.toml index c0efa0732..4aecac5b2 100644 --- a/malachite-float/Cargo.toml +++ b/malachite-float/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "malachite-float" -version = "0.4.15" +version = "0.4.16" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true @@ -22,9 +22,9 @@ path = "src/bin.rs" [dependencies] itertools = { version = "0.11.0", default-features = false, features = ["use_alloc"] } -malachite-base = { version = "0.4.15", default-features = false } -malachite-nz = { version = "0.4.15", default-features = false, features = ["float_helpers"] } -malachite-q = { version = "0.4.15", default-features = false } +malachite-base = { version = "0.4.16", default-features = false } +malachite-nz = { version = "0.4.16", default-features = false, features = ["float_helpers"] } +malachite-q = { version = "0.4.16", default-features = false } serde = { version = "1.0.188", optional = true, default-features = false, features = ["alloc", "derive"] } serde_json = { version = "1.0.105", optional = true } diff --git a/malachite-float/src/arithmetic/add.rs b/malachite-float/src/arithmetic/add.rs index a902b7e8a..b1de981f3 100644 --- a/malachite-float/src/arithmetic/add.rs +++ b/malachite-float/src/arithmetic/add.rs @@ -199,11 +199,14 @@ impl Float { Equal } (x @ float_either_zero!(), z, subtract) => { - x.clone_from(z); + let (new_x, mut o) = + Float::from_float_prec_round_ref(z, prec, if subtract { -rm } else { rm }); + *x = new_x; if subtract { x.neg_assign(); + o = o.reverse(); } - x.set_prec_round(prec, rm) + o } (z, float_either_zero!(), _) => z.set_prec_round(prec, rm), ( @@ -304,15 +307,15 @@ impl Float { Equal, ), (float_either_zero!(), z, subtract) => { - let mut out = if subtract { -z } else { z.clone() }; - let o = out.set_prec_round(prec, rm); - (out, o) - } - (z, float_either_zero!(), _) => { - let mut out = z.clone(); - let o = out.set_prec_round(prec, rm); - (out, o) + let (mut x, mut o) = + Float::from_float_prec_round_ref(z, prec, if subtract { -rm } else { rm }); + if subtract { + x.neg_assign(); + o = o.reverse(); + } + (x, o) } + (z, float_either_zero!(), _) => Float::from_float_prec_round_ref(z, prec, rm), ( Float(Finite { sign: x_sign, @@ -392,13 +395,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x+y+\epsilon. + /// f(x,y,p,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -480,13 +483,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x+y+\epsilon. + /// f(x,y,p,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -568,13 +571,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x+y+\epsilon. + /// f(x,y,p,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -656,13 +659,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x+y+\epsilon. + /// f(x,y,p,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -744,10 +747,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x+y+\epsilon. + /// f(x,y,p) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -801,10 +804,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x+y+\epsilon. + /// f(x,y,p) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -858,10 +861,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x+y+\epsilon. + /// f(x,y,p) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -915,10 +918,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x+y+\epsilon. + /// f(x,y,p) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -970,13 +973,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x+y+\epsilon. + /// f(x,y,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1044,13 +1047,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x+y+\epsilon. + /// f(x,y,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1118,13 +1121,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x+y+\epsilon. + /// f(x,y,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1191,13 +1194,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x+y+\epsilon. + /// f(x,y,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1264,13 +1267,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1339,13 +1342,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1433,10 +1436,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1483,10 +1486,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1532,13 +1535,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1595,13 +1598,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1657,13 +1660,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x+y+\epsilon. + /// f(x,y,p,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1750,13 +1753,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x+y+\epsilon. + /// f(x,y,p,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1861,13 +1864,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x+y+\epsilon. + /// f(x,y,p,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1972,11 +1975,7 @@ impl Float { } } (float_zero!(), y) => Float::from_rational_prec_round(y, prec, rm), - (_, y) if y == 0 => { - let mut x = self.clone(); - let o = x.set_prec_round(prec, rm); - (x, o) - } + (_, y) if y == 0 => Float::from_float_prec_round_ref(self, prec, rm), (x, y) => { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; @@ -1986,9 +1985,7 @@ impl Float { let (q, o) = Float::from_rational_prec_ref(&y, working_prec); if o == Equal { // Result is exact so we can add it directly! - let mut x = self.clone(); - let o = x.add_prec_round_assign(q, prec, rm); - return (x, o); + return self.add_prec_round_ref_val(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let mut t = x.add_prec_ref_val(q, working_prec).0; @@ -2032,13 +2029,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x+y+\epsilon. + /// f(x,y,p,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2143,11 +2140,7 @@ impl Float { } } (float_zero!(), y) => Float::from_rational_prec_round_ref(y, prec, rm), - (_, y) if *y == 0 => { - let mut x = self.clone(); - let o = x.set_prec_round(prec, rm); - (x, o) - } + (_, y) if *y == 0 => Float::from_float_prec_round_ref(self, prec, rm), (x, y) => { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; @@ -2157,9 +2150,7 @@ impl Float { let (q, o) = Float::from_rational_prec_ref(y, working_prec); if o == Equal { // Result is exact so we can add it directly! - let mut x = self.clone(); - let o = x.add_prec_round_assign(q, prec, rm); - return (x, o); + return self.add_prec_round_ref_val(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let mut t = x.add_prec_ref_val(q, working_prec).0; @@ -2205,10 +2196,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x+y+\epsilon. + /// f(x,y,p) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2264,10 +2255,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x+y+\epsilon. + /// f(x,y,p) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2323,10 +2314,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x+y+\epsilon. + /// f(x,y,p) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2382,10 +2373,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x+y+\epsilon. + /// f(x,y,p) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2440,13 +2431,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x+y+\epsilon. + /// f(x,y,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2514,13 +2505,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x+y+\epsilon. + /// f(x,y,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2593,13 +2584,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x+y+\epsilon. + /// f(x,y,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2672,13 +2663,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x+y+\epsilon. + /// f(x,y,m) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2750,13 +2741,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2907,13 +2898,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -3066,10 +3057,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -3125,10 +3116,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -3183,13 +3174,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// @@ -3256,13 +3247,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// x \gets x+y+\epsilon. + /// x \gets x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// @@ -3335,10 +3326,10 @@ impl Add for Float { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -3399,10 +3390,10 @@ impl<'a> Add<&'a Float> for Float { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -3464,10 +3455,10 @@ impl<'a> Add for &'a Float { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -3529,10 +3520,10 @@ impl<'a, 'b> Add<&'a Float> for &'b Float { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -3593,10 +3584,10 @@ impl AddAssign for Float { /// rounding mode. /// /// $$ - /// x\gets = x+y+\epsilon. + /// x\gets = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `+` documentation for information on special cases. @@ -3668,10 +3659,10 @@ impl<'a> AddAssign<&'a Float> for Float { /// rounding mode. /// /// $$ - /// x\gets = x+y+\epsilon. + /// x\gets = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `+` documentation for information on special cases. @@ -3744,10 +3735,10 @@ impl Add for Float { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -3810,10 +3801,10 @@ impl<'a> Add<&'a Rational> for Float { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -3879,10 +3870,10 @@ impl<'a> Add for &'a Float { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -3947,10 +3938,10 @@ impl<'a, 'b> Add<&'a Rational> for &'b Float { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -4013,10 +4004,10 @@ impl AddAssign for Float { /// rounding mode. /// /// $$ - /// x\gets = x+y+\epsilon. + /// x\gets = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `+` documentation for information on special cases. @@ -4085,10 +4076,10 @@ impl<'a> AddAssign<&'a Rational> for Float { /// rounding mode. /// /// $$ - /// x\gets = x+y+\epsilon. + /// x\gets = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `+` documentation for information on special cases. @@ -4159,10 +4150,10 @@ impl Add for Rational { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -4220,10 +4211,10 @@ impl<'a> Add<&'a Float> for Rational { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -4284,10 +4275,10 @@ impl<'a> Add for &'a Rational { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -4347,10 +4338,10 @@ impl<'a, 'b> Add<&'a Float> for &'b Rational { /// rounding mode. /// /// $$ - /// f(x,y) = x+y+\epsilon. + /// f(x,y) = x+y+\varepsilon. /// $$ - /// - If $x+y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x+y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, + /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: diff --git a/malachite-float/src/arithmetic/div.rs b/malachite-float/src/arithmetic/div.rs new file mode 100644 index 000000000..fdbd971da --- /dev/null +++ b/malachite-float/src/arithmetic/div.rs @@ -0,0 +1,6268 @@ +// 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 crate::arithmetic::is_power_of_2::abs_is_power_of_2; +use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; +use crate::{float_either_infinity, float_either_zero, float_nan, Float}; +use core::cmp::max; +use core::cmp::Ordering::{self, *}; +use core::mem::swap; +use core::ops::{Div, DivAssign}; +use malachite_base::num::arithmetic::traits::{CheckedLogBase2, IsPowerOf2, NegAssign, Sign}; +use malachite_base::num::basic::traits::Zero as ZeroTrait; +use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::num::logic::traits::{NotAssign, SignificantBits}; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_nz::natural::arithmetic::float_div::{ + div_float_significands_in_place, div_float_significands_in_place_ref, + div_float_significands_ref_ref, div_float_significands_ref_val, +}; +use malachite_q::Rational; + +const DIV_RATIONAL_THRESHOLD: u64 = 50; +const RATIONAL_DIV_THRESHOLD: u64 = 50; + +fn div_rational_prec_round_assign_naive( + x: &mut Float, + y: Rational, + prec: u64, + rm: RoundingMode, +) -> Ordering { + assert_ne!(prec, 0); + match (&mut *x, y) { + (float_nan!(), _) => Equal, + (Float(Infinity { sign }), y) => { + if y < 0 { + sign.not_assign(); + }; + Equal + } + (Float(Zero { sign }), y) => { + match y.sign() { + Equal => *x = float_nan!(), + Greater => {} + Less => sign.not_assign(), + } + Equal + } + (x, y) => { + if y == 0 { + *x = Float(Infinity { sign: *x > 0u32 }); + Equal + } else { + let not_sign = *x < 0; + let mut z = Float::ZERO; + swap(x, &mut z); + let (mut quotient, o) = + Float::from_rational_prec_round(Rational::exact_from(z) / y, prec, rm); + if quotient == 0u32 && not_sign { + quotient.neg_assign(); + } + *x = quotient; + o + } + } + } +} + +fn div_rational_prec_round_assign_naive_ref( + x: &mut Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> Ordering { + assert_ne!(prec, 0); + match (&mut *x, y) { + (float_nan!(), _) => Equal, + (Float(Infinity { sign }), y) => { + if *y < 0 { + sign.not_assign(); + }; + Equal + } + (Float(Zero { sign }), y) => { + match y.sign() { + Equal => *x = float_nan!(), + Greater => {} + Less => sign.not_assign(), + } + Equal + } + (x, y) => { + if *y == 0 { + *x = Float(Infinity { sign: *x > 0u32 }); + Equal + } else { + let not_sign = *x < 0; + let mut z = Float::ZERO; + swap(x, &mut z); + let (mut quotient, o) = + Float::from_rational_prec_round(Rational::exact_from(z) / y, prec, rm); + if quotient == 0u32 && not_sign { + quotient.neg_assign(); + } + *x = quotient; + o + } + } + } +} + +pub_test! {div_rational_prec_round_naive( + mut x: Float, + y: Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + let o = div_rational_prec_round_assign_naive(&mut x, y, prec, rm); + (x, o) +}} + +pub_test! {div_rational_prec_round_naive_val_ref( + mut x: Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + let o = div_rational_prec_round_assign_naive_ref(&mut x, y, prec, rm); + (x, o) +}} + +pub_test! {div_rational_prec_round_naive_ref_val( + x: &Float, + y: Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (x, y) { + (float_nan!(), _) => (float_nan!(), Equal), + (Float(Infinity { sign }), y) => ( + if y >= 0u32 { + Float(Infinity { sign: *sign }) + } else { + Float(Infinity { sign: !*sign }) + }, + Equal, + ), + (Float(Zero { sign }), y) => ( + match y.sign() { + Equal => float_nan!(), + Greater => Float(Zero { sign: *sign }), + Less => Float(Zero { sign: !*sign }), + }, + Equal, + ), + (x, y) => { + if y == 0 { + (Float(Infinity { sign: *x > 0u32 }), Equal) + } else { + let (mut quotient, o) = + Float::from_rational_prec_round(Rational::exact_from(x) / y, prec, rm); + if quotient == 0u32 && *x < 0 { + quotient.neg_assign(); + } + (quotient, o) + } + } + } +}} + +pub_test! {div_rational_prec_round_naive_ref_ref( + x: &Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (x, y) { + (float_nan!(), _) => (float_nan!(), Equal), + (Float(Infinity { sign }), y) => ( + if *y >= 0u32 { + Float(Infinity { sign: *sign }) + } else { + Float(Infinity { sign: !*sign }) + }, + Equal, + ), + (Float(Zero { sign }), y) => ( + match y.sign() { + Equal => float_nan!(), + Greater => Float(Zero { sign: *sign }), + Less => Float(Zero { sign: !*sign }), + }, + Equal, + ), + (x, y) => { + if *y == 0 { + (Float(Infinity { sign: *x > 0u32 }), Equal) + } else { + let (mut quotient, o) = + Float::from_rational_prec_round(Rational::exact_from(x) / y, prec, rm); + if quotient == 0u32 && *x < 0 { + quotient.neg_assign(); + } + (quotient, o) + } + } + } +}} + +fn div_rational_prec_round_assign_direct( + x: &mut Float, + y: Rational, + prec: u64, + mut rm: RoundingMode, +) -> Ordering { + assert_ne!(prec, 0); + let sign = y >= 0; + let (n, d) = y.into_numerator_and_denominator(); + if !sign { + rm.neg_assign(); + } + let o = match ( + if n == 0 { None } else { n.checked_log_base_2() }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let o = x.set_prec_round(prec, rm); + *x <<= log_d; + *x >>= log_n; + o + } + (None, Some(log_d)) => { + let o = x.div_prec_round_assign(Float::from_natural_min_prec(n), prec, rm); + *x <<= log_d; + o + } + (Some(log_n), None) => { + let o = x.mul_prec_round_assign(Float::from_natural_min_prec(d), prec, rm); + *x >>= log_n; + o + } + (None, None) => { + let n = Float::from_natural_min_prec(n); + let d = Float::from_natural_min_prec(d); + let mul_prec = x.get_min_prec().unwrap_or(1) + d.significant_bits(); + x.mul_prec_round_assign(d, mul_prec, Floor); + x.div_prec_round_assign(n, prec, rm) + } + }; + if sign { + o + } else { + x.neg_assign(); + o.reverse() + } +} + +fn div_rational_prec_round_assign_direct_ref( + x: &mut Float, + y: &Rational, + prec: u64, + mut rm: RoundingMode, +) -> Ordering { + assert_ne!(prec, 0); + let sign = *y >= 0; + let (n, d) = y.numerator_and_denominator_ref(); + if !sign { + rm.neg_assign(); + } + let o = match ( + if *n == 0 { + None + } else { + n.checked_log_base_2() + }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let o = x.set_prec_round(prec, rm); + *x <<= log_d; + *x >>= log_n; + o + } + (None, Some(log_d)) => { + let o = x.div_prec_round_assign(Float::from_natural_min_prec_ref(n), prec, rm); + *x <<= log_d; + o + } + (Some(log_n), None) => { + let o = x.mul_prec_round_assign(Float::from_natural_min_prec_ref(d), prec, rm); + *x >>= log_n; + o + } + (None, None) => { + let n = Float::from_natural_min_prec_ref(n); + let d = Float::from_natural_min_prec_ref(d); + let mul_prec = x.get_min_prec().unwrap_or(1) + d.significant_bits(); + x.mul_prec_round_assign(d, mul_prec, Floor); + x.div_prec_round_assign(n, prec, rm) + } + }; + if sign { + o + } else { + x.neg_assign(); + o.reverse() + } +} + +pub_test! {div_rational_prec_round_direct( + mut x: Float, + y: Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + let o = div_rational_prec_round_assign_direct(&mut x, y, prec, rm); + (x, o) +}} + +pub_test! {div_rational_prec_round_direct_val_ref( + mut x: Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + let o = div_rational_prec_round_assign_direct_ref(&mut x, y, prec, rm); + (x, o) +}} + +pub_test! {div_rational_prec_round_direct_ref_val( + x: &Float, + y: Rational, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + let sign = y >= 0; + let (n, d) = y.into_numerator_and_denominator(); + if !sign { + rm.neg_assign(); + } + let (quotient, o) = match ( + if n == 0 { None } else { n.checked_log_base_2() }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let (quotient, o) = Float::from_float_prec_round_ref(x, prec, rm); + (quotient << log_d >> log_n, o) + } + (None, Some(log_d)) => { + let (quotient, o) = x.div_prec_round_ref_val(Float::from_natural_min_prec(n), prec, rm); + (quotient << log_d, o) + } + (Some(log_n), None) => { + let (quotient, o) = x.mul_prec_round_ref_val(Float::from_natural_min_prec(d), prec, rm); + (quotient >> log_n, o) + } + (None, None) => { + let n = Float::from_natural_min_prec(n); + let d = Float::from_natural_min_prec(d); + let mul_prec = x.get_min_prec().unwrap_or(1) + d.significant_bits(); + x.mul_prec_round_ref_val(d, mul_prec, Floor) + .0 + .div_prec_round(n, prec, rm) + } + }; + if sign { + (quotient, o) + } else { + (-quotient, o.reverse()) + } +}} + +pub_test! {div_rational_prec_round_direct_ref_ref( + x: &Float, + y: &Rational, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + let sign = *y >= 0; + let (n, d) = y.numerator_and_denominator_ref(); + if !sign { + rm.neg_assign(); + } + let (quotient, o) = match ( + if *n == 0 { + None + } else { + n.checked_log_base_2() + }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let (quotient, o) = Float::from_float_prec_round_ref(x, prec, rm); + (quotient << log_d >> log_n, o) + } + (None, Some(log_d)) => { + let (quotient, o) = + x.div_prec_round_ref_val(Float::from_natural_min_prec_ref(n), prec, rm); + (quotient << log_d, o) + } + (Some(log_n), None) => { + let (quotient, o) = + x.mul_prec_round_ref_val(Float::from_natural_min_prec_ref(d), prec, rm); + (quotient >> log_n, o) + } + (None, None) => { + let n = Float::from_natural_min_prec_ref(n); + let d = Float::from_natural_min_prec_ref(d); + let mul_prec = x.get_min_prec().unwrap_or(1) + d.significant_bits(); + x.mul_prec_round_ref_val(d, mul_prec, Floor) + .0 + .div_prec_round(n, prec, rm) + } + }; + if sign { + (quotient, o) + } else { + (-quotient, o.reverse()) + } +}} + +pub_test! {rational_div_float_prec_round_naive( + x: Rational, + y: Float, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (x, y) { + (_, float_nan!()) => (float_nan!(), Equal), + (x, Float(Infinity { sign })) => ( + if x >= 0u32 { + Float(Zero { sign }) + } else { + Float(Zero { sign: !sign }) + }, + Equal, + ), + (x, Float(Zero { sign })) => ( + match x.sign() { + Equal => float_nan!(), + Greater => Float(Infinity { sign }), + Less => Float(Infinity { sign: !sign }), + }, + Equal, + ), + (x, y) => { + let not_sign = y < 0; + let (mut quotient, o) = + Float::from_rational_prec_round(x / Rational::exact_from(y), prec, rm); + if quotient == 0u32 && not_sign { + quotient.neg_assign(); + } + (quotient, o) + } + } +}} + +pub_test! {rational_div_float_prec_round_naive_val_ref( + x: Rational, + y: &Float, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (x, y) { + (_, float_nan!()) => (float_nan!(), Equal), + (x, Float(Infinity { sign })) => ( + if x >= 0u32 { + Float(Zero { sign: *sign }) + } else { + Float(Zero { sign: !*sign }) + }, + Equal, + ), + (x, Float(Zero { sign })) => ( + match x.sign() { + Equal => float_nan!(), + Greater => Float(Infinity { sign: *sign }), + Less => Float(Infinity { sign: !*sign }), + }, + Equal, + ), + (x, y) => { + let (mut quotient, o) = + Float::from_rational_prec_round(x / Rational::exact_from(y), prec, rm); + if quotient == 0u32 && *y < 0 { + quotient.neg_assign(); + } + (quotient, o) + } + } +}} + +pub_test! {rational_div_float_prec_round_naive_ref_val( + x: &Rational, + y: Float, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (x, y) { + (_, float_nan!()) => (float_nan!(), Equal), + (x, Float(Infinity { sign })) => ( + if *x >= 0u32 { + Float(Zero { sign }) + } else { + Float(Zero { sign: !sign }) + }, + Equal, + ), + (x, Float(Zero { sign })) => ( + match x.sign() { + Equal => float_nan!(), + Greater => Float(Infinity { sign }), + Less => Float(Infinity { sign: !sign }), + }, + Equal, + ), + (x, y) => { + let not_sign = y < 0; + let (mut quotient, o) = + Float::from_rational_prec_round(x / Rational::exact_from(y), prec, rm); + if quotient == 0u32 && not_sign { + quotient.neg_assign(); + } + (quotient, o) + } + } +}} + +pub_test! {rational_div_float_prec_round_naive_ref_ref( + x: &Rational, + y: &Float, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (x, y) { + (_, float_nan!()) => (float_nan!(), Equal), + (x, Float(Infinity { sign })) => ( + if *x >= 0u32 { + Float(Zero { sign: *sign }) + } else { + Float(Zero { sign: !*sign }) + }, + Equal, + ), + (x, Float(Zero { sign })) => ( + match x.sign() { + Equal => float_nan!(), + Greater => Float(Infinity { sign: *sign }), + Less => Float(Infinity { sign: !*sign }), + }, + Equal, + ), + (x, y) => { + let (mut quotient, o) = + Float::from_rational_prec_round(x / Rational::exact_from(y), prec, rm); + if quotient == 0u32 && *y < 0 { + quotient.neg_assign(); + } + (quotient, o) + } + } +}} + +pub_test! {rational_div_float_prec_round_direct( + x: Rational, + y: Float, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + let sign = x >= 0; + let (n, d) = x.into_numerator_and_denominator(); + if !sign { + rm.neg_assign(); + } + let (quotient, o) = match ( + if n == 0 { None } else { n.checked_log_base_2() }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let (quotient, o) = Float::reciprocal_prec_round(y, prec, rm); + (quotient << log_n >> log_d, o) + } + (None, Some(log_d)) => { + let (quotient, o) = Float::from_natural_min_prec(n).div_prec_round(y, prec, rm); + (quotient >> log_d, o) + } + (Some(log_n), None) => { + let d = Float::from_natural_min_prec(d); + let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); + let (quotient, o) = y + .mul_prec_round(d, mul_prec, Floor) + .0 + .reciprocal_prec_round(prec, rm); + (quotient << log_n, o) + } + (None, None) => { + let n = Float::from_natural_min_prec(n); + let d = Float::from_natural_min_prec(d); + let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); + n.div_prec_round(y.mul_prec_round(d, mul_prec, Floor).0, prec, rm) + } + }; + if sign { + (quotient, o) + } else { + (-quotient, o.reverse()) + } +}} + +pub_test! {rational_div_float_prec_round_direct_val_ref( + x: Rational, + y: &Float, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + let sign = x >= 0; + let (n, d) = x.into_numerator_and_denominator(); + if !sign { + rm.neg_assign(); + } + let (quotient, o) = match ( + if n == 0 { None } else { n.checked_log_base_2() }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let (quotient, o) = Float::reciprocal_prec_round_ref(y, prec, rm); + (quotient << log_n >> log_d, o) + } + (None, Some(log_d)) => { + let (quotient, o) = Float::from_natural_min_prec(n).div_prec_round_val_ref(y, prec, rm); + (quotient >> log_d, o) + } + (Some(log_n), None) => { + let d = Float::from_natural_min_prec(d); + let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); + let (quotient, o) = y + .mul_prec_round_ref_val(d, mul_prec, Floor) + .0 + .reciprocal_prec_round(prec, rm); + (quotient << log_n, o) + } + (None, None) => { + let n = Float::from_natural_min_prec(n); + let d = Float::from_natural_min_prec(d); + let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); + n.div_prec_round(y.mul_prec_round_ref_val(d, mul_prec, Floor).0, prec, rm) + } + }; + if sign { + (quotient, o) + } else { + (-quotient, o.reverse()) + } +}} + +pub_test! {rational_div_float_prec_round_direct_ref_val( + x: &Rational, + y: Float, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + let sign = *x >= 0; + let (n, d) = x.numerator_and_denominator_ref(); + if !sign { + rm.neg_assign(); + } + let (quotient, o) = match ( + if *n == 0 { + None + } else { + n.checked_log_base_2() + }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let (quotient, o) = Float::reciprocal_prec_round(y, prec, rm); + (quotient << log_n >> log_d, o) + } + (None, Some(log_d)) => { + let (quotient, o) = Float::from_natural_min_prec_ref(n).div_prec_round(y, prec, rm); + (quotient >> log_d, o) + } + (Some(log_n), None) => { + let d = Float::from_natural_min_prec_ref(d); + let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); + let (quotient, o) = y + .mul_prec_round(d, mul_prec, Floor) + .0 + .reciprocal_prec_round(prec, rm); + (quotient << log_n, o) + } + (None, None) => { + let n = Float::from_natural_min_prec_ref(n); + let d = Float::from_natural_min_prec_ref(d); + let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); + n.div_prec_round(y.mul_prec_round(d, mul_prec, Floor).0, prec, rm) + } + }; + if sign { + (quotient, o) + } else { + (-quotient, o.reverse()) + } +}} + +pub_test! {rational_div_float_prec_round_direct_ref_ref( + x: &Rational, + y: &Float, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + let sign = *x >= 0; + let (n, d) = x.numerator_and_denominator_ref(); + if !sign { + rm.neg_assign(); + } + let (quotient, o) = match ( + if *n == 0 { + None + } else { + n.checked_log_base_2() + }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let (quotient, o) = Float::reciprocal_prec_round_ref(y, prec, rm); + (quotient << log_n >> log_d, o) + } + (None, Some(log_d)) => { + let (quotient, o) = + Float::from_natural_min_prec_ref(n).div_prec_round_val_ref(y, prec, rm); + (quotient >> log_d, o) + } + (Some(log_n), None) => { + let d = Float::from_natural_min_prec_ref(d); + let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); + let (quotient, o) = y + .mul_prec_round_ref_val(d, mul_prec, Floor) + .0 + .reciprocal_prec_round(prec, rm); + (quotient << log_n, o) + } + (None, None) => { + let n = Float::from_natural_min_prec_ref(n); + let d = Float::from_natural_min_prec_ref(d); + let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); + n.div_prec_round(y.mul_prec_round_ref_val(d, mul_prec, Floor).0, prec, rm) + } + }; + if sign { + (quotient, o) + } else { + (-quotient, o.reverse()) + } +}} + +impl Float { + /// Divides two [`Float`]s, rounding the result to the specified precision and with the + /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,p,m)=\infty$ if $0.00.0$ + /// - $f(x,0.0,p,m)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,p,m)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,p,m)=\infty$ if $x<0.0$ + /// - $f(0.0,x,p,m)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,p,m)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_prec`] instead. If you + /// know that your target precision is the maximum of the precisions of the two inputs, consider + /// using [`Float::div_round`] instead. If both of these things are true, consider using `/` + /// instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_prec_round(Float::from(E), 5, Floor); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round(Float::from(E), 5, Ceiling); + /// assert_eq!(quotient.to_string(), "1.19"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round(Float::from(E), 5, Nearest); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round(Float::from(E), 20, Floor); + /// assert_eq!(quotient.to_string(), "1.155725"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round(Float::from(E), 20, Ceiling); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round(Float::from(E), 20, Nearest); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn div_prec_round( + mut self, + other: Float, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + let o = self.div_prec_round_assign(other, prec, rm); + (self, o) + } + + /// Divides two [`Float`]s, rounding the result to the specified precision and with the + /// specified rounding mode. The first [`Float`] is are taken by value and the second by + /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,p,m)=\infty$ if $0.00.0$ + /// - $f(x,0.0,p,m)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,p,m)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,p,m)=\infty$ if $x<0.0$ + /// - $f(0.0,x,p,m)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,p,m)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_prec_val_ref`] instead. + /// If you know that your target precision is the maximum of the precisions of the two inputs, + /// consider using [`Float::div_round_val_ref`] instead. If both of these things are true, + /// consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_val_ref(&Float::from(E), 5, Floor); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_val_ref(&Float::from(E), 5, Ceiling); + /// assert_eq!(quotient.to_string(), "1.19"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_val_ref(&Float::from(E), 5, Nearest); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_val_ref(&Float::from(E), 20, Floor); + /// assert_eq!(quotient.to_string(), "1.155725"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_val_ref(&Float::from(E), 20, Ceiling); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_val_ref(&Float::from(E), 20, Nearest); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn div_prec_round_val_ref( + mut self, + other: &Float, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + let o = self.div_prec_round_assign_ref(other, prec, rm); + (self, o) + } + + /// Divides two [`Float`]s, rounding the result to the specified precision and with the + /// specified rounding mode. The first [`Float`] is are taken by reference and the second by + /// value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,p,m)=\infty$ if $0.00.0$ + /// - $f(x,0.0,p,m)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,p,m)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,p,m)=\infty$ if $x<0.0$ + /// - $f(0.0,x,p,m)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,p,m)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_prec_ref_val`] instead. + /// If you know that your target precision is the maximum of the precisions of the two inputs, + /// consider using [`Float::div_round_ref_val`] instead. If both of these things are true, + /// consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_val(Float::from(E), 5, Floor); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_val(Float::from(E), 5, Ceiling); + /// assert_eq!(quotient.to_string(), "1.19"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_val(Float::from(E), 5, Nearest); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_val(Float::from(E), 20, Floor); + /// assert_eq!(quotient.to_string(), "1.155725"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_val(Float::from(E), 20, Ceiling); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_val(Float::from(E), 20, Nearest); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn div_prec_round_ref_val( + &self, + other: Float, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (self, other) { + (float_nan!(), _) + | (_, float_nan!()) + | (float_either_infinity!(), float_either_infinity!()) + | (float_either_zero!(), float_either_zero!()) => (float_nan!(), Equal), + ( + Float(Infinity { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => ( + Float(Infinity { + sign: *x_sign == y_sign, + }), + Equal, + ), + ( + Float(Zero { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => ( + Float(Zero { + sign: *x_sign == y_sign, + }), + Equal, + ), + ( + Float(Finite { + sign: x_sign, + exponent: x_exp, + precision: x_prec, + significand: x, + }), + Float(Finite { + sign: y_sign, + exponent: y_exp, + precision: y_prec, + significand: mut y, + }), + ) => { + if y.is_power_of_2() { + let (mut quotient, mut o) = + Float::from_float_prec_round_ref(self, prec, if y_sign { rm } else { -rm }); + if !y_sign { + quotient.neg_assign(); + o = o.reverse(); + } + return (quotient >> y_exp.checked_sub(1).unwrap(), o); + } + let sign = *x_sign == y_sign; + let (quotient, exp_offset, o) = div_float_significands_ref_val( + x, + *x_prec, + &mut y, + y_prec, + prec, + if sign { rm } else { -rm }, + ); + let exp = x_exp + .checked_sub(y_exp) + .unwrap() + .checked_add(i32::exact_from(exp_offset)) + .unwrap(); + ( + Float(Finite { + sign, + exponent: exp, + precision: prec, + significand: quotient, + }), + if sign { o } else { o.reverse() }, + ) + } + } + } + + /// Divides two [`Float`]s, rounding the result to the specified precision and with the + /// specified rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,p,m)=\infty$ if $0.00.0$ + /// - $f(x,0.0,p,m)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,p,m)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,p,m)=\infty$ if $x<0.0$ + /// - $f(0.0,x,p,m)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,p,m)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_prec_ref_ref`] instead. + /// If you know that your target precision is the maximum of the precisions of the two inputs, + /// consider using [`Float::div_round_ref_ref`] instead. If both of these things are true, + /// consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_ref(&Float::from(E), 5, Floor); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_ref(&Float::from(E), 5, Ceiling); + /// assert_eq!(quotient.to_string(), "1.19"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_ref(&Float::from(E), 5, Nearest); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_ref(&Float::from(E), 20, Floor); + /// assert_eq!(quotient.to_string(), "1.155725"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_ref(&Float::from(E), 20, Ceiling); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_prec_round_ref_ref(&Float::from(E), 20, Nearest); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn div_prec_round_ref_ref( + &self, + other: &Float, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (self, other) { + (float_nan!(), _) + | (_, float_nan!()) + | (float_either_infinity!(), float_either_infinity!()) + | (float_either_zero!(), float_either_zero!()) => (float_nan!(), Equal), + ( + Float(Infinity { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => ( + Float(Infinity { + sign: x_sign == y_sign, + }), + Equal, + ), + ( + Float(Zero { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => ( + Float(Zero { + sign: x_sign == y_sign, + }), + Equal, + ), + ( + Float(Finite { + sign: x_sign, + exponent: x_exp, + precision: x_prec, + significand: x, + }), + Float(Finite { + sign: y_sign, + exponent: y_exp, + precision: y_prec, + significand: y, + }), + ) => { + if y.is_power_of_2() { + let (mut quotient, mut o) = Float::from_float_prec_round_ref( + self, + prec, + if *y_sign { rm } else { -rm }, + ); + if !y_sign { + quotient.neg_assign(); + o = o.reverse(); + } + return (quotient >> y_exp.checked_sub(1).unwrap(), o); + } + let sign = x_sign == y_sign; + let (quotient, exp_offset, o) = div_float_significands_ref_ref( + x, + *x_prec, + y, + *y_prec, + prec, + if sign { rm } else { -rm }, + ); + let exp = x_exp + .checked_sub(*y_exp) + .unwrap() + .checked_add(i32::exact_from(exp_offset)) + .unwrap(); + ( + Float(Finite { + sign, + exponent: exp, + precision: prec, + significand: quotient, + }), + if sign { o } else { o.reverse() }, + ) + } + } + } + + /// Divides two [`Float`]s, rounding the result to the nearest value of the specified precision. + /// Both [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating whether the + /// rounded quotient is less than, equal to, or greater than the exact quotient. Although `NaN`s + /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns + /// `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,p)=\infty$ if $0.00.0$ + /// - $f(x,0.0,p)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,p)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,p)=\infty$ if $x<0.0$ + /// - $f(0.0,x,p)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,p)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,p)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,p)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_round`] instead. If you know that your target precision is the maximum of + /// the precisions of the two inputs, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_prec(Float::from(E), 5); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec(Float::from(E), 20); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn div_prec(self, other: Float, prec: u64) -> (Float, Ordering) { + self.div_prec_round(other, prec, Nearest) + } + + /// Divides two [`Float`]s, rounding the result to the nearest value of the specified precision. + /// The first [`Float`] is taken by value and the second by reference. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,p)=\infty$ if $0.00.0$ + /// - $f(x,0.0,p)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,p)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,p)=\infty$ if $x<0.0$ + /// - $f(0.0,x,p)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,p)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,p)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,p)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_round_val_ref`] instead. If you know that your target precision is the + /// maximum of the precisions of the two inputs, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_prec_val_ref(&Float::from(E), 5); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_val_ref(&Float::from(E), 20); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn div_prec_val_ref(self, other: &Float, prec: u64) -> (Float, Ordering) { + self.div_prec_round_val_ref(other, prec, Nearest) + } + + /// Divides two [`Float`]s, rounding the result to the nearest value of the specified precision. + /// The first [`Float`] is taken by reference and the second by value. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,p)=\infty$ if $0.00.0$ + /// - $f(x,0.0,p)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,p)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,p)=\infty$ if $x<0.0$ + /// - $f(0.0,x,p)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,p)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,p)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,p)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_round_ref_val`] instead. If you know that your target precision is the + /// maximum of the precisions of the two inputs, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_prec_ref_val(Float::from(E), 5); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_ref_val(Float::from(E), 20); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn div_prec_ref_val(&self, other: Float, prec: u64) -> (Float, Ordering) { + self.div_prec_round_ref_val(other, prec, Nearest) + } + + /// Divides two [`Float`]s, rounding the result to the nearest value of the specified precision. + /// Both [`Float`]s are taken by reference. An [`Ordering`] is also returned, indicating whether + /// the rounded quotient is less than, equal to, or greater than the exact quotient. Although + /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also + /// returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,p)=\infty$ if $0.00.0$ + /// - $f(x,0.0,p)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,p)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,p)=\infty$ if $x<0.0$ + /// - $f(0.0,x,p)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,p)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,p)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,p)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_round_ref_ref`] instead. If you know that your target precision is the + /// maximum of the precisions of the two inputs, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_prec_ref_ref(&Float::from(E), 5); + /// assert_eq!(quotient.to_string(), "1.12"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_prec_ref_ref(&Float::from(E), 20); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn div_prec_ref_ref(&self, other: &Float, prec: u64) -> (Float, Ordering) { + self.div_prec_round_ref_ref(other, prec, Nearest) + } + + /// Divides two [`Float`]s, rounding the result with the specified rounding mode. Both + /// [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating whether the + /// rounded quotient is less than, equal to, or greater than the exact quotient. Although `NaN`s + /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns + /// `Equal`. + /// + /// The precision of the output is the maximum of the precision of the inputs. See + /// [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN},x,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,m)=\infty$ if $0.00.0$ + /// - $f(x,0.0,m)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,m)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,m)=\infty$ if $x<0.0$ + /// - $f(0.0,x,m)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,m)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,m)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,m)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to specify an output precision, consider using [`Float::div_prec_round`] + /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `/` + /// instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_round(Float::from(E), Floor); + /// assert_eq!(quotient.to_string(), "1.1557273497909217"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_round(Float::from(E), Ceiling); + /// assert_eq!(quotient.to_string(), "1.155727349790922"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_round(Float::from(E), Nearest); + /// assert_eq!(quotient.to_string(), "1.1557273497909217"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_round(self, other: Float, rm: RoundingMode) -> (Float, Ordering) { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round(other, prec, rm) + } + + /// Divides two [`Float`]s, rounding the result with the specified rounding mode. The first + /// [`Float`] is taken by value and the second by reference. An [`Ordering`] is also returned, + /// indicating whether the rounded quotient is less than, equal to, or greater than the exact + /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function + /// returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the maximum of the precision of the inputs. See + /// [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN},x,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,m)=\infty$ if $0.00.0$ + /// - $f(x,0.0,m)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,m)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,m)=\infty$ if $x<0.0$ + /// - $f(0.0,x,m)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,m)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,m)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,m)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to specify an output precision, consider using [`Float::div_prec_round_val_ref`] + /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `/` + /// instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_round_val_ref(&Float::from(E), Floor); + /// assert_eq!(quotient.to_string(), "1.1557273497909217"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_round_val_ref(&Float::from(E), Ceiling); + /// assert_eq!(quotient.to_string(), "1.155727349790922"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_round_val_ref(&Float::from(E), Nearest); + /// assert_eq!(quotient.to_string(), "1.1557273497909217"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_round_val_ref(self, other: &Float, rm: RoundingMode) -> (Float, Ordering) { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_val_ref(other, prec, rm) + } + + /// Divides two [`Float`]s, rounding the result with the specified rounding mode. The first + /// [`Float`] is taken by reference and the second by value. An [`Ordering`] is also returned, + /// indicating whether the rounded quotient is less than, equal to, or greater than the exact + /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function + /// returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the maximum of the precision of the inputs. See + /// [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN},x,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,m)=\infty$ if $0.00.0$ + /// - $f(x,0.0,m)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,m)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,m)=\infty$ if $x<0.0$ + /// - $f(0.0,x,m)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,m)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,m)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,m)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to specify an output precision, consider using [`Float::div_prec_round_ref_val`] + /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `/` + /// instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_round_ref_val(Float::from(E), Floor); + /// assert_eq!(quotient.to_string(), "1.1557273497909217"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_round_ref_val(Float::from(E), Ceiling); + /// assert_eq!(quotient.to_string(), "1.155727349790922"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_round_ref_val(Float::from(E), Nearest); + /// assert_eq!(quotient.to_string(), "1.1557273497909217"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_round_ref_val(&self, other: Float, rm: RoundingMode) -> (Float, Ordering) { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_ref_val(other, prec, rm) + } + + /// Divides two [`Float`]s, rounding the result with the specified rounding mode. Both + /// [`Float`]s are taken by reference. An [`Ordering`] is also returned, indicating whether the + /// rounded quotient is less than, equal to, or greater than the exact quotient. Although `NaN`s + /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns + /// `Equal`. + /// + /// The precision of the output is the maximum of the precision of the inputs. See + /// [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN},x,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = + /// \text{NaN}$ + /// - $f(\infty,x,m)=\infty$ if $0.00.0$ + /// - $f(x,0.0,m)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x,m)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0,m)=\infty$ if $x<0.0$ + /// - $f(0.0,x,m)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x,m)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x,m)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x,m)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to specify an output precision, consider using [`Float::div_prec_round_ref_ref`] + /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `/` + /// instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_round_ref_ref(&Float::from(E), Floor); + /// assert_eq!(quotient.to_string(), "1.1557273497909217"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_round_ref_ref(&Float::from(E), Ceiling); + /// assert_eq!(quotient.to_string(), "1.155727349790922"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_round_ref_ref(&Float::from(E), Nearest); + /// assert_eq!(quotient.to_string(), "1.1557273497909217"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_round_ref_ref(&self, other: &Float, rm: RoundingMode) -> (Float, Ordering) { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_ref_ref(other, prec, rm) + } + + /// Divides a [`Float`] by a [`Float`] in place, rounding the result to the specified precision + /// and with the specified rounding mode. The [`Float`] on the right-hand side is taken by + /// value. An [`Ordering`] is returned, indicating whether the rounded quotient is less than, + /// equal to, or greater than the exact quotient. Although `NaN`s are not comparable to any + /// [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::div_prec_round`] documentation for information on special cases. + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_prec_assign`] instead. If + /// you know that your target precision is the maximum of the precisions of the two inputs, + /// consider using [`Float::div_round_assign`] instead. If both of these things are true, + /// consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign(Float::from(E), 5, Floor), + /// Less + /// ); + /// assert_eq!(quotient.to_string(), "1.12"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign(Float::from(E), 5, Ceiling), + /// Greater + /// ); + /// assert_eq!(quotient.to_string(), "1.19"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign(Float::from(E), 5, Nearest), + /// Less + /// ); + /// assert_eq!(quotient.to_string(), "1.12"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign(Float::from(E), 20, Floor), + /// Less + /// ); + /// assert_eq!(quotient.to_string(), "1.155725"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign(Float::from(E), 20, Ceiling), + /// Greater + /// ); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign(Float::from(E), 20, Nearest), + /// Greater + /// ); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// ``` + #[inline] + pub fn div_prec_round_assign(&mut self, other: Float, prec: u64, rm: RoundingMode) -> Ordering { + assert_ne!(prec, 0); + match (&mut *self, other) { + (float_nan!(), _) + | (_, float_nan!()) + | (float_either_infinity!(), float_either_infinity!()) + | (float_either_zero!(), float_either_zero!()) => { + *self = float_nan!(); + Equal + } + ( + Float(Infinity { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => { + *self = Float(Infinity { + sign: *x_sign == y_sign, + }); + Equal + } + ( + Float(Zero { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => { + *self = Float(Zero { + sign: *x_sign == y_sign, + }); + Equal + } + (_, y) if abs_is_power_of_2(&y) => { + if y < 0 { + self.neg_assign(); + } + let o = self.set_prec_round(prec, rm); + *self >>= y.get_exponent().unwrap().checked_sub(1).unwrap(); + o + } + ( + Float(Finite { + sign: ref mut x_sign, + exponent: ref mut x_exp, + precision: ref mut x_prec, + significand: ref mut x, + }), + Float(Finite { + sign: y_sign, + exponent: y_exp, + precision: y_prec, + significand: mut y, + }), + ) => { + let sign = *x_sign == y_sign; + let (exp_offset, o) = div_float_significands_in_place( + x, + *x_prec, + &mut y, + y_prec, + prec, + if sign { rm } else { -rm }, + ); + *x_sign = sign; + *x_exp = x_exp + .checked_sub(y_exp) + .unwrap() + .checked_add(i32::exact_from(exp_offset)) + .unwrap(); + *x_prec = prec; + if sign { + o + } else { + o.reverse() + } + } + } + } + + /// Divides a [`Float`] by a [`Float`] in place, rounding the result to the specified precision + /// and with the specified rounding mode. The [`Float`] on the right-hand side is taken by + /// reference. An [`Ordering`] is returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::div_prec_round`] documentation for information on special cases. + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_prec_assign_ref`] + /// instead. If you know that your target precision is the maximum of the precisions of the two + /// inputs, consider using [`Float::div_round_assign_ref`] instead. If both of these things are + /// true, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign_ref(&Float::from(E), 5, Floor), + /// Less + /// ); + /// assert_eq!(quotient.to_string(), "1.12"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign_ref(&Float::from(E), 5, Ceiling), + /// Greater + /// ); + /// assert_eq!(quotient.to_string(), "1.19"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign_ref(&Float::from(E), 5, Nearest), + /// Less + /// ); + /// assert_eq!(quotient.to_string(), "1.12"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign_ref(&Float::from(E), 20, Floor), + /// Less + /// ); + /// assert_eq!(quotient.to_string(), "1.155725"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign_ref(&Float::from(E), 20, Ceiling), + /// Greater + /// ); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// + /// let mut quotient = Float::from(PI); + /// assert_eq!( + /// quotient.div_prec_round_assign_ref(&Float::from(E), 20, Nearest), + /// Greater + /// ); + /// assert_eq!(quotient.to_string(), "1.155727"); + /// ``` + #[inline] + pub fn div_prec_round_assign_ref( + &mut self, + other: &Float, + prec: u64, + rm: RoundingMode, + ) -> Ordering { + assert_ne!(prec, 0); + match (&mut *self, other) { + (float_nan!(), _) + | (_, float_nan!()) + | (float_either_infinity!(), float_either_infinity!()) + | (float_either_zero!(), float_either_zero!()) => { + *self = float_nan!(); + Equal + } + ( + Float(Infinity { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => { + *self = Float(Infinity { + sign: x_sign == y_sign, + }); + Equal + } + ( + Float(Zero { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => { + *self = Float(Zero { + sign: x_sign == y_sign, + }); + Equal + } + (_, y) if abs_is_power_of_2(y) => { + if *y < 0 { + self.neg_assign(); + } + let o = self.set_prec_round(prec, rm); + *self >>= y.get_exponent().unwrap().checked_sub(1).unwrap(); + o + } + ( + Float(Finite { + sign: ref mut x_sign, + exponent: ref mut x_exp, + precision: ref mut x_prec, + significand: ref mut x, + }), + Float(Finite { + sign: y_sign, + exponent: y_exp, + precision: y_prec, + significand: y, + }), + ) => { + let sign = x_sign == y_sign; + let (exp_offset, o) = div_float_significands_in_place_ref( + x, + *x_prec, + y, + *y_prec, + prec, + if sign { rm } else { -rm }, + ); + *x_sign = sign; + *x_exp = x_exp + .checked_sub(*y_exp) + .unwrap() + .checked_add(i32::exact_from(exp_offset)) + .unwrap(); + *x_prec = prec; + if sign { + o + } else { + o.reverse() + } + } + } + } + + /// Divides a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of the + /// specified precision. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] + /// is returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function sets the [`Float`] to `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::div_prec`] documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_round_assign`] instead. If you know that your target precision is the + /// maximum of the precisions of the two inputs, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_prec_assign(Float::from(E), 5), Less); + /// assert_eq!(x.to_string(), "1.12"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_prec_assign(Float::from(E), 20), Greater); + /// assert_eq!(x.to_string(), "1.155727"); + /// ``` + #[inline] + pub fn div_prec_assign(&mut self, other: Float, prec: u64) -> Ordering { + self.div_prec_round_assign(other, prec, Nearest) + } + + /// Divides a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of the + /// specified precision. The [`Float`] on the right-hand side is taken by reference. An + /// [`Ordering`] is returned, indicating whether the rounded quotient is less than, equal to, or + /// greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::div_prec`] documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_round_assign_ref`] instead. If you know that your target precision is the + /// maximum of the precisions of the two inputs, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), `prec`)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_prec_assign_ref(&Float::from(E), 5), Less); + /// assert_eq!(x.to_string(), "1.12"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_prec_assign_ref(&Float::from(E), 20), Greater); + /// assert_eq!(x.to_string(), "1.155727"); + /// ``` + #[inline] + pub fn div_prec_assign_ref(&mut self, other: &Float, prec: u64) -> Ordering { + self.div_prec_round_assign_ref(other, prec, Nearest) + } + + /// Divides a [`Float`] by a [`Float`] in place, rounding the result with the specified rounding + /// mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned, + /// indicating whether the rounded quotient is less than, equal to, or greater than the exact + /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function sets + /// the [`Float`] to `NaN` it also returns `Equal`. + /// + /// The precision of the output is the maximum of the precision of the inputs. See + /// [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. + /// + /// See the [`Float::div_round`] documentation for information on special cases. + /// + /// If you want to specify an output precision, consider using [`Float::div_prec_round_assign`] + /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `/=` + /// instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_round_assign(Float::from(E), Floor), Less); + /// assert_eq!(x.to_string(), "1.1557273497909217"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_round_assign(Float::from(E), Ceiling), Greater); + /// assert_eq!(x.to_string(), "1.155727349790922"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_round_assign(Float::from(E), Nearest), Less); + /// assert_eq!(x.to_string(), "1.1557273497909217"); + /// ``` + #[inline] + pub fn div_round_assign(&mut self, other: Float, rm: RoundingMode) -> Ordering { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_assign(other, prec, rm) + } + + /// Divides a [`Float`] by a [`Float`] in place, rounding the result with the specified rounding + /// mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function sets the [`Float`] to `NaN` it also returns `Equal`. + /// + /// The precision of the output is the maximum of the precision of the inputs. See + /// [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. + /// + /// See the [`Float::div_round`] documentation for information on special cases. + /// + /// If you want to specify an output precision, consider using + /// [`Float::div_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest` + /// rounding mode, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::{E, PI}; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_round_assign_ref(&Float::from(E), Floor), Less); + /// assert_eq!(x.to_string(), "1.1557273497909217"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_round_assign_ref(&Float::from(E), Ceiling), Greater); + /// assert_eq!(x.to_string(), "1.155727349790922"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.div_round_assign_ref(&Float::from(E), Nearest), Less); + /// assert_eq!(x.to_string(), "1.1557273497909217"); + /// ``` + #[inline] + pub fn div_round_assign_ref(&mut self, other: &Float, rm: RoundingMode) -> Ordering { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_assign_ref(other, prec, rm) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result to the specified precision and + /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by + /// value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=f(\pm0.0,0,p,m)=\text{NaN}$ + /// - $f(\infty,x,p,m)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ + /// - $f(-\infty,x,p,m)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ + /// - $f(0.0,x,p,m)=0.0$ if $x>0$ + /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ + /// - $f(-0.0,x,p,m)=-0.0$ if $x>0$ + /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_rational_prec`] instead. + /// If you know that your target precision is the precision of the [`Float`] input, consider + /// using [`Float::div_rational_round`] instead. If both of these things are true, consider + /// using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_round(Rational::from_unsigneds(1u8, 3), 5, Floor); + /// assert_eq!(quotient.to_string(), "9.0"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_round(Rational::from_unsigneds(1u8, 3), 5, Ceiling); + /// assert_eq!(quotient.to_string(), "9.5"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_round(Rational::from_unsigneds(1u8, 3), 5, Nearest); + /// assert_eq!(quotient.to_string(), "9.5"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_round(Rational::from_unsigneds(1u8, 3), 20, Floor); + /// assert_eq!(quotient.to_string(), "9.42477"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_round(Rational::from_unsigneds(1u8, 3), 20, Ceiling); + /// assert_eq!(quotient.to_string(), "9.42479"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_round(Rational::from_unsigneds(1u8, 3), 20, Nearest); + /// assert_eq!(quotient.to_string(), "9.42477"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_rational_prec_round( + mut self, + other: Rational, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + let o = self.div_rational_prec_round_assign(other, prec, rm); + (self, o) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result to the specified precision and + /// with the specified rounding mode. The [`Float`] is taken by value and the [`Rational`] by + /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=f(\pm0.0,0,p,m)=\text{NaN}$ + /// - $f(\infty,x,p,m)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ + /// - $f(-\infty,x,p,m)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ + /// - $f(0.0,x,p,m)=0.0$ if $x>0$ + /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ + /// - $f(-0.0,x,p,m)=-0.0$ if $x>0$ + /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_rational_prec_val_ref`] + /// instead. If you know that your target precision is the precision of the [`Float`] input, + /// consider using [`Float::div_rational_round_val_ref`] instead. If both of these things are + /// true, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_val_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 5, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "9.0"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_val_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 5, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "9.5"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_val_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 5, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "9.5"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_val_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 20, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "9.42477"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_val_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 20, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "9.42479"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_val_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 20, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "9.42477"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_rational_prec_round_val_ref( + mut self, + other: &Rational, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + let o = self.div_rational_prec_round_assign_ref(other, prec, rm); + (self, o) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result to the specified precision and + /// with the specified rounding mode. The [`Float`] is taken by reference and the [`Rational`] + /// by value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=f(\pm0.0,0,p,m)=\text{NaN}$ + /// - $f(\infty,x,p,m)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ + /// - $f(-\infty,x,p,m)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ + /// - $f(0.0,x,p,m)=0.0$ if $x>0$ + /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ + /// - $f(-0.0,x,p,m)=-0.0$ if $x>0$ + /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_rational_prec_ref_val`] + /// instead. If you know that your target precision is the precision of the [`Float`] input, + /// consider using [`Float::div_rational_round_ref_val`] instead. If both of these things are + /// true, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_val( + /// Rational::from_unsigneds(1u8, 3), + /// 5, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "9.0"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_val( + /// Rational::from_unsigneds(1u8, 3), + /// 5, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "9.5"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_val( + /// Rational::from_unsigneds(1u8, 3), + /// 5, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "9.5"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_val( + /// Rational::from_unsigneds(1u8, 3), + /// 20, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "9.42477"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_val( + /// Rational::from_unsigneds(1u8, 3), + /// 20, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "9.42479"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_val( + /// Rational::from_unsigneds(1u8, 3), + /// 20, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "9.42477"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_rational_prec_round_ref_val( + &self, + other: Rational, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + if max(self.complexity(), other.significant_bits()) < DIV_RATIONAL_THRESHOLD { + div_rational_prec_round_naive_ref_val(self, other, prec, rm) + } else { + div_rational_prec_round_direct_ref_val(self, other, prec, rm) + } + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result to the specified precision and + /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by + /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=f(\pm0.0,0,p,m)=\text{NaN}$ + /// - $f(\infty,x,p,m)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ + /// - $f(-\infty,x,p,m)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ + /// - $f(0.0,x,p,m)=0.0$ if $x>0$ + /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ + /// - $f(-0.0,x,p,m)=-0.0$ if $x>0$ + /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_rational_prec_ref_ref`] + /// instead. If you know that your target precision is the precision of the [`Float`] input, + /// consider using [`Float::div_rational_round_ref_ref`] instead. If both of these things are + /// true, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 5, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "9.0"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 5, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "9.5"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 5, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "9.5"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 20, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "9.42477"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 20, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "9.42479"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_round_ref_ref( + /// &Rational::from_unsigneds(1u8, 3), + /// 20, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "9.42477"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_rational_prec_round_ref_ref( + &self, + other: &Rational, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + if max(self.complexity(), other.significant_bits()) < DIV_RATIONAL_THRESHOLD { + div_rational_prec_round_naive_ref_ref(self, other, prec, rm) + } else { + div_rational_prec_round_direct_ref_ref(self, other, prec, rm) + } + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result to the nearest value of the + /// specified precision. The [`Float`] and the [`Rational`] are both are taken by value. An + /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal + /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=f(\pm0.0,0,p)=\text{NaN}$ + /// - $f(\infty,x,p)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,p)=-\infty$ if $x<0$ + /// - $f(-\infty,x,p)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,p)=\infty$ if $x<0$ + /// - $f(0.0,x,p)=0.0$ if $x>0$ + /// - $f(0.0,x,p)=-0.0$ if $x<0$ + /// - $f(-0.0,x,p)=-0.0$ if $x>0$ + /// - $f(-0.0,x,p)=0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_round`] instead. If you know that your target precision is the + /// precision of the [`Float`] input, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec(Rational::exact_from(1.5), 5); + /// assert_eq!(quotient.to_string(), "2.1"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec(Rational::exact_from(1.5), 20); + /// assert_eq!(quotient.to_string(), "2.094395"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_rational_prec(self, other: Rational, prec: u64) -> (Float, Ordering) { + self.div_rational_prec_round(other, prec, Nearest) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result to the nearest value of the + /// specified precision. The [`Float`] is taken by value and the [`Rational`] by reference. An + /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal + /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=f(\pm0.0,0,p)=\text{NaN}$ + /// - $f(\infty,x,p)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,p)=-\infty$ if $x<0$ + /// - $f(-\infty,x,p)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,p)=\infty$ if $x<0$ + /// - $f(0.0,x,p)=0.0$ if $x>0$ + /// - $f(0.0,x,p)=-0.0$ if $x<0$ + /// - $f(-0.0,x,p)=-0.0$ if $x>0$ + /// - $f(-0.0,x,p)=0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_round_val_ref`] instead. If you know that your target precision + /// is the precision of the [`Float`] input, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_val_ref(&Rational::exact_from(1.5), 5); + /// assert_eq!(quotient.to_string(), "2.1"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_val_ref(&Rational::exact_from(1.5), 20); + /// assert_eq!(quotient.to_string(), "2.094395"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_rational_prec_val_ref(self, other: &Rational, prec: u64) -> (Float, Ordering) { + self.div_rational_prec_round_val_ref(other, prec, Nearest) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result to the nearest value of the + /// specified precision. The [`Float`] is taken by reference and the [`Rational`] by value. An + /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal + /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=f(\pm0.0,0,p)=\text{NaN}$ + /// - $f(\infty,x,p)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,p)=-\infty$ if $x<0$ + /// - $f(-\infty,x,p)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,p)=\infty$ if $x<0$ + /// - $f(0.0,x,p)=0.0$ if $x>0$ + /// - $f(0.0,x,p)=-0.0$ if $x<0$ + /// - $f(-0.0,x,p)=-0.0$ if $x>0$ + /// - $f(-0.0,x,p)=0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_round_ref_val`] instead. If you know that your target precision + /// is the precision of the [`Float`] input, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::from(PI).div_rational_prec_ref_val(Rational::exact_from(1.5), 5); + /// assert_eq!(quotient.to_string(), "2.1"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_ref_val(Rational::exact_from(1.5), 20); + /// assert_eq!(quotient.to_string(), "2.094395"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_rational_prec_ref_val(&self, other: Rational, prec: u64) -> (Float, Ordering) { + self.div_rational_prec_round_ref_val(other, prec, Nearest) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result to the nearest value of the + /// specified precision. The [`Float`] and the [`Rational`] are both are taken by reference. An + /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal + /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=f(\pm0.0,0,p)=\text{NaN}$ + /// - $f(\infty,x,p)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,p)=-\infty$ if $x<0$ + /// - $f(-\infty,x,p)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,p)=\infty$ if $x<0$ + /// - $f(0.0,x,p)=0.0$ if $x>0$ + /// - $f(0.0,x,p)=-0.0$ if $x<0$ + /// - $f(-0.0,x,p)=-0.0$ if $x>0$ + /// - $f(-0.0,x,p)=0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_round_ref_ref`] instead. If you know that your target precision + /// is the precision of the [`Float`] input, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_ref_ref(&Rational::exact_from(1.5), 5); + /// assert_eq!(quotient.to_string(), "2.1"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_prec_ref_ref(&Rational::exact_from(1.5), 20); + /// assert_eq!(quotient.to_string(), "2.094395"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn div_rational_prec_ref_ref(&self, other: &Rational, prec: u64) -> (Float, Ordering) { + self.div_rational_prec_round_ref_ref(other, prec, Nearest) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result with the specified rounding mode. + /// The [`Float`] and the [`Rational`] are both are taken by value. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the [`Float`] input. + /// + /// Special cases: + /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=f(\pm0.0,0,m)=\text{NaN}$ + /// - $f(\infty,x,m)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,m)=-\infty$ if $x<0$ + /// - $f(-\infty,x,m)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,m)=\infty$ if $x<0$ + /// - $f(0.0,x,m)=0.0$ if $x>0$ + /// - $f(0.0,x,m)=-0.0$ if $x<0$ + /// - $f(-0.0,x,m)=-0.0$ if $x>0$ + /// - $f(-0.0,x,m)=0.0$ if $x<0$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::div_rational_prec_round`] instead. If you know you'll be using the `Nearest` + /// rounding mode, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round(Rational::from_unsigneds(1u8, 3), Floor); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round(Rational::from_unsigneds(1u8, 3), Ceiling); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round(Rational::from_unsigneds(1u8, 3), Nearest); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// ``` + #[inline] + pub fn div_rational_round(self, other: Rational, rm: RoundingMode) -> (Float, Ordering) { + let prec = self.significant_bits(); + self.div_rational_prec_round(other, prec, rm) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result with the specified rounding mode. + /// The [`Float`] is taken by value and the [`Rational`] by reference. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the [`Float`] input. + /// + /// Special cases: + /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=f(\pm0.0,0,m)=\text{NaN}$ + /// - $f(\infty,x,m)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,m)=-\infty$ if $x<0$ + /// - $f(-\infty,x,m)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,m)=\infty$ if $x<0$ + /// - $f(0.0,x,m)=0.0$ if $x>0$ + /// - $f(0.0,x,m)=-0.0$ if $x<0$ + /// - $f(-0.0,x,m)=-0.0$ if $x>0$ + /// - $f(-0.0,x,m)=0.0$ if $x<0$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::div_rational_prec_round_val_ref`] instead. If you know you'll be using the + /// `Nearest` rounding mode, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_val_ref(&Rational::from_unsigneds(1u8, 3), Floor); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_val_ref(&Rational::from_unsigneds(1u8, 3), Ceiling); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_val_ref(&Rational::from_unsigneds(1u8, 3), Nearest); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// ``` + #[inline] + pub fn div_rational_round_val_ref( + self, + other: &Rational, + rm: RoundingMode, + ) -> (Float, Ordering) { + let prec = self.significant_bits(); + self.div_rational_prec_round_val_ref(other, prec, rm) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result with the specified rounding mode. + /// The [`Float`] is taken by reference and the [`Rational`] by value. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the [`Float`] input. + /// + /// Special cases: + /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=f(\pm0.0,0,m)=\text{NaN}$ + /// - $f(\infty,x,m)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,m)=-\infty$ if $x<0$ + /// - $f(-\infty,x,m)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,m)=\infty$ if $x<0$ + /// - $f(0.0,x,m)=0.0$ if $x>0$ + /// - $f(0.0,x,m)=-0.0$ if $x<0$ + /// - $f(-0.0,x,m)=-0.0$ if $x>0$ + /// - $f(-0.0,x,m)=0.0$ if $x<0$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::div_rational_prec_round_ref_val`] instead. If you know you'll be using the + /// `Nearest` rounding mode, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_ref_val(Rational::from_unsigneds(1u8, 3), Floor); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_ref_val(Rational::from_unsigneds(1u8, 3), Ceiling); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_ref_val(Rational::from_unsigneds(1u8, 3), Nearest); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// ``` + #[inline] + pub fn div_rational_round_ref_val( + &self, + other: Rational, + rm: RoundingMode, + ) -> (Float, Ordering) { + let prec = self.significant_bits(); + self.div_rational_prec_round_ref_val(other, prec, rm) + } + + /// Divides a [`Float`] by a [`Rational`], rounding the result with the specified rounding mode. + /// The [`Float`] and the [`Rational`] are both are taken by reference. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the [`Float`] input. + /// + /// Special cases: + /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=f(\pm0.0,0,m)=\text{NaN}$ + /// - $f(\infty,x,m)=\infty$ if $x\geq 0$ + /// - $f(\infty,x,m)=-\infty$ if $x<0$ + /// - $f(-\infty,x,m)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x,m)=\infty$ if $x<0$ + /// - $f(0.0,x,m)=0.0$ if $x>0$ + /// - $f(0.0,x,m)=-0.0$ if $x<0$ + /// - $f(-0.0,x,m)=-0.0$ if $x>0$ + /// - $f(-0.0,x,m)=0.0$ if $x<0$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::div_rational_prec_round_ref_ref`] instead. If you know you'll be using the + /// `Nearest` rounding mode, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_ref_ref(&Rational::from_unsigneds(1u8, 3), Floor); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_ref_ref(&Rational::from_unsigneds(1u8, 3), Ceiling); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// + /// let (quotient, o) = + /// Float::from(PI).div_rational_round_ref_ref(&Rational::from_unsigneds(1u8, 3), Nearest); + /// assert_eq!(quotient.to_string(), "9.424777960769379"); + /// assert_eq!(o, Equal); + /// ``` + #[inline] + pub fn div_rational_round_ref_ref( + &self, + other: &Rational, + rm: RoundingMode, + ) -> (Float, Ordering) { + let prec = self.significant_bits(); + self.div_rational_prec_round_ref_ref(other, prec, rm) + } + + /// Divides a [`Float`] by a [`Rational`] in place, rounding the result to the specified + /// precision and with the specified rounding mode. The [`Rational`] is taken by value. An + /// [`Ordering`] is returned, indicating whether the rounded quotient is less than, equal to, or + /// greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::div_rational_prec_round`] documentation for information on special cases. + /// + /// If you know you'll be using `Nearest`, consider using [`Float::div_rational_prec_assign`] + /// instead. If you know that your target precision is the precision of the [`Float`] input, + /// consider using [`Float::div_rational_round_assign`] instead. If both of these things are + /// true, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Floor), + /// Less + /// ); + /// assert_eq!(x.to_string(), "9.0"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Ceiling), + /// Greater + /// ); + /// assert_eq!(x.to_string(), "9.5"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Nearest), + /// Greater + /// ); + /// assert_eq!(x.to_string(), "9.5"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Floor), + /// Less + /// ); + /// assert_eq!(x.to_string(), "9.42477"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Ceiling), + /// Greater + /// ); + /// assert_eq!(x.to_string(), "9.42479"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Nearest), + /// Less + /// ); + /// assert_eq!(x.to_string(), "9.42477"); + /// ``` + #[inline] + pub fn div_rational_prec_round_assign( + &mut self, + other: Rational, + prec: u64, + rm: RoundingMode, + ) -> Ordering { + if max(self.complexity(), other.significant_bits()) < DIV_RATIONAL_THRESHOLD { + div_rational_prec_round_assign_naive(self, other, prec, rm) + } else { + div_rational_prec_round_assign_direct(self, other, prec, rm) + } + } + + /// Divides a [`Float`] by a [`Rational`] in place, rounding the result to the specified + /// precision and with the specified rounding mode. The [`Rational`] is taken by reference. An + /// [`Ordering`] is returned, indicating whether the rounded quotient is less than, equal to, or + /// greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::div_rational_prec_round`] documentation for information on special cases. + /// + /// If you know you'll be using `Nearest`, consider using + /// [`Float::div_rational_prec_assign_ref`] instead. If you know that your target precision is + /// the precision of the [`Float`] input, consider using + /// [`Float::div_rational_round_assign_ref`] instead. If both of these things are true, consider + /// using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Floor), + /// Less + /// ); + /// assert_eq!(x.to_string(), "9.0"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Ceiling), + /// Greater + /// ); + /// assert_eq!(x.to_string(), "9.5"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Nearest), + /// Greater + /// ); + /// assert_eq!(x.to_string(), "9.5"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Floor), + /// Less + /// ); + /// assert_eq!(x.to_string(), "9.42477"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Ceiling), + /// Greater + /// ); + /// assert_eq!(x.to_string(), "9.42479"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Nearest), + /// Less + /// ); + /// assert_eq!(x.to_string(), "9.42477"); + /// ``` + #[inline] + pub fn div_rational_prec_round_assign_ref( + &mut self, + other: &Rational, + prec: u64, + rm: RoundingMode, + ) -> Ordering { + if max(self.complexity(), other.significant_bits()) < DIV_RATIONAL_THRESHOLD { + div_rational_prec_round_assign_naive_ref(self, other, prec, rm) + } else { + div_rational_prec_round_assign_direct_ref(self, other, prec, rm) + } + } + + /// Divides a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value of + /// the specified precision. The [`Rational`] is taken by value. An [`Ordering`] is returned, + /// indicating whether the rounded quotient is less than, equal to, or greater than the exact + /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function sets + /// the [`Float`] to `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::div_rational_prec`] documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_round_assign`] instead. If you know that your target precision is + /// the maximum of the precisions of the two inputs, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_assign(Rational::exact_from(1.5), 5), + /// Greater + /// ); + /// assert_eq!(x.to_string(), "2.1"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_assign(Rational::exact_from(1.5), 20), + /// Less + /// ); + /// assert_eq!(x.to_string(), "2.094395"); + /// ``` + #[inline] + pub fn div_rational_prec_assign(&mut self, other: Rational, prec: u64) -> Ordering { + self.div_rational_prec_round_assign(other, prec, Nearest) + } + + /// Divides a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value of + /// the specified precision. The [`Rational`] is taken by reference. An [`Ordering`] is + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function sets the [`Float`] to `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::div_rational_prec`] documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_round_assign`] instead. If you know that your target precision is + /// the maximum of the precisions of the two inputs, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_assign_ref(&Rational::exact_from(1.5), 5), + /// Greater + /// ); + /// assert_eq!(x.to_string(), "2.1"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_prec_assign_ref(&Rational::exact_from(1.5), 20), + /// Less + /// ); + /// assert_eq!(x.to_string(), "2.094395"); + /// ``` + #[inline] + pub fn div_rational_prec_assign_ref(&mut self, other: &Rational, prec: u64) -> Ordering { + self.div_rational_prec_round_assign_ref(other, prec, Nearest) + } + + /// Divides a [`Float`] by a [`Rational`] in place, rounding the result with the specified + /// rounding mode. The [`Rational`] is taken by value. An [`Ordering`] is returned, indicating + /// whether the rounded quotient is less than, equal to, or greater than the exact quotient. + /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the + /// [`Float`] to `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. + /// + /// See the [`Float::div_rational_round`] documentation for information on special cases. + /// + /// If you want to specify an output precision, consider using + /// [`Float::div_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest` + /// rounding mode, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_round_assign(Rational::from_unsigneds(1u8, 3), Floor), + /// Equal + /// ); + /// assert_eq!(x.to_string(), "9.424777960769379"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_round_assign(Rational::from_unsigneds(1u8, 3), Ceiling), + /// Equal + /// ); + /// assert_eq!(x.to_string(), "9.424777960769379"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_round_assign(Rational::from_unsigneds(1u8, 3), Nearest), + /// Equal + /// ); + /// assert_eq!(x.to_string(), "9.424777960769379"); + /// ``` + #[inline] + pub fn div_rational_round_assign(&mut self, other: Rational, rm: RoundingMode) -> Ordering { + let prec = self.significant_bits(); + self.div_rational_prec_round_assign(other, prec, rm) + } + + /// Divides a [`Float`] by a [`Rational`] in place, rounding the result with the specified + /// rounding mode. The [`Rational`] is taken by reference. An [`Ordering`] is returned, + /// indicating whether the rounded quotient is less than, equal to, or greater than the exact + /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function sets + /// the [`Float`] to `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// x \gets x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. + /// + /// See the [`Float::div_rational_round`] documentation for information on special cases. + /// + /// If you want to specify an output precision, consider using + /// [`Float::div_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest` + /// rounding mode, consider using `/=` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Floor), + /// Equal + /// ); + /// assert_eq!(x.to_string(), "9.424777960769379"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Ceiling), + /// Equal + /// ); + /// assert_eq!(x.to_string(), "9.424777960769379"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!( + /// x.div_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Nearest), + /// Equal + /// ); + /// assert_eq!(x.to_string(), "9.424777960769379"); + /// ``` + #[inline] + pub fn div_rational_round_assign_ref( + &mut self, + other: &Rational, + rm: RoundingMode, + ) -> Ordering { + let prec = self.significant_bits(); + self.div_rational_prec_round_assign_ref(other, prec, rm) + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result to the specified precision and + /// with the specified rounding mode. The [`Rational`] and the [`Float`] are both taken by + /// value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ + /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p,m)=0.0$ if $x>0$ + /// - $f(0,x,p,m)=-0.0$ if $x<0$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::rational_div_float_prec`] + /// instead. If you know that your target precision is the precision of the [`Float`] input, + /// consider using [`Float::rational_div_float_round`] instead. If both of these things are + /// true, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_round(Rational::from(3), Float::from(PI), 5, Floor); + /// assert_eq!(quotient.to_string(), "0.94"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_round(Rational::from(3), Float::from(PI), 5, Ceiling); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_round(Rational::from(3), Float::from(PI), 5, Nearest); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_round(Rational::from(3), Float::from(PI), 20, Floor); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_round(Rational::from(3), Float::from(PI), 20, Ceiling); + /// assert_eq!(quotient.to_string(), "0.95493"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_round(Rational::from(3), Float::from(PI), 20, Nearest); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_prec_round( + x: Rational, + y: Float, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + if max(x.significant_bits(), y.complexity()) < RATIONAL_DIV_THRESHOLD { + rational_div_float_prec_round_naive(x, y, prec, rm) + } else { + rational_div_float_prec_round_direct(x, y, prec, rm) + } + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result to the specified precision and + /// with the specified rounding mode. The [`Rational`] is taken by value and the [`Float`] by + /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ + /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p,m)=0.0$ if $x>0$ + /// - $f(0,x,p,m)=-0.0$ if $x<0$ + /// + /// If you know you'll be using `Nearest`, consider using + /// [`Float::rational_div_float_prec_val_ref`] instead. If you know that your target precision + /// is the precision of the [`Float`] input, consider using + /// [`Float::rational_div_float_round_val_ref`] instead. If both of these things are true, + /// consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_val_ref( + /// Rational::from(3), + /// &Float::from(PI), + /// 5, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "0.94"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_val_ref( + /// Rational::from(3), + /// &Float::from(PI), + /// 5, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_val_ref( + /// Rational::from(3), + /// &Float::from(PI), + /// 5, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_val_ref( + /// Rational::from(3), + /// &Float::from(PI), + /// 20, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_val_ref( + /// Rational::from(3), + /// &Float::from(PI), + /// 20, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "0.95493"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_val_ref( + /// Rational::from(3), + /// &Float::from(PI), + /// 20, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_prec_round_val_ref( + x: Rational, + y: &Float, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + if max(x.significant_bits(), y.complexity()) < RATIONAL_DIV_THRESHOLD { + rational_div_float_prec_round_naive_val_ref(x, y, prec, rm) + } else { + rational_div_float_prec_round_direct_val_ref(x, y, prec, rm) + } + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result to the specified precision and + /// with the specified rounding mode. The [`Rational`] is taken by reference and the [`Float`] + /// by value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ + /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p,m)=0.0$ if $x>0$ + /// - $f(0,x,p,m)=-0.0$ if $x<0$ + /// + /// If you know you'll be using `Nearest`, consider using + /// [`Float::rational_div_float_prec_ref_val`] instead. If you know that your target precision + /// is the precision of the [`Float`] input, consider using + /// [`Float::rational_div_float_round_ref_val`] instead. If both of these things are true, + /// consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_val( + /// &Rational::from(3), + /// Float::from(PI), + /// 5, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "0.94"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_val( + /// &Rational::from(3), + /// Float::from(PI), + /// 5, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_val( + /// &Rational::from(3), + /// Float::from(PI), + /// 5, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_val( + /// &Rational::from(3), + /// Float::from(PI), + /// 20, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_val( + /// &Rational::from(3), + /// Float::from(PI), + /// 20, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "0.95493"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_val( + /// &Rational::from(3), + /// Float::from(PI), + /// 20, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_prec_round_ref_val( + x: &Rational, + y: Float, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + if max(x.significant_bits(), y.complexity()) < RATIONAL_DIV_THRESHOLD { + rational_div_float_prec_round_naive_ref_val(x, y, prec, rm) + } else { + rational_div_float_prec_round_direct_ref_val(x, y, prec, rm) + } + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result to the specified precision and + /// with the specified rounding mode. The [`Rational`] and the [`Float`] are both taken by + /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less + /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to + /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,p,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ + /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p,m)=0.0$ if $x>0$ + /// - $f(0,x,p,m)=-0.0$ if $x<0$ + /// + /// If you know you'll be using `Nearest`, consider using + /// [`Float::rational_div_float_prec_ref_ref`] instead. If you know that your target precision + /// is the precision of the [`Float`] input, consider using + /// [`Float::rational_div_float_round_ref_ref`] instead. If both of these things are true, + /// consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits(), prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_ref( + /// &Rational::from(3), + /// &Float::from(PI), + /// 5, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "0.94"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_ref( + /// &Rational::from(3), + /// &Float::from(PI), + /// 5, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_ref( + /// &Rational::from(3), + /// &Float::from(PI), + /// 5, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_ref( + /// &Rational::from(3), + /// &Float::from(PI), + /// 20, + /// Floor, + /// ); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_ref( + /// &Rational::from(3), + /// &Float::from(PI), + /// 20, + /// Ceiling, + /// ); + /// assert_eq!(quotient.to_string(), "0.95493"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec_round_ref_ref( + /// &Rational::from(3), + /// &Float::from(PI), + /// 20, + /// Nearest, + /// ); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_prec_round_ref_ref( + x: &Rational, + y: &Float, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + if max(x.significant_bits(), y.complexity()) < RATIONAL_DIV_THRESHOLD { + rational_div_float_prec_round_naive_ref_ref(x, y, prec, rm) + } else { + rational_div_float_prec_round_direct_ref_ref(x, y, prec, rm) + } + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result to the nearest value of the + /// specified precision. The [`Rational`] and the [`Float`] are both are taken by value. An + /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal + /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(x,\text{NaN},p)=f(0,\pm0.0,p)=\text{NaN}$ + /// - $f(x,\infty,x,p)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p)=0.0$ if $x>0$ + /// - $f(0,x,p)=-0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::rational_div_float_prec_round`] instead. If you know that your target precision is + /// the precision of the [`Float`] input, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = Float::rational_div_float_prec(Rational::from(3), Float::from(PI), 5); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = Float::rational_div_float_prec(Rational::from(3), Float::from(PI), 20); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_prec(x: Rational, y: Float, prec: u64) -> (Float, Ordering) { + Float::rational_div_float_prec_round(x, y, prec, Nearest) + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result to the nearest value of the + /// specified precision. The [`Rational`] is taken by value and the [`Float`] by reference. An + /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal + /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(x,\text{NaN},p)=f(0,\pm0.0,p)=\text{NaN}$ + /// - $f(x,\infty,x,p)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p)=0.0$ if $x>0$ + /// - $f(0,x,p)=-0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::rational_div_float_prec_round_val_ref`] instead. If you know that your target + /// precision is the precision of the [`Float`] input, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_val_ref(Rational::from(3), &Float::from(PI), 5); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_val_ref(Rational::from(3), &Float::from(PI), 20); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_prec_val_ref(x: Rational, y: &Float, prec: u64) -> (Float, Ordering) { + Float::rational_div_float_prec_round_val_ref(x, y, prec, Nearest) + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result to the nearest value of the + /// specified precision. The [`Rational`] is taken by reference and the [`Float`] by value. An + /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal + /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(x,\text{NaN},p)=f(0,\pm0.0,p)=\text{NaN}$ + /// - $f(x,\infty,x,p)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p)=0.0$ if $x>0$ + /// - $f(0,x,p)=-0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::rational_div_float_prec_round_ref_val`] instead. If you know that your target + /// precision is the precision of the [`Float`] input, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_ref_val(&Rational::from(3), Float::from(PI), 5); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_ref_val(&Rational::from(3), Float::from(PI), 20); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_prec_ref_val(x: &Rational, y: Float, prec: u64) -> (Float, Ordering) { + Float::rational_div_float_prec_round_ref_val(x, y, prec, Nearest) + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result to the nearest value of the + /// specified precision. The [`Rational`] and the [`Float`] are both are taken by reference. An + /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal + /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], + /// whenever this function returns a `NaN` it also returns `Equal`. + /// + /// If the quotient is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,y,p) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(x,\text{NaN},p)=f(0,\pm0.0,p)=\text{NaN}$ + /// - $f(x,\infty,x,p)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p)=0.0$ if $x>0$ + /// - $f(0,x,p)=-0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::rational_div_float_prec_round_ref_ref`] instead. If you know that your target + /// precision is the precision of the [`Float`] input, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits(), prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_ref_ref(&Rational::from(3), &Float::from(PI), 5); + /// assert_eq!(quotient.to_string(), "0.97"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_prec_ref_ref(&Rational::from(3), &Float::from(PI), 20); + /// assert_eq!(quotient.to_string(), "0.954929"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_prec_ref_ref( + x: &Rational, + y: &Float, + prec: u64, + ) -> (Float, Ordering) { + Float::rational_div_float_prec_round_ref_ref(x, y, prec, Nearest) + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result with the specified rounding mode. + /// The [`Rational`] and the [`Float`] are both are taken by value. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the [`Float`] input. + /// + /// Special cases: + /// - $f(x,\text{NaN},m)=f(0,\pm0.0,m)=\text{NaN}$ + /// - $f(x,\infty,x,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,m)=0.0$ if $x>0$ + /// - $f(0,x,m)=-0.0$ if $x<0$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::rational_div_float_prec_round`] instead. If you know you'll be using the `Nearest` + /// rounding mode, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::rational_div_float_round(Rational::from(3), Float::from(PI), Floor); + /// assert_eq!(quotient.to_string(), "0.954929658551372"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = + /// Float::rational_div_float_round(Rational::from(3), Float::from(PI), Ceiling); + /// assert_eq!(quotient.to_string(), "0.9549296585513721"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_round(Rational::from(3), Float::from(PI), Nearest); + /// assert_eq!(quotient.to_string(), "0.954929658551372"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_round(x: Rational, y: Float, rm: RoundingMode) -> (Float, Ordering) { + let prec = y.significant_bits(); + Float::rational_div_float_prec_round(x, y, prec, rm) + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result with the specified rounding mode. + /// The [`Rational`] is taken by value and the [`Float`] by reference. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the [`Float`] input. + /// + /// Special cases: + /// - $f(x,\text{NaN},m)=f(0,\pm0.0,m)=\text{NaN}$ + /// - $f(x,\infty,x,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,m)=0.0$ if $x>0$ + /// - $f(0,x,m)=-0.0$ if $x<0$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::rational_div_float_prec_round_val_ref`] instead. If you know you'll be using the + /// `Nearest` rounding mode, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_val_ref(Rational::from(3), &Float::from(PI), Floor); + /// assert_eq!(quotient.to_string(), "0.954929658551372"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_val_ref(Rational::from(3), &Float::from(PI), Ceiling); + /// assert_eq!(quotient.to_string(), "0.9549296585513721"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_val_ref(Rational::from(3), &Float::from(PI), Nearest); + /// assert_eq!(quotient.to_string(), "0.954929658551372"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_round_val_ref( + x: Rational, + y: &Float, + rm: RoundingMode, + ) -> (Float, Ordering) { + let prec = y.significant_bits(); + Float::rational_div_float_prec_round_val_ref(x, y, prec, rm) + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result with the specified rounding mode. + /// The [`Rational`] is taken by reference and the [`Float`] by value. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the [`Float`] input. + /// + /// Special cases: + /// - $f(x,\text{NaN},m)=f(0,\pm0.0,m)=\text{NaN}$ + /// - $f(x,\infty,x,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,m)=0.0$ if $x>0$ + /// - $f(0,x,m)=-0.0$ if $x<0$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::rational_div_float_prec_round_ref_val`] instead. If you know you'll be using the + /// `Nearest` rounding mode, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_ref_val(&Rational::from(3), Float::from(PI), Floor); + /// assert_eq!(quotient.to_string(), "0.954929658551372"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_ref_val(&Rational::from(3), Float::from(PI), Ceiling); + /// assert_eq!(quotient.to_string(), "0.9549296585513721"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_ref_val(&Rational::from(3), Float::from(PI), Nearest); + /// assert_eq!(quotient.to_string(), "0.954929658551372"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_round_ref_val( + x: &Rational, + y: Float, + rm: RoundingMode, + ) -> (Float, Ordering) { + let prec = y.significant_bits(); + Float::rational_div_float_prec_round_ref_val(x, y, prec, rm) + } + + /// Divides a [`Rational`] by a [`Float`], rounding the result with the specified rounding mode. + /// The [`Rational`] and the [`Float`] are both are taken by reference. An [`Ordering`] is also + /// returned, indicating whether the rounded quotient is less than, equal to, or greater than + /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] + /// for a description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. + /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// + /// If the output has a precision, it is the precision of the [`Float`] input. + /// + /// Special cases: + /// - $f(x,\text{NaN},m)=f(0,\pm0.0,m)=\text{NaN}$ + /// - $f(x,\infty,x,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,m)=0.0$ if $x>0$ + /// - $f(0,x,m)=-0.0$ if $x<0$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::rational_div_float_prec_round_ref_ref`] instead. If you know you'll be using the + /// `Nearest` rounding mode, consider using `/` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), + /// y.significant_bits())`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to + /// represent the output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// use std::cmp::Ordering::*; + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_ref_ref(&Rational::from(3), &Float::from(PI), Floor); + /// assert_eq!(quotient.to_string(), "0.954929658551372"); + /// assert_eq!(o, Less); + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_ref_ref(&Rational::from(3), &Float::from(PI), Ceiling); + /// assert_eq!(quotient.to_string(), "0.9549296585513721"); + /// assert_eq!(o, Greater); + /// + /// let (quotient, o) = + /// Float::rational_div_float_round_ref_ref(&Rational::from(3), &Float::from(PI), Nearest); + /// assert_eq!(quotient.to_string(), "0.954929658551372"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn rational_div_float_round_ref_ref( + x: &Rational, + y: &Float, + rm: RoundingMode, + ) -> (Float, Ordering) { + let prec = y.significant_bits(); + Float::rational_div_float_prec_round_ref_ref(x, y, prec, rm) + } +} + +impl Div for Float { + type Output = Float; + + /// Divides two [`Float`]s, taking both by value. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. If the + /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with + /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the + /// `Nearest` rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm\infty)=f(\pm0.0,\pm0.0) = \text{NaN}$ + /// - $f(\infty,x)=\infty$ if $0.00.0$ + /// - $f(x,0.0)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0)=\infty$ if $x<0.0$ + /// - $f(0.0,x)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using [`Float::div_prec`] + /// instead. If you want to specify the output precision, consider using [`Float::div_round`]. + /// If you want both of these things, consider using [`Float::div_prec_round`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_float::Float; + /// + /// assert!((Float::from(1.5) / Float::NAN).is_nan()); + /// assert_eq!(Float::from(1.5) / Float::ZERO, Float::INFINITY); + /// assert_eq!( + /// Float::from(1.5) / Float::NEGATIVE_ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!(Float::from(-1.5) / Float::ZERO, Float::NEGATIVE_INFINITY); + /// assert_eq!(Float::from(-1.5) / Float::NEGATIVE_ZERO, Float::INFINITY); + /// assert!((Float::ZERO / Float::ZERO).is_nan()); + /// + /// assert_eq!((Float::from(1.5) / Float::from(2.5)).to_string(), "0.6"); + /// assert_eq!((Float::from(1.5) / Float::from(-2.5)).to_string(), "-0.6"); + /// assert_eq!((Float::from(-1.5) / Float::from(2.5)).to_string(), "-0.6"); + /// assert_eq!((Float::from(-1.5) / Float::from(-2.5)).to_string(), "0.6"); + /// ``` + #[inline] + fn div(self, other: Float) -> Float { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round(other, prec, Nearest).0 + } +} + +impl<'a> Div<&'a Float> for Float { + type Output = Float; + + /// Divides two [`Float`]s, taking the first by value and the second by reference. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. If the + /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with + /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the + /// `Nearest` rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm\infty)=f(\pm0.0,\pm0.0) = \text{NaN}$ + /// - $f(\infty,x)=\infty$ if $0.00.0$ + /// - $f(x,0.0)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0)=\infty$ if $x<0.0$ + /// - $f(0.0,x)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_val_ref`] instead. If you want to specify the output precision, consider + /// using [`Float::div_round_val_ref`]. If you want both of these things, consider using + /// [`Float::div_prec_round_val_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_float::Float; + /// + /// assert!((Float::from(1.5) / &Float::NAN).is_nan()); + /// assert_eq!(Float::from(1.5) / &Float::ZERO, Float::INFINITY); + /// assert_eq!( + /// Float::from(1.5) / &Float::NEGATIVE_ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!(Float::from(-1.5) / &Float::ZERO, Float::NEGATIVE_INFINITY); + /// assert_eq!(Float::from(-1.5) / &Float::NEGATIVE_ZERO, Float::INFINITY); + /// assert!((Float::ZERO / &Float::ZERO).is_nan()); + /// + /// assert_eq!((Float::from(1.5) / &Float::from(2.5)).to_string(), "0.6"); + /// assert_eq!((Float::from(1.5) / &Float::from(-2.5)).to_string(), "-0.6"); + /// assert_eq!((Float::from(-1.5) / &Float::from(2.5)).to_string(), "-0.6"); + /// assert_eq!((Float::from(-1.5) / &Float::from(-2.5)).to_string(), "0.6"); + /// ``` + #[inline] + fn div(self, other: &'a Float) -> Float { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_val_ref(other, prec, Nearest).0 + } +} + +impl<'a> Div for &'a Float { + type Output = Float; + + /// Divides two [`Float`]s, taking the first by reference and the second by value. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. If the + /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with + /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the + /// `Nearest` rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm\infty)=f(\pm0.0,\pm0.0) = \text{NaN}$ + /// - $f(\infty,x)=\infty$ if $0.00.0$ + /// - $f(x,0.0)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0)=\infty$ if $x<0.0$ + /// - $f(0.0,x)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_ref_val`] instead. If you want to specify the output precision, consider + /// using [`Float::div_round_ref_val`]. If you want both of these things, consider using + /// [`Float::div_prec_round_ref_val`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_float::Float; + /// + /// assert!((&Float::from(1.5) / Float::NAN).is_nan()); + /// assert_eq!(&Float::from(1.5) / Float::ZERO, Float::INFINITY); + /// assert_eq!( + /// &Float::from(1.5) / Float::NEGATIVE_ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!(&Float::from(-1.5) / Float::ZERO, Float::NEGATIVE_INFINITY); + /// assert_eq!(&Float::from(-1.5) / Float::NEGATIVE_ZERO, Float::INFINITY); + /// assert!((&Float::ZERO / Float::ZERO).is_nan()); + /// + /// assert_eq!((&Float::from(1.5) / Float::from(2.5)).to_string(), "0.6"); + /// assert_eq!((&Float::from(1.5) / Float::from(-2.5)).to_string(), "-0.6"); + /// assert_eq!((&Float::from(-1.5) / Float::from(2.5)).to_string(), "-0.6"); + /// assert_eq!((&Float::from(-1.5) / Float::from(-2.5)).to_string(), "0.6"); + /// ``` + #[inline] + fn div(self, other: Float) -> Float { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_ref_val(other, prec, Nearest).0 + } +} + +impl<'a, 'b> Div<&'a Float> for &'b Float { + type Output = Float; + + /// Divides two [`Float`]s, taking both by reference. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. If the + /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with + /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the + /// `Nearest` rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm\infty)=f(\pm0.0,\pm0.0) = \text{NaN}$ + /// - $f(\infty,x)=\infty$ if $0.00.0$ + /// - $f(x,0.0)=-\infty$ if $x<0.0$ + /// - $f(-\infty,x)=-\infty$ if $0.00.0$ + /// - $f(x,-0.0)=\infty$ if $x<0.0$ + /// - $f(0.0,x)=0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(0.0,x)=-0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// - $f(-0.0,x)=-0.0$ if $x$ is not NaN and $x>0.0$ + /// - $f(-0.0,x)=0.0$ if $x$ is not NaN and $x<0.0$ + /// - $f(x,-\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ + /// - $f(x,-\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_ref_ref`] instead. If you want to specify the output precision, consider + /// using [`Float::div_round_ref_ref`]. If you want both of these things, consider using + /// [`Float::div_prec_round_ref_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_float::Float; + /// + /// assert!((&Float::from(1.5) / &Float::NAN).is_nan()); + /// assert_eq!(&Float::from(1.5) / &Float::ZERO, Float::INFINITY); + /// assert_eq!( + /// &Float::from(1.5) / &Float::NEGATIVE_ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!(&Float::from(-1.5) / &Float::ZERO, Float::NEGATIVE_INFINITY); + /// assert_eq!(&Float::from(-1.5) / &Float::NEGATIVE_ZERO, Float::INFINITY); + /// assert!((&Float::ZERO / &Float::ZERO).is_nan()); + /// + /// assert_eq!((&Float::from(1.5) / &Float::from(2.5)).to_string(), "0.6"); + /// assert_eq!((&Float::from(1.5) / &Float::from(-2.5)).to_string(), "-0.6"); + /// assert_eq!((&Float::from(-1.5) / &Float::from(2.5)).to_string(), "-0.6"); + /// assert_eq!((&Float::from(-1.5) / &Float::from(-2.5)).to_string(), "0.6"); + /// ``` + #[inline] + fn div(self, other: &'a Float) -> Float { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_ref_ref(other, prec, Nearest).0 + } +} + +impl DivAssign for Float { + /// Divides a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side by + /// value. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. If the + /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with + /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the + /// `Nearest` rounding mode. + /// + /// $$ + /// x\gets = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// See the `/` documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_assign`] instead. If you want to specify the output precision, consider + /// using [`Float::div_round_assign`]. If you want both of these things, consider using + /// [`Float::div_prec_round_assign`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_float::Float; + /// + /// let mut x = Float::from(1.5); + /// x /= Float::NAN; + /// assert!(x.is_nan()); + /// + /// let mut x = Float::from(1.5); + /// x /= Float::ZERO; + /// assert_eq!(x, Float::INFINITY); + /// + /// let mut x = Float::from(1.5); + /// x /= Float::NEGATIVE_ZERO; + /// assert_eq!(x, Float::NEGATIVE_INFINITY); + /// + /// let mut x = Float::from(-1.5); + /// x /= Float::ZERO; + /// assert_eq!(x, Float::NEGATIVE_INFINITY); + /// + /// let mut x = Float::from(-1.5); + /// x /= Float::NEGATIVE_ZERO; + /// assert_eq!(x, Float::INFINITY); + /// + /// let mut x = Float::INFINITY; + /// x /= Float::INFINITY; + /// assert!(x.is_nan()); + /// + /// let mut x = Float::from(1.5); + /// x /= Float::from(2.5); + /// assert_eq!(x.to_string(), "0.6"); + /// + /// let mut x = Float::from(1.5); + /// x /= Float::from(-2.5); + /// assert_eq!(x.to_string(), "-0.6"); + /// + /// let mut x = Float::from(-1.5); + /// x /= Float::from(2.5); + /// assert_eq!(x.to_string(), "-0.6"); + /// + /// let mut x = Float::from(-1.5); + /// x /= Float::from(-2.5); + /// assert_eq!(x.to_string(), "0.6"); + /// ``` + #[inline] + fn div_assign(&mut self, other: Float) { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_assign(other, prec, Nearest); + } +} + +impl<'a> DivAssign<&'a Float> for Float { + /// Divides a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side by + /// reference. + /// + /// If the output has a precision, it is the maximum of the precisions of the inputs. If the + /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with + /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the + /// `Nearest` rounding mode. + /// + /// $$ + /// x\gets = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// See the `/` documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_prec_assign`] instead. If you want to specify the output precision, consider + /// using [`Float::div_round_assign`]. If you want both of these things, consider using + /// [`Float::div_prec_round_assign`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_float::Float; + /// + /// let mut x = Float::from(1.5); + /// x /= &Float::NAN; + /// assert!(x.is_nan()); + /// + /// let mut x = Float::from(1.5); + /// x /= &Float::ZERO; + /// assert_eq!(x, Float::INFINITY); + /// + /// let mut x = Float::from(1.5); + /// x /= &Float::NEGATIVE_ZERO; + /// assert_eq!(x, Float::NEGATIVE_INFINITY); + /// + /// let mut x = Float::from(-1.5); + /// x /= &Float::ZERO; + /// assert_eq!(x, Float::NEGATIVE_INFINITY); + /// + /// let mut x = Float::from(-1.5); + /// x /= &Float::NEGATIVE_ZERO; + /// assert_eq!(x, Float::INFINITY); + /// + /// let mut x = Float::INFINITY; + /// x /= &Float::INFINITY; + /// assert!(x.is_nan()); + /// + /// let mut x = Float::from(1.5); + /// x /= &Float::from(2.5); + /// assert_eq!(x.to_string(), "0.6"); + /// + /// let mut x = Float::from(1.5); + /// x /= &Float::from(-2.5); + /// assert_eq!(x.to_string(), "-0.6"); + /// + /// let mut x = Float::from(-1.5); + /// x /= &Float::from(2.5); + /// assert_eq!(x.to_string(), "-0.6"); + /// + /// let mut x = Float::from(-1.5); + /// x /= &Float::from(-2.5); + /// assert_eq!(x.to_string(), "0.6"); + /// ``` + #[inline] + fn div_assign(&mut self, other: &Float) { + let prec = max(self.significant_bits(), other.significant_bits()); + self.div_prec_round_assign_ref(other, prec, Nearest); + } +} + +impl Div for Float { + type Output = Float; + + /// Divides a [`Float`] by a [`Rational`], taking both by value. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// Special cases: + /// - $f(\text{NaN},x)=f(\pm\infty,0)=f(\pm0.0,0)=\text{NaN}$ + /// - $f(\infty,x)=\infty$ if $x\geq 0$ + /// - $f(\infty,x)=-\infty$ if $x<0$ + /// - $f(-\infty,x)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x)=\infty$ if $x<0$ + /// - $f(0.0,x)=0.0$ if $x>0$ + /// - $f(0.0,x)=-0.0$ if $x<0$ + /// - $f(-0.0,x)=-0.0$ if $x>0$ + /// - $f(-0.0,x)=0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec`] instead. If you want to specify the output precision, consider + /// using [`Float::div_rational_round`]. If you want both of these things, consider using + /// [`Float::div_rational_prec_round`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// assert!((Float::NAN / Rational::exact_from(1.5)).is_nan()); + /// assert_eq!(Float::INFINITY / Rational::exact_from(1.5), Float::INFINITY); + /// assert_eq!( + /// Float::NEGATIVE_INFINITY / Rational::exact_from(1.5), + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// Float::INFINITY / Rational::exact_from(-1.5), + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// Float::NEGATIVE_INFINITY / Rational::exact_from(-1.5), + /// Float::INFINITY + /// ); + /// + /// assert_eq!( + /// (Float::from(2.5) / Rational::exact_from(1.5)).to_string(), + /// "1.6666666666666667" + /// ); + /// assert_eq!( + /// (Float::from(2.5) / Rational::exact_from(-1.5)).to_string(), + /// "-1.6666666666666667" + /// ); + /// assert_eq!( + /// (Float::from(-2.5) / Rational::exact_from(1.5)).to_string(), + /// "-1.6666666666666667" + /// ); + /// assert_eq!( + /// (Float::from(-2.5) / Rational::exact_from(-1.5)).to_string(), + /// "1.6666666666666667" + /// ); + /// ``` + #[inline] + fn div(self, other: Rational) -> Float { + let prec = self.significant_bits(); + self.div_rational_prec_round(other, prec, Nearest).0 + } +} + +impl<'a> Div<&'a Rational> for Float { + type Output = Float; + + /// Divides a [`Float`] by a [`Rational`], taking the first by value and the second by + /// reference. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// Special cases: + /// - $f(\text{NaN},x)=f(\pm\infty,0)=f(\pm0.0,0)=\text{NaN}$ + /// - $f(\infty,x)=\infty$ if $x\geq 0$ + /// - $f(\infty,x)=-\infty$ if $x<0$ + /// - $f(-\infty,x)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x)=\infty$ if $x<0$ + /// - $f(0.0,x)=0.0$ if $x>0$ + /// - $f(0.0,x)=-0.0$ if $x<0$ + /// - $f(-0.0,x)=-0.0$ if $x>0$ + /// - $f(-0.0,x)=0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_val_ref`] instead. If you want to specify the output precision, + /// consider using [`Float::div_rational_round_val_ref`]. If you want both of these things, + /// consider using [`Float::div_rational_prec_round_val_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// assert!((Float::NAN / &Rational::exact_from(1.5)).is_nan()); + /// assert_eq!( + /// Float::INFINITY / &Rational::exact_from(1.5), + /// Float::INFINITY + /// ); + /// assert_eq!( + /// Float::NEGATIVE_INFINITY / &Rational::exact_from(1.5), + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// Float::INFINITY / &Rational::exact_from(-1.5), + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// Float::NEGATIVE_INFINITY / &Rational::exact_from(-1.5), + /// Float::INFINITY + /// ); + /// + /// assert_eq!( + /// (Float::from(2.5) / &Rational::exact_from(1.5)).to_string(), + /// "1.6666666666666667" + /// ); + /// assert_eq!( + /// (Float::from(2.5) / &Rational::exact_from(-1.5)).to_string(), + /// "-1.6666666666666667" + /// ); + /// assert_eq!( + /// (Float::from(-2.5) / &Rational::exact_from(1.5)).to_string(), + /// "-1.6666666666666667" + /// ); + /// assert_eq!( + /// (Float::from(-2.5) / &Rational::exact_from(-1.5)).to_string(), + /// "1.6666666666666667" + /// ); + /// ``` + #[inline] + fn div(self, other: &Rational) -> Float { + let prec = self.significant_bits(); + self.div_rational_prec_round_val_ref(other, prec, Nearest).0 + } +} + +impl<'a> Div for &'a Float { + type Output = Float; + + /// Divides a [`Float`] by a [`Rational`], taking the first by reference and the second by + /// value. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// Special cases: + /// - $f(\text{NaN},x)=f(\pm\infty,0)=f(\pm0.0,0)=\text{NaN}$ + /// - $f(\infty,x)=\infty$ if $x\geq 0$ + /// - $f(\infty,x)=-\infty$ if $x<0$ + /// - $f(-\infty,x)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x)=\infty$ if $x<0$ + /// - $f(0.0,x)=0.0$ if $x>0$ + /// - $f(0.0,x)=-0.0$ if $x<0$ + /// - $f(-0.0,x)=-0.0$ if $x>0$ + /// - $f(-0.0,x)=0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_ref_val`] instead. If you want to specify the output precision, + /// consider using [`Float::div_rational_round_ref_val`]. If you want both of these things, + /// consider using [`Float::div_rational_prec_round_ref_val`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// assert!((&Float::NAN / Rational::exact_from(1.5)).is_nan()); + /// assert_eq!( + /// &Float::INFINITY / Rational::exact_from(1.5), + /// Float::INFINITY + /// ); + /// assert_eq!( + /// &Float::NEGATIVE_INFINITY / Rational::exact_from(1.5), + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// &Float::INFINITY / Rational::exact_from(-1.5), + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// &Float::NEGATIVE_INFINITY / Rational::exact_from(-1.5), + /// Float::INFINITY + /// ); + /// + /// assert_eq!( + /// (&Float::from(2.5) / Rational::exact_from(1.5)).to_string(), + /// "1.6666666666666667" + /// ); + /// assert_eq!( + /// (&Float::from(2.5) / Rational::exact_from(-1.5)).to_string(), + /// "-1.6666666666666667" + /// ); + /// assert_eq!( + /// (&Float::from(-2.5) / Rational::exact_from(1.5)).to_string(), + /// "-1.6666666666666667" + /// ); + /// assert_eq!( + /// (&Float::from(-2.5) / Rational::exact_from(-1.5)).to_string(), + /// "1.6666666666666667" + /// ); + /// ``` + #[inline] + fn div(self, other: Rational) -> Float { + let prec = self.significant_bits(); + self.div_rational_prec_round_ref_val(other, prec, Nearest).0 + } +} + +impl<'a, 'b> Div<&'a Rational> for &'b Float { + type Output = Float; + + /// Divides a [`Float`] by a [`Rational`], taking both by reference. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// Special cases: + /// - $f(\text{NaN},x)=f(\pm\infty,0)=f(\pm0.0,0)=\text{NaN}$ + /// - $f(\infty,x)=\infty$ if $x\geq 0$ + /// - $f(\infty,x)=-\infty$ if $x<0$ + /// - $f(-\infty,x)=-\infty$ if $x\geq 0$ + /// - $f(-\infty,x)=\infty$ if $x<0$ + /// - $f(0.0,x)=0.0$ if $x>0$ + /// - $f(0.0,x)=-0.0$ if $x<0$ + /// - $f(-0.0,x)=-0.0$ if $x>0$ + /// - $f(-0.0,x)=0.0$ if $x<0$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_ref_ref`] instead. If you want to specify the output precision, + /// consider using [`Float::div_rational_round_ref_ref`]. If you want both of these things, + /// consider using [`Float::div_rational_prec_round_ref_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// assert!((&Float::NAN / &Rational::exact_from(1.5)).is_nan()); + /// assert_eq!( + /// &Float::INFINITY / &Rational::exact_from(1.5), + /// Float::INFINITY + /// ); + /// assert_eq!( + /// &Float::NEGATIVE_INFINITY / &Rational::exact_from(1.5), + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// &Float::INFINITY / &Rational::exact_from(-1.5), + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// &Float::NEGATIVE_INFINITY / &Rational::exact_from(-1.5), + /// Float::INFINITY + /// ); + /// + /// assert_eq!( + /// (&Float::from(2.5) / &Rational::exact_from(1.5)).to_string(), + /// "1.6666666666666667" + /// ); + /// assert_eq!( + /// (&Float::from(2.5) / &Rational::exact_from(-1.5)).to_string(), + /// "-1.6666666666666667" + /// ); + /// assert_eq!( + /// (&Float::from(-2.5) / &Rational::exact_from(1.5)).to_string(), + /// "-1.6666666666666667" + /// ); + /// assert_eq!( + /// (&Float::from(-2.5) / &Rational::exact_from(-1.5)).to_string(), + /// "1.6666666666666667" + /// ); + /// ``` + #[inline] + fn div(self, other: &Rational) -> Float { + let prec = self.significant_bits(); + self.div_rational_prec_round_ref_ref(other, prec, Nearest).0 + } +} + +impl DivAssign for Float { + /// Divides a [`Float`] by a [`Rational`] in place, taking the [`Rational`] by value. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// x\gets = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// See the `/` documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_assign`] instead. If you want to specify the output precision, + /// consider using [`Float::div_rational_round_assign`]. If you want both of these things, + /// consider using [`Float::div_rational_prec_round_assign`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// let mut x = Float::NAN; + /// x /= Rational::exact_from(1.5); + /// assert!(x.is_nan()); + /// + /// let mut x = Float::INFINITY; + /// x /= Rational::exact_from(1.5); + /// assert_eq!(x, Float::INFINITY); + /// + /// let mut x = Float::NEGATIVE_INFINITY; + /// x /= Rational::exact_from(1.5); + /// assert_eq!(x, Float::NEGATIVE_INFINITY); + /// + /// let mut x = Float::INFINITY; + /// x /= Rational::exact_from(-1.5); + /// assert_eq!(x, Float::NEGATIVE_INFINITY); + /// + /// let mut x = Float::NEGATIVE_INFINITY; + /// x /= Rational::exact_from(-1.5); + /// assert_eq!(x, Float::INFINITY); + /// + /// let mut x = Float::from(2.5); + /// x /= Rational::exact_from(1.5); + /// assert_eq!(x.to_string(), "1.6666666666666667"); + /// ``` + #[inline] + fn div_assign(&mut self, other: Rational) { + let prec = self.significant_bits(); + self.div_rational_prec_round_assign(other, prec, Nearest); + } +} + +impl<'a> DivAssign<&'a Rational> for Float { + /// Divides a [`Float`] by a [`Rational`] in place, taking the [`Rational`] by reference. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// x\gets = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// See the `/` documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::div_rational_prec_assign_ref`] instead. If you want to specify the output + /// precision, consider using [`Float::div_rational_round_assign_ref`]. If you want both of + /// these things, consider using [`Float::div_rational_prec_round_assign_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// let mut x = Float::NAN; + /// x /= &Rational::exact_from(1.5); + /// assert!(x.is_nan()); + /// + /// let mut x = Float::INFINITY; + /// x /= &Rational::exact_from(1.5); + /// assert_eq!(x, Float::INFINITY); + /// + /// let mut x = Float::NEGATIVE_INFINITY; + /// x /= &Rational::exact_from(1.5); + /// assert_eq!(x, Float::NEGATIVE_INFINITY); + /// + /// let mut x = Float::INFINITY; + /// x /= &Rational::exact_from(-1.5); + /// assert_eq!(x, Float::NEGATIVE_INFINITY); + /// + /// let mut x = Float::NEGATIVE_INFINITY; + /// x /= &Rational::exact_from(-1.5); + /// assert_eq!(x, Float::INFINITY); + /// + /// let mut x = Float::from(2.5); + /// x /= &Rational::exact_from(1.5); + /// assert_eq!(x.to_string(), "1.6666666666666667"); + /// ``` + #[inline] + fn div_assign(&mut self, other: &Rational) { + let prec = self.significant_bits(); + self.div_rational_prec_round_assign_ref(other, prec, Nearest); + } +} + +impl Div for Rational { + type Output = Float; + + /// Divides a [`Rational`] by a [`Float`], taking both by value. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// Special cases: + /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ + /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p,m)=0.0$ if $x>0$ + /// - $f(0,x,p,m)=-0.0$ if $x<0$ + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// assert!((Rational::exact_from(1.5) / Float::NAN).is_nan()); + /// assert_eq!(Rational::exact_from(1.5) / Float::ZERO, Float::INFINITY); + /// assert_eq!( + /// Rational::exact_from(1.5) / Float::NEGATIVE_ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// Rational::exact_from(-1.5) / Float::ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// Rational::exact_from(-1.5) / Float::NEGATIVE_ZERO, + /// Float::INFINITY + /// ); + /// + /// assert_eq!( + /// (Rational::exact_from(1.5) / Float::from(2.5)).to_string(), + /// "0.6" + /// ); + /// assert_eq!( + /// (Rational::exact_from(-1.5) / Float::from(2.5)).to_string(), + /// "-0.6" + /// ); + /// assert_eq!( + /// (Rational::exact_from(1.5) / Float::from(-2.5)).to_string(), + /// "-0.6" + /// ); + /// assert_eq!( + /// (Rational::exact_from(-1.5) / Float::from(-2.5)).to_string(), + /// "0.6" + /// ); + /// ``` + #[inline] + fn div(self, other: Float) -> Float { + let prec = other.significant_bits(); + Float::rational_div_float_prec_round(self, other, prec, Nearest).0 + } +} + +impl<'a> Div<&'a Float> for Rational { + type Output = Float; + + /// Divides a [`Rational`] by a [`Float`], taking the [`Rational`] by value and the [`Float`] by + /// reference. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// Special cases: + /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ + /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p,m)=0.0$ if $x>0$ + /// - $f(0,x,p,m)=-0.0$ if $x<0$ + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// assert!((Rational::exact_from(1.5) / &Float::NAN).is_nan()); + /// assert_eq!(Rational::exact_from(1.5) / &Float::ZERO, Float::INFINITY); + /// assert_eq!( + /// Rational::exact_from(1.5) / &Float::NEGATIVE_ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// Rational::exact_from(-1.5) / &Float::ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// Rational::exact_from(-1.5) / &Float::NEGATIVE_ZERO, + /// Float::INFINITY + /// ); + /// + /// assert_eq!( + /// (Rational::exact_from(1.5) / &Float::from(2.5)).to_string(), + /// "0.6" + /// ); + /// assert_eq!( + /// (Rational::exact_from(-1.5) / &Float::from(2.5)).to_string(), + /// "-0.6" + /// ); + /// assert_eq!( + /// (Rational::exact_from(1.5) / &Float::from(-2.5)).to_string(), + /// "-0.6" + /// ); + /// assert_eq!( + /// (Rational::exact_from(-1.5) / &Float::from(-2.5)).to_string(), + /// "0.6" + /// ); + /// ``` + #[inline] + fn div(self, other: &Float) -> Float { + let prec = other.significant_bits(); + Float::rational_div_float_prec_round_val_ref(self, other, prec, Nearest).0 + } +} + +impl<'a> Div for &'a Rational { + type Output = Float; + + /// Divides a [`Rational`] by a [`Float`], taking the [`Rational`] by reference and the + /// [`Float`] by value. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// Special cases: + /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ + /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p,m)=0.0$ if $x>0$ + /// - $f(0,x,p,m)=-0.0$ if $x<0$ + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// assert!((&Rational::exact_from(1.5) / Float::NAN).is_nan()); + /// assert_eq!(&Rational::exact_from(1.5) / Float::ZERO, Float::INFINITY); + /// assert_eq!( + /// &Rational::exact_from(1.5) / Float::NEGATIVE_ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// &Rational::exact_from(-1.5) / Float::ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// &Rational::exact_from(-1.5) / Float::NEGATIVE_ZERO, + /// Float::INFINITY + /// ); + /// + /// assert_eq!( + /// (&Rational::exact_from(1.5) / Float::from(2.5)).to_string(), + /// "0.6" + /// ); + /// assert_eq!( + /// (&Rational::exact_from(-1.5) / Float::from(2.5)).to_string(), + /// "-0.6" + /// ); + /// assert_eq!( + /// (&Rational::exact_from(1.5) / Float::from(-2.5)).to_string(), + /// "-0.6" + /// ); + /// assert_eq!( + /// (&Rational::exact_from(-1.5) / Float::from(-2.5)).to_string(), + /// "0.6" + /// ); + /// ``` + #[inline] + fn div(self, other: Float) -> Float { + let prec = other.significant_bits(); + Float::rational_div_float_prec_round_ref_val(self, other, prec, Nearest).0 + } +} + +impl<'a, 'b> Div<&'a Float> for &'b Rational { + type Output = Float; + + /// Divides a [`Rational`] by a [`Float`], taking both by reference. + /// + /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient + /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s + /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = x/y+\varepsilon. + /// $$ + /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. + /// + /// Special cases: + /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ + /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ + /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or #x=-0.0$ + /// - $f(0,x,p,m)=0.0$ if $x>0$ + /// - $f(0,x,p,m)=-0.0$ if $x<0$ + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::{ + /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, + /// }; + /// use malachite_base::num::conversion::traits::ExactFrom; + /// use malachite_float::Float; + /// use malachite_q::Rational; + /// + /// assert!((&Rational::exact_from(1.5) / &Float::NAN).is_nan()); + /// assert_eq!(&Rational::exact_from(1.5) / &Float::ZERO, Float::INFINITY); + /// assert_eq!( + /// &Rational::exact_from(1.5) / &Float::NEGATIVE_ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// &Rational::exact_from(-1.5) / &Float::ZERO, + /// Float::NEGATIVE_INFINITY + /// ); + /// assert_eq!( + /// &Rational::exact_from(-1.5) / &Float::NEGATIVE_ZERO, + /// Float::INFINITY + /// ); + /// + /// assert_eq!( + /// (&Rational::exact_from(1.5) / &Float::from(2.5)).to_string(), + /// "0.6" + /// ); + /// assert_eq!( + /// (&Rational::exact_from(-1.5) / &Float::from(2.5)).to_string(), + /// "-0.6" + /// ); + /// assert_eq!( + /// (&Rational::exact_from(1.5) / &Float::from(-2.5)).to_string(), + /// "-0.6" + /// ); + /// assert_eq!( + /// (&Rational::exact_from(-1.5) / &Float::from(-2.5)).to_string(), + /// "0.6" + /// ); + /// ``` + #[inline] + fn div(self, other: &Float) -> Float { + let prec = other.significant_bits(); + Float::rational_div_float_prec_round_ref_ref(self, other, prec, Nearest).0 + } +} diff --git a/malachite-float/src/arithmetic/is_power_of_2.rs b/malachite-float/src/arithmetic/is_power_of_2.rs index a0f3c2852..a51614d1a 100644 --- a/malachite-float/src/arithmetic/is_power_of_2.rs +++ b/malachite-float/src/arithmetic/is_power_of_2.rs @@ -71,6 +71,26 @@ impl IsPowerOf2 for Float { } } +pub(crate) fn abs_is_power_of_2(x: &Float) -> bool { + match x { + Float(Finite { significand, .. }) => { + let mut first = true; + for x in significand.limbs().rev() { + if first { + if x != HIGH_BIT { + return false; + } + first = false; + } else if x != 0 { + return false; + } + } + true + } + _ => false, + } +} + pub(crate) fn float_is_signed_min(f: &Float) -> bool { match f { Float(Finite { diff --git a/malachite-float/src/arithmetic/mod.rs b/malachite-float/src/arithmetic/mod.rs index 3451d4fa8..09dbea79a 100644 --- a/malachite-float/src/arithmetic/mod.rs +++ b/malachite-float/src/arithmetic/mod.rs @@ -11,6 +11,10 @@ pub mod abs; /// Addition of [`Float`](super::Float)s, and of [`Float`](super::Float)s with /// [`Rational`](malachite_q::Rational)s. pub mod add; +/// Division of [`Float`](super::Float)s, of [`Float`](super::Float)s by +/// [`Rational`](malachite_q::Rational)s, and of [`Rational`](malachite_q::Rational)s by +/// [`Float`](super::Float)s. +pub mod div; /// An implementations of [`IsPowerOf2`](malachite_base::num::arithmetic::traits::IsPowerOf2), a /// trait for determining whether a number is an integer power of 2. pub mod is_power_of_2; @@ -22,6 +26,10 @@ pub mod neg; /// Implementations of [`PowerOf2`](malachite_base::num::arithmetic::traits::PowerOf2), a trait for /// computing a power of 2. pub mod power_of_2; +/// Implementations of [`Reciprocal`](malachite_base::num::arithmetic::traits::Reciprocal) and +/// [`ReciprocalAssign`](malachite_base::num::arithmetic::traits::ReciprocalAssign), traits for +/// computing the reciprocal of a number. +pub mod reciprocal; /// Left-shifting a [`Float`](super::Float) (multiplying it by a power of 2). /// /// # shl @@ -109,6 +117,7 @@ pub mod shr; pub mod sign; /// Squaring of [`Float`](super::Float)s. pub mod square; -/// Subtraction of [`Float`](super::Float)s, and of [`Float`](super::Float)s with -/// [`Rational`](malachite_q::Rational)s. +/// Subtraction of [`Float`](super::Float)s, of [`Float`](super::Float)s by +/// [`Rational`](malachite_q::Rational)s, and of [`Rational`](malachite_q::Rational)s by +/// [`Float`](super::Float)s. pub mod sub; diff --git a/malachite-float/src/arithmetic/mul.rs b/malachite-float/src/arithmetic/mul.rs index 85914f7e0..788ab243d 100644 --- a/malachite-float/src/arithmetic/mul.rs +++ b/malachite-float/src/arithmetic/mul.rs @@ -12,10 +12,12 @@ use core::cmp::{ max, Ordering::{self, *}, }; +use core::mem::swap; use core::ops::{Mul, MulAssign}; -use malachite_base::num::arithmetic::traits::{NegAssign, Sign}; +use malachite_base::num::arithmetic::traits::{CheckedLogBase2, NegAssign, Sign}; +use malachite_base::num::basic::traits::Zero as ZeroTrait; use malachite_base::num::conversion::traits::ExactFrom; -use malachite_base::num::logic::traits::SignificantBits; +use malachite_base::num::logic::traits::{NotAssign, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_mul::{ mul_float_significands_in_place, mul_float_significands_in_place_ref, @@ -23,9 +25,110 @@ use malachite_nz::natural::arithmetic::float_mul::{ }; use malachite_q::Rational; -// The non-naive algorithm requires general float division, which we don't have yet. -pub fn mul_rational_prec_round_naive( - x: Float, +const MUL_RATIONAL_THRESHOLD: u64 = 50; + +fn mul_rational_prec_round_assign_naive( + x: &mut Float, + y: Rational, + prec: u64, + rm: RoundingMode, +) -> Ordering { + assert_ne!(prec, 0); + match (&mut *x, y) { + (float_nan!(), _) => Equal, + (Float(Infinity { sign }), y) => { + match y.sign() { + Equal => *x = float_nan!(), + Greater => {} + Less => { + sign.not_assign(); + } + }; + Equal + } + (Float(Zero { sign }), y) => { + if y < 0 { + sign.not_assign(); + }; + Equal + } + (x, y) => { + let not_sign = *x < 0; + let mut z = Float::ZERO; + swap(x, &mut z); + let (mut product, o) = + Float::from_rational_prec_round(Rational::exact_from(z) * y, prec, rm); + if product == 0u32 && not_sign { + product.neg_assign(); + } + *x = product; + o + } + } +} + +fn mul_rational_prec_round_assign_naive_ref( + x: &mut Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> Ordering { + assert_ne!(prec, 0); + match (&mut *x, y) { + (float_nan!(), _) => Equal, + (Float(Infinity { sign }), y) => { + match y.sign() { + Equal => *x = float_nan!(), + Greater => {} + Less => { + sign.not_assign(); + } + }; + Equal + } + (Float(Zero { sign }), y) => { + if *y < 0 { + sign.not_assign(); + }; + Equal + } + (x, y) => { + let not_sign = *x < 0; + let mut z = Float::ZERO; + swap(x, &mut z); + let (mut product, o) = + Float::from_rational_prec_round(Rational::exact_from(z) * y, prec, rm); + if product == 0u32 && not_sign { + product.neg_assign(); + } + *x = product; + o + } + } +} + +pub_test! {mul_rational_prec_round_naive( + mut x: Float, + y: Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + let o = mul_rational_prec_round_assign_naive(&mut x, y, prec, rm); + (x, o) +}} + +pub_test! {mul_rational_prec_round_naive_val_ref( + mut x: Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + let o = mul_rational_prec_round_assign_naive_ref(&mut x, y, prec, rm); + (x, o) +}} + +pub_test! {mul_rational_prec_round_naive_ref_val( + x: &Float, y: Rational, prec: u64, rm: RoundingMode, @@ -36,30 +139,280 @@ pub fn mul_rational_prec_round_naive( (Float(Infinity { sign }), y) => ( match y.sign() { Equal => float_nan!(), - Greater => Float(Infinity { sign }), - Less => Float(Infinity { sign: !sign }), + Greater => Float(Infinity { sign: *sign }), + Less => Float(Infinity { sign: !*sign }), }, Equal, ), (Float(Zero { sign }), y) => ( if y >= 0u32 { - Float(Zero { sign }) + Float(Zero { sign: *sign }) } else { - Float(Zero { sign: !sign }) + Float(Zero { sign: !*sign }) }, Equal, ), (x, y) => { let (mut product, o) = - Float::from_rational_prec_round(Rational::exact_from(&x) * y, prec, rm); - if product == 0u32 && x < 0 { + Float::from_rational_prec_round(Rational::exact_from(x) * y, prec, rm); + if product == 0u32 && *x < 0 { product.neg_assign(); } (product, o) } } +}} + +pub_test! {mul_rational_prec_round_naive_ref_ref( + x: &Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (x, y) { + (float_nan!(), _) => (float_nan!(), Equal), + (Float(Infinity { sign }), y) => ( + match y.sign() { + Equal => float_nan!(), + Greater => Float(Infinity { sign: *sign }), + Less => Float(Infinity { sign: !*sign }), + }, + Equal, + ), + (Float(Zero { sign }), y) => ( + if *y >= 0u32 { + Float(Zero { sign: *sign }) + } else { + Float(Zero { sign: !*sign }) + }, + Equal, + ), + (x, y) => { + let (mut product, o) = + Float::from_rational_prec_round(Rational::exact_from(x) * y, prec, rm); + if product == 0u32 && *x < 0 { + product.neg_assign(); + } + (product, o) + } + } +}} + +fn mul_rational_prec_round_assign_direct( + x: &mut Float, + y: Rational, + prec: u64, + mut rm: RoundingMode, +) -> Ordering { + assert_ne!(prec, 0); + let sign = y >= 0; + let (n, d) = y.into_numerator_and_denominator(); + if !sign { + rm.neg_assign(); + } + let o = match ( + if n == 0 { None } else { n.checked_log_base_2() }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let o = x.set_prec_round(prec, rm); + *x <<= log_n; + *x >>= log_d; + o + } + (None, Some(log_d)) => { + let o = x.mul_prec_round_assign(Float::from_natural_min_prec(n), prec, rm); + *x >>= log_d; + o + } + (Some(log_n), None) => { + let o = x.div_prec_round_assign(Float::from_natural_min_prec(d), prec, rm); + *x <<= log_n; + o + } + (None, None) => { + let n = Float::from_natural_min_prec(n); + let d = Float::from_natural_min_prec(d); + let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits(); + x.mul_prec_round_assign(n, mul_prec, Floor); + x.div_prec_round_assign(d, prec, rm) + } + }; + if sign { + o + } else { + x.neg_assign(); + o.reverse() + } +} + +fn mul_rational_prec_round_assign_direct_ref( + x: &mut Float, + y: &Rational, + prec: u64, + mut rm: RoundingMode, +) -> Ordering { + assert_ne!(prec, 0); + let sign = *y >= 0; + let (n, d) = y.numerator_and_denominator_ref(); + if !sign { + rm.neg_assign(); + } + let o = match ( + if *n == 0 { + None + } else { + n.checked_log_base_2() + }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let o = x.set_prec_round(prec, rm); + *x <<= log_n; + *x >>= log_d; + o + } + (None, Some(log_d)) => { + let o = x.mul_prec_round_assign(Float::from_natural_min_prec_ref(n), prec, rm); + *x >>= log_d; + o + } + (Some(log_n), None) => { + let o = x.div_prec_round_assign(Float::from_natural_min_prec_ref(d), prec, rm); + *x <<= log_n; + o + } + (None, None) => { + let n = Float::from_natural_min_prec_ref(n); + let d = Float::from_natural_min_prec_ref(d); + let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits(); + x.mul_prec_round_assign(n, mul_prec, Floor); + x.div_prec_round_assign(d, prec, rm) + } + }; + if sign { + o + } else { + x.neg_assign(); + o.reverse() + } } +pub_test! {mul_rational_prec_round_direct( + mut x: Float, + y: Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + let o = mul_rational_prec_round_assign_direct(&mut x, y, prec, rm); + (x, o) +}} + +pub_test! {mul_rational_prec_round_direct_val_ref( + mut x: Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + let o = mul_rational_prec_round_assign_direct_ref(&mut x, y, prec, rm); + (x, o) +}} + +pub_test! {mul_rational_prec_round_direct_ref_val( + x: &Float, + y: Rational, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + let sign = y >= 0; + let (n, d) = y.into_numerator_and_denominator(); + if !sign { + rm.neg_assign(); + } + let (product, o) = match ( + if n == 0 { None } else { n.checked_log_base_2() }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let (product, o) = Float::from_float_prec_round_ref(x, prec, rm); + (product << log_n >> log_d, o) + } + (None, Some(log_d)) => { + let (product, o) = x.mul_prec_round_ref_val(Float::from_natural_min_prec(n), prec, rm); + (product >> log_d, o) + } + (Some(log_n), None) => { + let (product, o) = x.div_prec_round_ref_val(Float::from_natural_min_prec(d), prec, rm); + (product << log_n, o) + } + (None, None) => { + let n = Float::from_natural_min_prec(n); + let d = Float::from_natural_min_prec(d); + let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits(); + x.mul_prec_round_ref_val(n, mul_prec, Floor) + .0 + .div_prec_round(d, prec, rm) + } + }; + if sign { + (product, o) + } else { + (-product, o.reverse()) + } +}} + +pub_test! {mul_rational_prec_round_direct_ref_ref( + x: &Float, + y: &Rational, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + let sign = *y >= 0; + let (n, d) = y.numerator_and_denominator_ref(); + if !sign { + rm.neg_assign(); + } + let (product, o) = match ( + if *n == 0 { + None + } else { + n.checked_log_base_2() + }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => { + let (product, o) = Float::from_float_prec_round_ref(x, prec, rm); + (product << log_n >> log_d, o) + } + (None, Some(log_d)) => { + let (product, o) = + x.mul_prec_round_ref_val(Float::from_natural_min_prec_ref(n), prec, rm); + (product >> log_d, o) + } + (Some(log_n), None) => { + let (product, o) = + x.div_prec_round_ref_val(Float::from_natural_min_prec_ref(d), prec, rm); + (product << log_n, o) + } + (None, None) => { + let n = Float::from_natural_min_prec_ref(n); + let d = Float::from_natural_min_prec_ref(d); + let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits(); + x.mul_prec_round_ref_val(n, mul_prec, Floor) + .0 + .div_prec_round(d, prec, rm) + } + }; + if sign { + (product, o) + } else { + (-product, o.reverse()) + } +}} + impl Float { /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also @@ -70,13 +423,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = xy+\epsilon. + /// f(x,y,p,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -102,9 +455,9 @@ impl Float { /// instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -163,13 +516,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = xy+\epsilon. + /// f(x,y,p,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -195,9 +548,9 @@ impl Float { /// consider using `*` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -256,13 +609,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = xy+\epsilon. + /// f(x,y,p,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -288,9 +641,9 @@ impl Float { /// consider using `*` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -349,13 +702,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = xy+\epsilon. + /// f(x,y,p,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -381,9 +734,9 @@ impl Float { /// consider using `*` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -507,10 +860,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = xy+\epsilon. + /// f(x,y,p) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -531,9 +884,9 @@ impl Float { /// the precisions of the two inputs, consider using `*` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -568,10 +921,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = xy+\epsilon. + /// f(x,y,p) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -592,9 +945,9 @@ impl Float { /// maximum of the precisions of the two inputs, consider using `*` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -629,10 +982,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = xy+\epsilon. + /// f(x,y,p) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -653,9 +1006,9 @@ impl Float { /// maximum of the precisions of the two inputs, consider using `*` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -690,10 +1043,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = xy+\epsilon. + /// f(x,y,p) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -714,9 +1067,9 @@ impl Float { /// maximum of the precisions of the two inputs, consider using `*` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -750,13 +1103,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = xy+\epsilon. + /// f(x,y,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -823,13 +1176,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = xy+\epsilon. + /// f(x,y,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -896,13 +1249,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = xy+\epsilon. + /// f(x,y,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -969,13 +1322,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = xy+\epsilon. + /// f(x,y,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1041,13 +1394,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1059,9 +1412,9 @@ impl Float { /// consider using `*=` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -1198,13 +1551,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1216,9 +1569,9 @@ impl Float { /// true, consider using `*=` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -1361,10 +1714,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1375,9 +1728,9 @@ impl Float { /// maximum of the precisions of the two inputs, consider using `*=` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -1412,10 +1765,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1426,9 +1779,9 @@ impl Float { /// maximum of the precisions of the two inputs, consider using `*=` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. @@ -1462,13 +1815,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1525,13 +1878,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1587,13 +1940,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = xy+\epsilon. + /// f(x,y,p,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1614,7 +1967,12 @@ impl Float { /// using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. @@ -1677,13 +2035,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = xy+\epsilon. + /// f(x,y,p,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1704,7 +2062,12 @@ impl Float { /// true, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. @@ -1785,13 +2148,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = xy+\epsilon. + /// f(x,y,p,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1812,7 +2175,12 @@ impl Float { /// true, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. @@ -1880,7 +2248,11 @@ impl Float { prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { - mul_rational_prec_round_naive(self.clone(), other, prec, rm) + if max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD { + mul_rational_prec_round_naive_ref_val(self, other, prec, rm) + } else { + mul_rational_prec_round_direct_ref_val(self, other, prec, rm) + } } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and @@ -1892,13 +2264,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = xy+\epsilon. + /// f(x,y,p,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1919,7 +2291,12 @@ impl Float { /// true, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. @@ -1987,7 +2364,11 @@ impl Float { prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { - mul_rational_prec_round_naive(self.clone(), other.clone(), prec, rm) + if max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD { + mul_rational_prec_round_naive_ref_ref(self, other, prec, rm) + } else { + mul_rational_prec_round_direct_ref_ref(self, other, prec, rm) + } } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the @@ -2001,10 +2382,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = xy+\epsilon. + /// f(x,y,p) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2024,7 +2405,12 @@ impl Float { /// precision of the [`Float`] input, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Examples /// ``` @@ -2058,10 +2444,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = xy+\epsilon. + /// f(x,y,p) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2081,7 +2467,12 @@ impl Float { /// is the precision of the [`Float`] input, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Examples /// ``` @@ -2116,10 +2507,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = xy+\epsilon. + /// f(x,y,p) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2139,7 +2530,12 @@ impl Float { /// is the precision of the [`Float`] input, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Examples /// ``` @@ -2173,10 +2569,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = xy+\epsilon. + /// f(x,y,p) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2196,7 +2592,12 @@ impl Float { /// is the precision of the [`Float`] input, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Examples /// ``` @@ -2230,13 +2631,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = xy+\epsilon. + /// f(x,y,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2256,7 +2657,9 @@ impl Float { /// rounding mode, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. @@ -2304,13 +2707,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = xy+\epsilon. + /// f(x,y,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2330,7 +2733,9 @@ impl Float { /// `Nearest` rounding mode, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. @@ -2382,13 +2787,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = xy+\epsilon. + /// f(x,y,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2408,7 +2813,9 @@ impl Float { /// `Nearest` rounding mode, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. @@ -2460,13 +2867,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = xy+\epsilon. + /// f(x,y,m) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2486,7 +2893,9 @@ impl Float { /// `Nearest` rounding mode, consider using `*` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. @@ -2537,13 +2946,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2555,10 +2964,12 @@ impl Float { /// true, consider using `*=` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), - /// prec)`. + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. @@ -2620,9 +3031,11 @@ impl Float { prec: u64, rm: RoundingMode, ) -> Ordering { - let (p, o) = mul_rational_prec_round_naive(self.clone(), other, prec, rm); - *self = p; - o + if max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD { + mul_rational_prec_round_assign_naive(self, other, prec, rm) + } else { + mul_rational_prec_round_assign_direct(self, other, prec, rm) + } } /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the specified @@ -2634,13 +3047,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2653,10 +3066,12 @@ impl Float { /// using `*=` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), - /// prec)`. + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. @@ -2718,9 +3133,11 @@ impl Float { prec: u64, rm: RoundingMode, ) -> Ordering { - let (p, o) = mul_rational_prec_round_naive(self.clone(), other.clone(), prec, rm); - *self = p; - o + if max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD { + mul_rational_prec_round_assign_naive_ref(self, other, prec, rm) + } else { + mul_rational_prec_round_assign_direct_ref(self, other, prec, rm) + } } /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value @@ -2734,10 +3151,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2748,7 +3165,12 @@ impl Float { /// the maximum of the precisions of the two inputs, consider using `*=` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Examples /// ``` @@ -2788,10 +3210,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2802,7 +3224,12 @@ impl Float { /// the maximum of the precisions of the two inputs, consider using `*=` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits(), prec)`. /// /// # Examples /// ``` @@ -2841,13 +3268,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// @@ -2858,7 +3285,12 @@ impl Float { /// rounding mode, consider using `*=` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to @@ -2909,13 +3341,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// x \gets xy+\epsilon. + /// x \gets xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// @@ -2926,7 +3358,12 @@ impl Float { /// rounding mode, consider using `*=` instead. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to @@ -2983,11 +3420,11 @@ impl Mul for Float { /// `Nearest` rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the maximum precision of the inputs. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$ @@ -3056,11 +3493,11 @@ impl<'a> Mul<&'a Float> for Float { /// `Nearest` rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the maximum precision of the inputs. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$ @@ -3130,11 +3567,11 @@ impl<'a> Mul for &'a Float { /// `Nearest` rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the maximum precision of the inputs. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$ @@ -3204,11 +3641,11 @@ impl<'a, 'b> Mul<&'a Float> for &'b Float { /// `Nearest` rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the maximum precision of the inputs. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$ @@ -3277,11 +3714,11 @@ impl MulAssign for Float { /// `Nearest` rounding mode. /// /// $$ - /// x\gets = xy+\epsilon. + /// x\gets = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the maximum precision of the inputs. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. /// /// See the `*` documentation for information on special cases. /// @@ -3360,11 +3797,11 @@ impl<'a> MulAssign<&'a Float> for Float { /// `Nearest` rounding mode. /// /// $$ - /// x\gets = xy+\epsilon. + /// x\gets = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the maximum precision of the inputs. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. /// /// See the `*` documentation for information on special cases. /// @@ -3444,11 +3881,11 @@ impl Mul for Float { /// rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$ @@ -3467,7 +3904,9 @@ impl Mul for Float { /// [`Float::mul_rational_prec_round`]. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. @@ -3518,11 +3957,11 @@ impl<'a> Mul<&'a Rational> for Float { /// rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$ @@ -3541,7 +3980,9 @@ impl<'a> Mul<&'a Rational> for Float { /// consider using [`Float::mul_rational_prec_round_val_ref`]. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. @@ -3595,11 +4036,11 @@ impl<'a> Mul for &'a Float { /// rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$ @@ -3618,7 +4059,9 @@ impl<'a> Mul for &'a Float { /// consider using [`Float::mul_rational_prec_round_ref_val`]. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. @@ -3671,11 +4114,11 @@ impl<'a, 'b> Mul<&'a Rational> for &'b Float { /// rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$ @@ -3694,7 +4137,9 @@ impl<'a, 'b> Mul<&'a Rational> for &'b Float { /// consider using [`Float::mul_rational_prec_round_ref_ref`]. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. @@ -3745,11 +4190,11 @@ impl MulAssign for Float { /// rounding mode. /// /// $$ - /// x\gets = xy+\epsilon. + /// x\gets = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// See the `*` documentation for information on special cases. /// @@ -3759,7 +4204,12 @@ impl MulAssign for Float { /// consider using [`Float::mul_rational_prec_round_assign`]. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. /// /// # Examples /// ``` @@ -3808,11 +4258,11 @@ impl<'a> MulAssign<&'a Rational> for Float { /// rounding mode. /// /// $$ - /// x\gets = xy+\epsilon. + /// x\gets = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// See the `*` documentation for information on special cases. /// @@ -3822,7 +4272,12 @@ impl<'a> MulAssign<&'a Rational> for Float { /// these things, consider using [`Float::mul_rational_prec_round_assign_ref`]. /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. /// /// # Examples /// ``` @@ -3873,11 +4328,11 @@ impl Mul for Rational { /// rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$ @@ -3891,7 +4346,12 @@ impl Mul for Rational { /// - $f(x,-0.0)=0.0$ if $x<0$ /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. /// /// # Examples /// ``` @@ -3939,11 +4399,11 @@ impl<'a> Mul<&'a Float> for Rational { /// rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$ @@ -3957,7 +4417,12 @@ impl<'a> Mul<&'a Float> for Rational { /// - $f(x,-0.0)=0.0$ if $x<0$ /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. /// /// # Examples /// ``` @@ -4008,11 +4473,11 @@ impl<'a> Mul for &'a Rational { /// rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$ @@ -4026,7 +4491,12 @@ impl<'a> Mul for &'a Rational { /// - $f(x,-0.0)=0.0$ if $x<0$ /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. /// /// # Examples /// ``` @@ -4076,11 +4546,11 @@ impl<'a, 'b> Mul<&'a Float> for &'b Rational { /// rounding mode. /// /// $$ - /// f(x,y) = xy+\epsilon. + /// f(x,y) = xy+\varepsilon. /// $$ - /// - If $xy$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $xy$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, where - /// $p$ is the precision of the input [`Float`]. + /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, + /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$ @@ -4094,7 +4564,12 @@ impl<'a, 'b> Mul<&'a Float> for &'b Rational { /// - $f(x,-0.0)=0.0$ if $x<0$ /// /// # Worst-case complexity - /// TODO + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// other.significant_bits())`. /// /// # Examples /// ``` diff --git a/malachite-float/src/arithmetic/reciprocal.rs b/malachite-float/src/arithmetic/reciprocal.rs new file mode 100644 index 000000000..215291cf9 --- /dev/null +++ b/malachite-float/src/arithmetic/reciprocal.rs @@ -0,0 +1,867 @@ +// 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; +use crate::{float_nan, Float}; +use core::cmp::Ordering::{self, *}; +use malachite_base::num::arithmetic::traits::{ + IsPowerOf2, NegAssign, Reciprocal, ReciprocalAssign, +}; +use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::num::logic::traits::SignificantBits; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_nz::natural::arithmetic::float_reciprocal::reciprocal_float_significand_ref; + +impl Float { + /// Takes the reciprocal of a [`Float`], rounding the result to the specified precision and with + /// the specified rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also + /// returned, indicating whether the rounded reciprocal is less than, equal to, or greater than + /// the exact reciprocal. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,p,m) = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$. + /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},p,m)=\text{NaN}$ + /// - $f(\infty,p,m)=0.0$ + /// - $f(-\infty,p,m)=-0.0$ + /// - $f(0.0,p,m)=\infty$ + /// - $f(-0.0,p,m)=-\infty$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_prec`] instead. If + /// you know that your target precision is the precision of the input, consider using + /// [`Float::reciprocal_round`] instead. If both of these things are true, consider using + /// [`Float::reciprocal`] instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact reciprocation. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(5, Floor); + /// assert_eq!(reciprocal.to_string(), "0.31"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(5, Ceiling); + /// assert_eq!(reciprocal.to_string(), "0.33"); + /// assert_eq!(o, Greater); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(5, Nearest); + /// assert_eq!(reciprocal.to_string(), "0.31"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(20, Floor); + /// assert_eq!(reciprocal.to_string(), "0.3183098"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(20, Ceiling); + /// assert_eq!(reciprocal.to_string(), "0.3183103"); + /// assert_eq!(o, Greater); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(20, Nearest); + /// assert_eq!(reciprocal.to_string(), "0.3183098"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn reciprocal_prec_round(mut self, prec: u64, rm: RoundingMode) -> (Float, Ordering) { + let o = self.reciprocal_prec_round_assign(prec, rm); + (self, o) + } + + /// Takes the reciprocal of a [`Float`], rounding the result to the specified precision and with + /// the specified rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also + /// returned, indicating whether the rounded reciprocal is less than, equal to, or greater than + /// the exact reciprocal. Although `NaN`s are not comparable to any [`Float`], whenever this + /// function returns a `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// f(x,p,m) = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$. + /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},p,m)=\text{NaN}$ + /// - $f(\infty,p,m)=0.0$ + /// - $f(-\infty,p,m)=-0.0$ + /// - $f(0.0,p,m)=\infty$ + /// - $f(-0.0,p,m)=-\infty$ + /// + /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_prec_ref`] + /// instead. If you know that your target precision is the precision of the input, consider + /// using [`Float::reciprocal_round_ref`] instead. If both of these things are true, consider + /// using `(&Float)::reciprocal()` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact reciprocation. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(5, Floor); + /// assert_eq!(reciprocal.to_string(), "0.31"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(5, Ceiling); + /// assert_eq!(reciprocal.to_string(), "0.33"); + /// assert_eq!(o, Greater); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(5, Nearest); + /// assert_eq!(reciprocal.to_string(), "0.31"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(20, Floor); + /// assert_eq!(reciprocal.to_string(), "0.3183098"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(20, Ceiling); + /// assert_eq!(reciprocal.to_string(), "0.3183103"); + /// assert_eq!(o, Greater); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(20, Nearest); + /// assert_eq!(reciprocal.to_string(), "0.3183098"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn reciprocal_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Float, Ordering) { + assert_ne!(prec, 0); + match self { + float_nan!() => (float_nan!(), Equal), + Float(Zero { sign }) => (Float(Infinity { sign: *sign }), Equal), + Float(Infinity { sign }) => (Float(Zero { sign: *sign }), Equal), + Float(Finite { + sign, + exponent: exp, + precision: x_prec, + significand: x, + }) => { + if x.is_power_of_2() { + let reciprocal = Float::power_of_2_prec(i64::from(1 - exp), prec); + return (if *sign { reciprocal } else { -reciprocal }, Equal); + } + let sign = *sign; + let (reciprocal, exp_offset, o) = + reciprocal_float_significand_ref(x, *x_prec, prec, if sign { rm } else { -rm }); + let exp = 1i32 + .checked_sub(*exp) + .unwrap() + .checked_add(i32::exact_from(exp_offset)) + .unwrap(); + ( + Float(Finite { + sign, + exponent: exp, + precision: prec, + significand: reciprocal, + }), + if sign { o } else { o.reverse() }, + ) + } + } + } + + /// Takes the reciprocal of a [`Float`], rounding the result to the nearest value of the + /// specified precision. The [`Float`] is taken by value. An [`Ordering`] is also returned, + /// indicating whether the rounded reciprocal is less than, equal to, or greater than the exact + /// reciprocal. Although `NaN`s are not comparable to any [`Float`], whenever this function + /// returns a `NaN` it also returns `Equal`. + /// + /// If the reciprocal is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,p) = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},p)=\text{NaN}$ + /// - $f(\infty,p)=0.0$ + /// - $f(-\infty,p)=-0.0$ + /// - $f(0.0,p)=\infty$ + /// - $f(-0.0,p)=-\infty$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::reciprocal_prec_round`] instead. If you know that your target precision is the + /// precision of the input, consider using [`Float::reciprocal`] instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec(5); + /// assert_eq!(reciprocal.to_string(), "0.31"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec(20); + /// assert_eq!(reciprocal.to_string(), "0.3183098"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn reciprocal_prec(self, prec: u64) -> (Float, Ordering) { + self.reciprocal_prec_round(prec, Nearest) + } + + /// Takes the reciprocal of a [`Float`], rounding the result to the nearest value of the + /// specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also returned, + /// indicating whether the rounded reciprocal is less than, equal to, or greater than the exact + /// reciprocal. Although `NaN`s are not comparable to any [`Float`], whenever this function + /// returns a `NaN` it also returns `Equal`. + /// + /// If the reciprocal is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// f(x,p) = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// Special cases: + /// - $f(\text{NaN},p)=\text{NaN}$ + /// - $f(\infty,p)=0.0$ + /// - $f(-\infty,p)=-0.0$ + /// - $f(0.0,p)=\infty$ + /// - $f(-0.0,p)=-\infty$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::reciprocal_prec_round_ref`] instead. If you know that your target precision is the + /// precision of the input, consider using `(&Float)::reciprocal()` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_ref(5); + /// assert_eq!(reciprocal.to_string(), "0.31"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_ref(20); + /// assert_eq!(reciprocal.to_string(), "0.3183098"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn reciprocal_prec_ref(&self, prec: u64) -> (Float, Ordering) { + self.reciprocal_prec_round_ref(prec, Nearest) + } + + /// Takes the reciprocal of a [`Float`], rounding the result with the specified rounding mode. + /// The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating whether the + /// rounded reciprocal is less than, equal to, or greater than the exact reciprocal. Although + /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also + /// returns `Equal`. + /// + /// The precision of the output is the precision of the input. See [`RoundingMode`] for a + /// description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$, where $p$ is the precision of the input. + /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$, where $p$ is the precision of the input. + /// + /// If the output has a precision, it is the precision of the input. + /// + /// Special cases: + /// - $f(\text{NaN},m)=\text{NaN}$ + /// - $f(\infty,m)=0.0$ + /// - $f(-\infty,m)=-0.0$ + /// - $f(0.0,m)=\infty$ + /// - $f(-0.0,m)=-\infty$ + /// + /// If you want to specify an output precision, consider using [`Float::reciprocal_prec_round`] + /// instead. If you know you'll be using the `Nearest` rounding mode, consider using + /// [`Float::reciprocal`] instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the + /// output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_round(Floor); + /// assert_eq!(reciprocal.to_string(), "0.31830988618379064"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_round(Ceiling); + /// assert_eq!(reciprocal.to_string(), "0.31830988618379069"); + /// assert_eq!(o, Greater); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_round(Nearest); + /// assert_eq!(reciprocal.to_string(), "0.31830988618379069"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn reciprocal_round(self, rm: RoundingMode) -> (Float, Ordering) { + let prec = self.significant_bits(); + self.reciprocal_prec_round(prec, rm) + } + + /// Takes the reciprocal of a [`Float`], rounding the result with the specified rounding mode. + /// The [`Float`] is taken by reference. An [`Ordering`] is also returned, indicating whether + /// the rounded reciprocal is less than, equal to, or greater than the exact reciprocal. + /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` + /// it also returns `Equal`. + /// + /// The precision of the output is the precision of the input. See [`RoundingMode`] for a + /// description of the possible rounding modes. + /// + /// $$ + /// f(x,y,m) = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$, where $p$ is the precision of the input. + /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$, where $p$ is the precision of the input. + /// + /// If the output has a precision, it is the precision of the input. + /// + /// Special cases: + /// - $f(\text{NaN},m)=\text{NaN}$ + /// - $f(\infty,m)=0.0$ + /// - $f(-\infty,m)=-0.0$ + /// - $f(0.0,m)=\infty$ + /// - $f(-0.0,m)=-\infty$ + /// + /// If you want to specify an output precision, consider using + /// [`Float::reciprocal_prec_round_ref`] instead. If you know you'll be using the `Nearest` + /// rounding mode, consider using `(&Float)::reciprocal()` instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the + /// output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_round_ref(Floor); + /// assert_eq!(reciprocal.to_string(), "0.31830988618379064"); + /// assert_eq!(o, Less); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_round_ref(Ceiling); + /// assert_eq!(reciprocal.to_string(), "0.31830988618379069"); + /// assert_eq!(o, Greater); + /// + /// let (reciprocal, o) = Float::from(PI).reciprocal_round_ref(Nearest); + /// assert_eq!(reciprocal.to_string(), "0.31830988618379069"); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn reciprocal_round_ref(&self, rm: RoundingMode) -> (Float, Ordering) { + let prec = self.significant_bits(); + self.reciprocal_prec_round_ref(prec, rm) + } + + /// Takes the reciprocal of a [`Float`] in place, rounding the result to the specified precision + /// and with the specified rounding mode. An [`Ordering`] is returned, indicating whether the + /// rounded reciprocal is less than, equal to, or greater than the exact reciprocal. Although + /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to + /// `NaN` it also returns `Equal`. + /// + /// See [`RoundingMode`] for a description of the possible rounding modes. + /// + /// $$ + /// x \gets 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. + /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::reciprocal_prec_round`] documentation for information on special cases. + /// + /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_prec_assign`] + /// instead. If you know that your target precision is the precision of the input, consider + /// using [`Float::reciprocal_round_assign`] instead. If both of these things are true, consider + /// using [`Float::reciprocal_assign`] instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// prec)`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but `prec` is too small for an exact reciprocation; + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_prec_round_assign(5, Floor), Less); + /// assert_eq!(x.to_string(), "0.31"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_prec_round_assign(5, Ceiling), Greater); + /// assert_eq!(x.to_string(), "0.33"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_prec_round_assign(5, Nearest), Less); + /// assert_eq!(x.to_string(), "0.31"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_prec_round_assign(20, Floor), Less); + /// assert_eq!(x.to_string(), "0.3183098"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_prec_round_assign(20, Ceiling), Greater); + /// assert_eq!(x.to_string(), "0.3183103"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_prec_round_assign(20, Nearest), Less); + /// assert_eq!(x.to_string(), "0.3183098"); + /// ``` + #[inline] + pub fn reciprocal_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering { + assert_ne!(prec, 0); + match &mut *self { + float_nan!() => Equal, + Float(Zero { sign }) => { + *self = Float(Infinity { sign: *sign }); + Equal + } + Float(Infinity { sign }) => { + *self = Float(Zero { sign: *sign }); + Equal + } + Float(Finite { + sign, + exponent: exp, + precision: x_prec, + significand: x, + }) => { + if x.is_power_of_2() { + let sign = *sign; + *self = Float::power_of_2_prec(i64::from(1 - *exp), prec); + if !sign { + self.neg_assign(); + } + return Equal; + } + let sign = *sign; + let (reciprocal, exp_offset, o) = + reciprocal_float_significand_ref(x, *x_prec, prec, if sign { rm } else { -rm }); + *exp = 1i32 + .checked_sub(*exp) + .unwrap() + .checked_add(i32::exact_from(exp_offset)) + .unwrap(); + *x_prec = prec; + *x = reciprocal; + if sign { + o + } else { + o.reverse() + } + } + } + } + + /// Takes the reciprocal of a [`Float`] in place, rounding the result to the nearest value of + /// the specified precision. An [`Ordering`] is returned, indicating whether the rounded + /// reciprocal is less than, equal to, or greater than the exact reciprocal. Although `NaN`s are + /// not comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also + /// returns `Equal`. + /// + /// If the reciprocal is equidistant from two [`Float`]s with the specified precision, the + /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a + /// description of the `Nearest` rounding mode. + /// + /// $$ + /// x \gets 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$. + /// + /// If the output has a precision, it is `prec`. + /// + /// See the [`Float::reciprocal_prec`] documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::reciprocal_prec_round_assign`] instead. If you know that your target precision is + /// the precision of the input, consider using [`Float::reciprocal`] instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), + /// prec)`. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_prec_assign(5), Less); + /// assert_eq!(x.to_string(), "0.31"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_prec_assign(20), Less); + /// assert_eq!(x.to_string(), "0.3183098"); + /// ``` + #[inline] + pub fn reciprocal_prec_assign(&mut self, prec: u64) -> Ordering { + self.reciprocal_prec_round_assign(prec, Nearest) + } + + /// Takes the reciprocal of a [`Float`] in place, rounding the result with the specified + /// rounding mode. An [`Ordering`] is returned, indicating whether the rounded reciprocal is + /// less than, equal to, or greater than the exact reciprocal. Although `NaN`s are not + /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also + /// returns `Equal`. + /// + /// The precision of the output is the precision of the input. See [`RoundingMode`] for a + /// description of the possible rounding modes. + /// + /// $$ + /// x \gets 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. + /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// + /// If the output has a precision, it is the precision of the input. + /// + /// See the [`Float::reciprocal_round`] documentation for information on special cases. + /// + /// If you want to specify an output precision, consider using + /// [`Float::reciprocal_prec_round_assign`] instead. If you know you'll be using the `Nearest` + /// rounding mode, consider using [`Float::reciprocal_assign`] instead. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. + /// + /// # Panics + /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the + /// output. + /// + /// # Examples + /// ``` + /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_round_assign(Floor), Less); + /// assert_eq!(x.to_string(), "0.31830988618379064"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_round_assign(Ceiling), Greater); + /// assert_eq!(x.to_string(), "0.31830988618379069"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.reciprocal_round_assign(Nearest), Greater); + /// assert_eq!(x.to_string(), "0.31830988618379069"); + /// ``` + #[inline] + pub fn reciprocal_round_assign(&mut self, rm: RoundingMode) -> Ordering { + let prec = self.significant_bits(); + self.reciprocal_prec_round_assign(prec, rm) + } +} + +impl Reciprocal for Float { + type Output = Float; + + /// Takes the reciprocal of a [`Float`], taking it by value. + /// + /// If the output has a precision, it is the precision of the input. If the reciprocal is + /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in + /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN})=\text{NaN}$ + /// - $f(\infty)=0.0$ + /// - $f(-\infty)=-0.0$ + /// - $f(0.0)=\infty$ + /// - $f(-0.0)=-\infty$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::reciprocal_prec`] instead. If you want to specify the output precision, consider + /// using [`Float::reciprocal_round`]. If you want both of these things, consider using + /// [`Float::reciprocal_prec_round`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::arithmetic::traits::Reciprocal; + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_float::Float; + /// + /// assert!(Float::NAN.reciprocal().is_nan()); + /// assert_eq!(Float::INFINITY.reciprocal().to_string(), "0.0"); + /// assert_eq!(Float::NEGATIVE_INFINITY.reciprocal().to_string(), "-0.0"); + /// assert_eq!( + /// Float::from(1.5).reciprocal().to_string(), + /// "0.6666666666666666" + /// ); + /// assert_eq!( + /// Float::from(-1.5).reciprocal().to_string(), + /// "-0.6666666666666666" + /// ); + /// ``` + #[inline] + fn reciprocal(self) -> Float { + let prec = self.significant_bits(); + self.reciprocal_prec_round(prec, Nearest).0 + } +} + +impl<'a> Reciprocal for &'a Float { + type Output = Float; + + /// Takes the reciprocal of a [`Float`], taking it by reference. + /// + /// If the output has a precision, it is the precision of the input. If the reciprocal is + /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in + /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// f(x,y) = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// Special cases: + /// - $f(\text{NaN})=\text{NaN}$ + /// - $f(\infty)=0.0$ + /// - $f(-\infty)=-0.0$ + /// - $f(0.0)=\infty$ + /// - $f(-0.0)=-\infty$ + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::reciprocal_prec_ref`] instead. If you want to specify the output precision, + /// consider using [`Float::reciprocal_round_ref`]. If you want both of these things, consider + /// using [`Float::reciprocal_prec_round_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::arithmetic::traits::Reciprocal; + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_float::Float; + /// + /// assert!((&Float::NAN).reciprocal().is_nan()); + /// assert_eq!((&Float::INFINITY).reciprocal().to_string(), "0.0"); + /// assert_eq!((&Float::NEGATIVE_INFINITY).reciprocal().to_string(), "-0.0"); + /// assert_eq!( + /// (&Float::from(1.5)).reciprocal().to_string(), + /// "0.6666666666666666" + /// ); + /// assert_eq!( + /// (&Float::from(-1.5)).reciprocal().to_string(), + /// "-0.6666666666666666" + /// ); + /// ``` + #[inline] + fn reciprocal(self) -> Float { + let prec = self.significant_bits(); + self.reciprocal_prec_round_ref(prec, Nearest).0 + } +} + +impl ReciprocalAssign for Float { + /// Takes the reciprocal of a [`Float`] in place. + /// + /// If the output has a precision, it is the precision of the input. If the reciprocal is + /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in + /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` + /// rounding mode. + /// + /// $$ + /// x\gets = 1/x+\varepsilon. + /// $$ + /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$, + /// where $p$ is the maximum precision of the inputs. + /// + /// See the [`Float::reciprocal`] documentation for information on special cases. + /// + /// If you want to use a rounding mode other than `Nearest`, consider using + /// [`Float::reciprocal_prec_assign`] instead. If you want to specify the output precision, + /// consider using [`Float::reciprocal_round_assign`]. If you want both of these things, + /// consider using [`Float::reciprocal_prec_round_assign`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n \log n \log\log n)$ + /// + /// $M(n) = O(n \log n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::arithmetic::traits::ReciprocalAssign; + /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; + /// use malachite_float::Float; + /// + /// let mut x = Float::NAN; + /// x.reciprocal_assign(); + /// assert!(x.is_nan()); + /// + /// let mut x = Float::INFINITY; + /// x.reciprocal_assign(); + /// assert_eq!(x.to_string(), "0.0"); + /// + /// let mut x = Float::NEGATIVE_INFINITY; + /// x.reciprocal_assign(); + /// assert_eq!(x.to_string(), "-0.0"); + /// + /// let mut x = Float::from(1.5); + /// x.reciprocal_assign(); + /// assert_eq!(x.to_string(), "0.6666666666666666"); + /// + /// let mut x = Float::from(-1.5); + /// x.reciprocal_assign(); + /// assert_eq!(x.to_string(), "-0.6666666666666666"); + /// ``` + #[inline] + fn reciprocal_assign(&mut self) { + let prec = self.significant_bits(); + self.reciprocal_prec_round_assign(prec, Nearest); + } +} diff --git a/malachite-float/src/arithmetic/square.rs b/malachite-float/src/arithmetic/square.rs index 2e3add751..4eee35801 100644 --- a/malachite-float/src/arithmetic/square.rs +++ b/malachite-float/src/arithmetic/square.rs @@ -32,13 +32,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,p,m) = x^2+\epsilon. + /// f(x,p,m) = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$. - /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x^2|\rfloor-p}$. + /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -53,9 +53,9 @@ impl Float { /// [`Float::square`] instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `prec`. @@ -109,13 +109,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,p,m) = x^2+\epsilon. + /// f(x,p,m) = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$. - /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x^2|\rfloor-p}$. + /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -130,9 +130,9 @@ impl Float { /// `(&Float).square()`instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `prec`. @@ -214,10 +214,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,p) = x^2+\epsilon. + /// f(x,p) = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -231,9 +231,9 @@ impl Float { /// precision of the input, consider using [`Float::square`] instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `prec`. @@ -268,10 +268,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,p) = x^2+\epsilon. + /// f(x,p) = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -285,9 +285,9 @@ impl Float { /// precision of the input, consider using `(&Float).square()` instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `prec`. @@ -320,13 +320,13 @@ impl Float { /// description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x^2+\epsilon. + /// f(x,y,m) = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the precision of the input. - /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x^2|\rfloor-p}$, where $p$ is the precision of the input. + /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// @@ -384,13 +384,13 @@ impl Float { /// description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x^2+\epsilon. + /// f(x,y,m) = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the precision of the input. - /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x^2|\rfloor-p}$, where $p$ is the precision of the input. + /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// @@ -448,13 +448,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x^2+\epsilon. + /// x \gets x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. - /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x^2|\rfloor-p}$. + /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -466,9 +466,9 @@ impl Float { /// [`Float::square_assign`] instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `prec`. @@ -479,15 +479,32 @@ impl Float { /// # Examples /// ``` /// use core::f64::consts::PI; + /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); - /// assert_eq!(x.square_prec_assign(5), Greater); + /// assert_eq!(x.square_prec_round_assign(5, Floor), Less); + /// assert_eq!(x.to_string(), "9.5"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.square_prec_round_assign(5, Ceiling), Greater); /// assert_eq!(x.to_string(), "10.0"); /// /// let mut x = Float::from(PI); - /// assert_eq!(x.square_prec_assign(20), Less); + /// assert_eq!(x.square_prec_round_assign(5, Nearest), Greater); + /// assert_eq!(x.to_string(), "10.0"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.square_prec_round_assign(20, Floor), Less); + /// assert_eq!(x.to_string(), "9.8696"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.square_prec_round_assign(20, Ceiling), Greater); + /// assert_eq!(x.to_string(), "9.86961"); + /// + /// let mut x = Float::from(PI); + /// assert_eq!(x.square_prec_round_assign(20, Nearest), Less); /// assert_eq!(x.to_string(), "9.8696"); /// ``` #[inline] @@ -528,10 +545,10 @@ impl Float { /// the `Nearest` rounding mode. /// /// $$ - /// x \gets x^2+\epsilon. + /// x \gets x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -542,9 +559,9 @@ impl Float { /// precision of the input, consider using [`Float::square`] instead. /// /// # Worst-case complexity - /// $T(n) = O(n \log n \log\log n + m)$ + /// $T(n, m) = O(n \log n \log\log n + m)$ /// - /// $M(n) = O(n \log n + m)$ + /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `prec`. @@ -577,13 +594,13 @@ impl Float { /// description of the possible rounding modes. /// /// $$ - /// x \gets x^2+\epsilon. + /// x \gets x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x^2|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the precision of the input. /// @@ -641,10 +658,10 @@ impl Square for Float { /// rounding mode. /// /// $$ - /// f(x,y) = x^2+\epsilon. + /// f(x,y) = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -694,10 +711,10 @@ impl<'a> Square for &'a Float { /// rounding mode. /// /// $$ - /// f(x,y) = x^2+\epsilon. + /// f(x,y) = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -745,10 +762,10 @@ impl SquareAssign for Float { /// rounding mode. /// /// $$ - /// x\gets = x^2+\epsilon. + /// x\gets = x^2+\varepsilon. /// $$ - /// - If $x^2$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x^2$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, + /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the [`Float::square`] documentation for information on special cases. diff --git a/malachite-float/src/arithmetic/sub.rs b/malachite-float/src/arithmetic/sub.rs index 550555f80..bfd54a446 100644 --- a/malachite-float/src/arithmetic/sub.rs +++ b/malachite-float/src/arithmetic/sub.rs @@ -38,13 +38,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x-y+\epsilon. + /// f(x,y,p,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -128,13 +128,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x-y+\epsilon. + /// f(x,y,p,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -218,13 +218,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x-y+\epsilon. + /// f(x,y,p,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -307,13 +307,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x-y+\epsilon. + /// f(x,y,p,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -398,10 +398,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x-y+\epsilon. + /// f(x,y,p) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -459,10 +459,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x-y+\epsilon. + /// f(x,y,p) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -520,10 +520,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x-y+\epsilon. + /// f(x,y,p) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -581,10 +581,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x-y+\epsilon. + /// f(x,y,p) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -641,13 +641,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x-y+\epsilon. + /// f(x,y,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -716,13 +716,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x-y+\epsilon. + /// f(x,y,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -791,13 +791,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x-y+\epsilon. + /// f(x,y,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -866,13 +866,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x-y+\epsilon. + /// f(x,y,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -941,13 +941,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1017,13 +1017,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1111,10 +1111,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1161,10 +1161,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1210,13 +1210,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1273,13 +1273,13 @@ impl Float { /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// @@ -1335,13 +1335,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x-y+\epsilon. + /// f(x,y,p,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1428,13 +1428,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x-y+\epsilon. + /// f(x,y,p,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1539,13 +1539,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x-y+\epsilon. + /// f(x,y,p,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1654,11 +1654,7 @@ impl Float { (-diff, o.reverse()) } } - (_, y) if y == 0 => { - let mut x = self.clone(); - let o = x.set_prec_round(prec, rm); - (x, o) - } + (_, y) if y == 0 => Float::from_float_prec_round_ref(self, prec, rm), (x, y) => { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; @@ -1667,10 +1663,8 @@ impl Float { // Error <= 1/2 ulp(q) let (q, o) = Float::from_rational_prec_ref(&y, working_prec); if o == Equal { - // Result is exact so we can add it directly! - let mut x = self.clone(); - let o = x.sub_prec_round_assign(q, prec, rm); - return (x, o); + // Result is exact so we can subtract it directly! + return self.sub_prec_round_ref_val(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let mut t = x.sub_prec_ref_val(q, working_prec).0; @@ -1714,13 +1708,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// f(x,y,p,m) = x-y+\epsilon. + /// f(x,y,p,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1829,11 +1823,7 @@ impl Float { (-diff, o.reverse()) } } - (_, y) if *y == 0 => { - let mut x = self.clone(); - let o = x.set_prec_round(prec, rm); - (x, o) - } + (_, y) if *y == 0 => Float::from_float_prec_round_ref(self, prec, rm), (x, y) => { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; @@ -1842,10 +1832,8 @@ impl Float { // Error <= 1/2 ulp(q) let (q, o) = Float::from_rational_prec_ref(y, working_prec); if o == Equal { - // Result is exact so we can add it directly! - let mut x = self.clone(); - let o = x.sub_prec_round_assign(q, prec, rm); - return (x, o); + // Result is exact so we can subtract it directly! + return self.sub_prec_round_ref_val(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let mut t = x.sub_prec_ref_val(q, working_prec).0; @@ -1891,10 +1879,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x-y+\epsilon. + /// f(x,y,p) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -1950,10 +1938,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x-y+\epsilon. + /// f(x,y,p) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2009,10 +1997,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x-y+\epsilon. + /// f(x,y,p) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2068,10 +2056,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// f(x,y,p) = x-y+\epsilon. + /// f(x,y,p) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2126,13 +2114,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x-y+\epsilon. + /// f(x,y,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2201,13 +2189,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x-y+\epsilon. + /// f(x,y,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2281,13 +2269,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x-y+\epsilon. + /// f(x,y,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2361,13 +2349,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// f(x,y,m) = x-y+\epsilon. + /// f(x,y,m) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// @@ -2440,13 +2428,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2555,7 +2543,7 @@ impl Float { // Error <= 1/2 ulp(q) let (q, o) = Float::from_rational_prec_ref(&y, working_prec); if o == Equal { - // Result is exact so we can add it directly! + // Result is exact so we can subtract it directly! return self.sub_prec_round_assign(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); @@ -2600,13 +2588,13 @@ impl Float { /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2714,7 +2702,7 @@ impl Float { // Error <= 1/2 ulp(q) let (q, o) = Float::from_rational_prec_ref(y, working_prec); if o == Equal { - // Result is exact so we can add it directly! + // Result is exact so we can subtract it directly! return self.sub_prec_round_assign(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); @@ -2761,10 +2749,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2820,10 +2808,10 @@ impl Float { /// description of the `Nearest` rounding mode. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// @@ -2878,13 +2866,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// @@ -2951,13 +2939,13 @@ impl Float { /// for a description of the possible rounding modes. /// /// $$ - /// x \gets x-y+\epsilon. + /// x \gets x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\epsilon| < + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. - /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\epsilon| < 2^{\lfloor\log_2 - /// |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. + /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < + /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// @@ -3031,10 +3019,10 @@ impl Sub for Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -3096,10 +3084,10 @@ impl<'a> Sub<&'a Float> for Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -3167,10 +3155,10 @@ impl<'a> Sub for &'a Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -3238,10 +3226,10 @@ impl<'a, 'b> Sub<&'a Float> for &'b Float { /// the `Nearest` rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: @@ -3307,10 +3295,10 @@ impl SubAssign for Float { /// the `Nearest` rounding mode. /// /// $$ - /// x\gets = x-y+\epsilon. + /// x\gets = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `-` documentation for information on special cases. @@ -3382,10 +3370,10 @@ impl<'a> SubAssign<&'a Float> for Float { /// the `Nearest` rounding mode. /// /// $$ - /// x\gets = x-y+\epsilon. + /// x\gets = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `-` documentation for information on special cases. @@ -3458,10 +3446,10 @@ impl Sub for Float { /// rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -3525,10 +3513,10 @@ impl<'a> Sub<&'a Rational> for Float { /// rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -3595,10 +3583,10 @@ impl<'a> Sub for &'a Float { /// rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -3664,10 +3652,10 @@ impl<'a, 'b> Sub<&'a Rational> for &'b Float { /// rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -3731,10 +3719,10 @@ impl SubAssign for Float { /// rounding mode. /// /// $$ - /// x\gets = x-y+\epsilon. + /// x\gets = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `-` documentation for information on special cases. @@ -3803,10 +3791,10 @@ impl<'a> SubAssign<&'a Rational> for Float { /// rounding mode. /// /// $$ - /// x\gets = x-y+\epsilon. + /// x\gets = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `-` documentation for information on special cases. @@ -3877,10 +3865,10 @@ impl Sub for Rational { /// rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -3942,10 +3930,10 @@ impl<'a> Sub<&'a Float> for Rational { /// rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -4007,10 +3995,10 @@ impl<'a> Sub for &'a Rational { /// rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: @@ -4071,10 +4059,10 @@ impl<'a, 'b> Sub<&'a Float> for &'b Rational { /// rounding mode. /// /// $$ - /// f(x,y) = x-y+\epsilon. + /// f(x,y) = x-y+\varepsilon. /// $$ - /// - If $x-y$ is infinite, zero, or `NaN`, $\epsilon$ may be ignored or assumed to be 0. - /// - If $x-y$ is finite and nonzero, then $|\epsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, + /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. + /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: diff --git a/malachite-float/src/basic/constants.rs b/malachite-float/src/basic/constants.rs index c12e29115..f6b62b3c1 100644 --- a/malachite-float/src/basic/constants.rs +++ b/malachite-float/src/basic/constants.rs @@ -215,10 +215,10 @@ impl Float { /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `p`. + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics - /// Panics if `p` is zero. + /// Panics if `prec` is zero. /// /// # Examples /// ``` @@ -259,10 +259,10 @@ impl Float { /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `p`. + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics - /// Panics if `p` is zero. + /// Panics if `prec` is zero. /// /// # Examples /// ``` @@ -303,10 +303,10 @@ impl Float { /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `p`. + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics - /// Panics if `p` is zero. + /// Panics if `prec` is zero. /// /// # Examples /// ``` @@ -347,10 +347,10 @@ impl Float { /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `p`. + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics - /// Panics if `p` is zero. + /// Panics if `prec` is zero. /// /// # Examples /// ``` diff --git a/malachite-float/src/basic/get_and_set.rs b/malachite-float/src/basic/get_and_set.rs index 45da5a9a9..07551bcdd 100644 --- a/malachite-float/src/basic/get_and_set.rs +++ b/malachite-float/src/basic/get_and_set.rs @@ -10,13 +10,17 @@ use crate::InnerFloat::Finite; use crate::{significand_bits, Float}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ - RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, + NegAssign, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, }; use malachite_base::num::basic::integers::PrimitiveInt; +use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; +const PREC_ROUND_THRESHOLD: u64 = 1500; + impl Float { /// Gets the significand of a [`Float`], taking the [`Float`] by value. /// @@ -369,4 +373,214 @@ impl Float { pub fn set_prec(&mut self, p: u64) -> Ordering { self.set_prec_round(p, Nearest) } + + /// Creates a [`Float`] from another [`Float`], possibly with a different precision. If the + /// precision decreases, rounding may be necessary, and will use the provided [`RoundingMode`]. + /// The input [`Float`] is taken by value. + /// + /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or + /// equal to the original value. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero or if `rm` is [`Exact`] but setting the desired precision requires + /// rounding. + /// + /// # Examples + /// ``` + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let original_x = Float::from(1.0f64 / 3.0); + /// assert_eq!(original_x.to_string(), "0.33333333333333331"); + /// assert_eq!(original_x.get_prec(), Some(53)); + /// + /// let (x, o) = Float::from_float_prec_round(original_x.clone(), 100, Exact); + /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); + /// assert_eq!(x.get_prec(), Some(100)); + /// assert_eq!(o, Equal); + /// + /// let (x, o) = Float::from_float_prec_round(original_x.clone(), 10, Floor); + /// assert_eq!(x.to_string(), "0.333"); + /// assert_eq!(x.get_prec(), Some(10)); + /// assert_eq!(o, Less); + /// + /// let (x, o) = Float::from_float_prec_round(original_x.clone(), 10, Ceiling); + /// assert_eq!(x.to_string(), "0.3335"); + /// assert_eq!(x.get_prec(), Some(10)); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn from_float_prec_round(mut x: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { + let o = x.set_prec_round(prec, rm); + (x, o) + } + + /// Creates a [`Float`] from another [`Float`], possibly with a different precision. If the + /// precision decreases, rounding may be necessary, and will use the provided [`RoundingMode`]. + /// The input [`Float`] is taken by reference. + /// + /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or + /// equal to the original value. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero or if `rm` is [`Exact`] but setting the desired precision requires + /// rounding. + /// + /// # Examples + /// ``` + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let original_x = Float::from(1.0f64 / 3.0); + /// assert_eq!(original_x.to_string(), "0.33333333333333331"); + /// assert_eq!(original_x.get_prec(), Some(53)); + /// + /// let (x, o) = Float::from_float_prec_round_ref(&original_x, 100, Exact); + /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); + /// assert_eq!(x.get_prec(), Some(100)); + /// assert_eq!(o, Equal); + /// + /// let (x, o) = Float::from_float_prec_round_ref(&original_x, 10, Floor); + /// assert_eq!(x.to_string(), "0.333"); + /// assert_eq!(x.get_prec(), Some(10)); + /// assert_eq!(o, Less); + /// + /// let (x, o) = Float::from_float_prec_round_ref(&original_x, 10, Ceiling); + /// assert_eq!(x.to_string(), "0.3335"); + /// assert_eq!(x.get_prec(), Some(10)); + /// assert_eq!(o, Greater); + /// ``` + pub fn from_float_prec_round_ref(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { + if x.significant_bits() < PREC_ROUND_THRESHOLD { + let mut x = x.clone(); + let o = x.set_prec_round(prec, rm); + return (x, o); + } + match x { + Float(Finite { + sign, + exponent, + significand, + .. + }) => { + let (mut y, mut o) = Float::from_natural_prec_round_ref( + significand, + prec, + if *sign { rm } else { -rm }, + ); + if !sign { + y.neg_assign(); + o = o.reverse(); + } + ( + y >> (i32::exact_from(significand_bits(significand)) - exponent), + o, + ) + } + _ => (x.clone(), Equal), + } + } + + /// Creates a [`Float`] from another [`Float`], possibly with a different precision. If the + /// precision decreases, rounding may be necessary, and will use [`Nearest`]. The input + /// [`Float`] is taken by value. + /// + /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or + /// equal to the original value. + /// + /// To use a different rounding mode, try [`Float::from_float_prec_round`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let original_x = Float::from(1.0f64 / 3.0); + /// assert_eq!(original_x.to_string(), "0.33333333333333331"); + /// assert_eq!(original_x.get_prec(), Some(53)); + /// + /// let (x, o) = Float::from_float_prec(original_x.clone(), 100); + /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); + /// assert_eq!(x.get_prec(), Some(100)); + /// assert_eq!(o, Equal); + /// + /// let (x, o) = Float::from_float_prec(original_x.clone(), 10); + /// assert_eq!(x.to_string(), "0.3335"); + /// assert_eq!(x.get_prec(), Some(10)); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn from_float_prec(mut x: Float, prec: u64) -> (Float, Ordering) { + let o = x.set_prec(prec); + (x, o) + } + + /// Creates a [`Float`] from another [`Float`], possibly with a different precision. If the + /// precision decreases, rounding may be necessary, and will use [`Nearest`]. The input + /// [`Float`] is taken by reference. + /// + /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or + /// equal to the original value. + /// + /// To use a different rounding mode, try [`Float::from_float_prec_round_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let original_x = Float::from(1.0f64 / 3.0); + /// assert_eq!(original_x.to_string(), "0.33333333333333331"); + /// assert_eq!(original_x.get_prec(), Some(53)); + /// + /// let (x, o) = Float::from_float_prec_ref(&original_x, 100); + /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); + /// assert_eq!(x.get_prec(), Some(100)); + /// assert_eq!(o, Equal); + /// + /// let (x, o) = Float::from_float_prec_ref(&original_x, 10); + /// assert_eq!(x.to_string(), "0.3335"); + /// assert_eq!(x.get_prec(), Some(10)); + /// assert_eq!(o, Greater); + /// ``` + #[inline] + pub fn from_float_prec_ref(x: &Float, prec: u64) -> (Float, Ordering) { + Float::from_float_prec_round_ref(x, prec, Nearest) + } } diff --git a/malachite-float/src/bin_util/demo_and_bench/arithmetic/add.rs b/malachite-float/src/bin_util/demo_and_bench/arithmetic/add.rs index 84f439b58..6fdd36cd9 100644 --- a/malachite-float/src/bin_util/demo_and_bench/arithmetic/add.rs +++ b/malachite-float/src/bin_util/demo_and_bench/arithmetic/add.rs @@ -12,14 +12,19 @@ use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::add::{ - add_prec_round_naive, add_rational_prec_round_naive, rug_add, rug_add_rational, - rug_add_rational_round, rug_add_round, + add_prec_round_naive, add_rational_prec_round_naive, rug_add, rug_add_prec, rug_add_prec_round, + rug_add_rational, rug_add_rational_prec, rug_add_rational_prec_round, rug_add_rational_round, + rug_add_round, }; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_2_pair_float_rational_max_complexity_bucketer, + pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, + pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_max_complexity_bucketer, - pair_2_triple_1_2_float_rational_max_complexity_bucketer, pair_float_max_complexity_bucketer, - pair_float_rational_max_complexity_bucketer, + pair_2_triple_1_2_float_rational_max_complexity_bucketer, + pair_2_triple_float_float_primitive_int_max_complexity_bucketer, + pair_2_triple_float_rational_primitive_int_max_complexity_bucketer, + pair_float_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, triple_1_2_float_max_complexity_bucketer, triple_1_2_float_rational_max_complexity_bucketer, @@ -28,12 +33,15 @@ use malachite_float::test_util::bench::bucketers::{ }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_1, float_float_rounding_mode_triple_gen_var_1_rm, - float_float_unsigned_rounding_mode_quadruple_gen_var_1, float_float_unsigned_triple_gen_var_1, + float_float_unsigned_rounding_mode_quadruple_gen_var_1, + float_float_unsigned_rounding_mode_quadruple_gen_var_1_rm, + float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, float_pair_gen, float_pair_gen_rm, float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_rounding_mode_triple_gen_var_1, float_rational_rounding_mode_triple_gen_var_3_rm, float_rational_unsigned_rounding_mode_quadruple_gen_var_1, - float_rational_unsigned_triple_gen_var_1, + float_rational_unsigned_rounding_mode_quadruple_gen_var_1_rm, + float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_1_rm, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use std::cmp::max; @@ -149,6 +157,7 @@ pub(crate) fn register(runner: &mut Runner) { register_bench!(runner, benchmark_float_add_algorithms); register_bench!(runner, benchmark_float_add_assign_evaluation_strategy); register_bench!(runner, benchmark_float_add_prec_evaluation_strategy); + register_bench!(runner, benchmark_float_add_prec_library_comparison); register_bench!(runner, benchmark_float_add_prec_algorithms); register_bench!(runner, benchmark_float_add_prec_assign_evaluation_strategy); register_bench!(runner, benchmark_float_add_round_evaluation_strategy); @@ -156,6 +165,7 @@ pub(crate) fn register(runner: &mut Runner) { register_bench!(runner, benchmark_float_add_round_algorithms); register_bench!(runner, benchmark_float_add_round_assign_evaluation_strategy); register_bench!(runner, benchmark_float_add_prec_round_evaluation_strategy); + register_bench!(runner, benchmark_float_add_prec_round_library_comparison); register_bench!(runner, benchmark_float_add_prec_round_algorithms); register_bench!( runner, @@ -174,6 +184,7 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_add_rational_prec_evaluation_strategy ); + register_bench!(runner, benchmark_float_add_rational_prec_library_comparison); register_bench!(runner, benchmark_float_add_rational_prec_algorithms); register_bench!( runner, @@ -196,6 +207,10 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_add_rational_prec_round_evaluation_strategy ); + register_bench!( + runner, + benchmark_float_add_rational_prec_round_library_comparison + ); register_bench!(runner, benchmark_float_add_rational_prec_round_algorithms); register_bench!( runner, @@ -1762,8 +1777,8 @@ fn benchmark_float_add_library_comparison( file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ - ("Malachite", &mut |(_, (x, y))| no_out!(x + y)), - ("rug", &mut |((x, y), _)| no_out!(rug_add(x, y))), + ("Malachite", &mut |(_, (x, y))| no_out!(&x + &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_add(&x, &y))), ], ); } @@ -1870,6 +1885,31 @@ fn benchmark_float_add_prec_algorithms( ); } +fn benchmark_float_add_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.add_prec(Float, u64)", + BenchmarkType::LibraryComparison, + float_float_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec))| { + no_out!(x.add_prec_ref_ref(&y, prec)) + }), + ("rug", &mut |((x, y, prec), _)| { + no_out!(rug_add_prec(&x, &y, prec)) + }), + ], + ); +} + fn benchmark_float_add_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, @@ -1950,10 +1990,10 @@ fn benchmark_float_add_round_library_comparison( &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { - no_out!(x.add_round(y, rm)) + no_out!(x.add_round_ref_ref(&y, rm)) }), ("rug", &mut |((x, y, rm), _)| { - no_out!(rug_add_round(x, y, rm)) + no_out!(rug_add_round(&x, &y, rm)) }), ], ); @@ -2046,6 +2086,31 @@ fn benchmark_float_add_prec_round_evaluation_strategy( ); } +fn benchmark_float_add_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.add_prec_round(Float, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_float_unsigned_rounding_mode_quadruple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec, rm))| { + no_out!(x.add_prec_round_ref_ref(&y, prec, rm)) + }), + ("rug", &mut |((x, y, prec, rm), _)| { + no_out!(rug_add_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + fn benchmark_float_add_prec_round_algorithms( gm: GenMode, config: &GenConfig, @@ -2138,8 +2203,8 @@ fn benchmark_float_add_rational_library_comparison( file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ - ("Malachite", &mut |(_, (x, y))| no_out!(x + y)), - ("rug", &mut |((x, y), _)| no_out!(rug_add_rational(x, y))), + ("Malachite", &mut |(_, (x, y))| no_out!(&x + &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_add_rational(&x, &y))), ], ); } @@ -2231,8 +2296,8 @@ fn benchmark_rational_add_float_library_comparison( file_name, &pair_2_pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ - ("Malachite", &mut |(_, (y, x))| no_out!(x + y)), - ("rug", &mut |((x, y), _)| no_out!(rug_add_rational(x, y))), + ("Malachite", &mut |(_, (y, x))| no_out!(&x + &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_add_rational(&x, &y))), ], ); } @@ -2272,6 +2337,31 @@ fn benchmark_float_add_rational_prec_evaluation_strategy( ); } +fn benchmark_float_add_rational_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.add_rational_prec(Rational, u64)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec))| { + no_out!(x.add_rational_prec_ref_ref(&y, prec)) + }), + ("rug", &mut |((x, y, prec), _)| { + no_out!(rug_add_rational_prec(&x, &y, prec)) + }), + ], + ); +} + fn benchmark_float_add_rational_prec_algorithms( gm: GenMode, config: &GenConfig, @@ -2375,10 +2465,10 @@ fn benchmark_float_add_rational_round_library_comparison( &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { - no_out!(x.add_rational_round(y, rm)) + no_out!(x.add_rational_round_ref_ref(&y, rm)) }), ("rug", &mut |((x, y, rm), _)| { - no_out!(rug_add_rational_round(x, y, rm)) + no_out!(rug_add_rational_round(&x, &y, rm)) }), ], ); @@ -2472,6 +2562,33 @@ fn benchmark_float_add_rational_prec_round_evaluation_strategy( ); } +fn benchmark_float_add_rational_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.add_rational_prec_round(Rational, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_rounding_mode_quadruple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( + "x", "y", "prec", + ), + &mut [ + ("Malachite", &mut |(_, (x, y, prec, rm))| { + no_out!(x.add_rational_prec_round_ref_ref(&y, prec, rm)) + }), + ("rug", &mut |((x, y, prec, rm), _)| { + no_out!(rug_add_rational_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + fn benchmark_float_add_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, diff --git a/malachite-float/src/bin_util/demo_and_bench/arithmetic/div.rs b/malachite-float/src/bin_util/demo_and_bench/arithmetic/div.rs new file mode 100644 index 000000000..afd2052c0 --- /dev/null +++ b/malachite-float/src/bin_util/demo_and_bench/arithmetic/div.rs @@ -0,0 +1,3663 @@ +// 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 core::cmp::max; +use malachite_base::num::logic::traits::SignificantBits; +use malachite_base::rounding_modes::RoundingMode::*; +use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; +use malachite_base::test_util::generators::common::{GenConfig, GenMode}; +use malachite_base::test_util::runner::Runner; +use malachite_float::arithmetic::div::{ + div_rational_prec_round_direct, div_rational_prec_round_direct_ref_ref, + div_rational_prec_round_direct_ref_val, div_rational_prec_round_direct_val_ref, + div_rational_prec_round_naive, div_rational_prec_round_naive_ref_ref, + div_rational_prec_round_naive_ref_val, div_rational_prec_round_naive_val_ref, + rational_div_float_prec_round_direct, rational_div_float_prec_round_direct_ref_ref, + rational_div_float_prec_round_direct_ref_val, rational_div_float_prec_round_direct_val_ref, + rational_div_float_prec_round_naive, rational_div_float_prec_round_naive_ref_ref, + rational_div_float_prec_round_naive_ref_val, rational_div_float_prec_round_naive_val_ref, +}; +use malachite_float::test_util::arithmetic::div::{ + div_prec_round_naive, rug_div, rug_div_prec, rug_div_prec_round, rug_div_rational, + rug_div_rational_prec, rug_div_rational_prec_round, rug_div_rational_round, rug_div_round, + rug_rational_div_float_prec, rug_rational_div_float_prec_round, rug_rational_div_float_round, +}; +use malachite_float::test_util::bench::bucketers::{ + pair_2_pair_float_max_complexity_bucketer, pair_2_pair_float_rational_max_complexity_bucketer, + pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, + pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, + pair_2_triple_1_2_float_max_complexity_bucketer, + pair_2_triple_1_2_float_rational_max_complexity_bucketer, + pair_2_triple_float_float_primitive_int_max_complexity_bucketer, + pair_2_triple_float_rational_primitive_int_max_complexity_bucketer, + pair_float_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, + quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, + quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, + triple_1_2_float_max_complexity_bucketer, triple_1_2_float_rational_max_complexity_bucketer, + triple_float_float_primitive_int_max_complexity_bucketer, + triple_float_rational_primitive_int_max_complexity_bucketer, +}; +use malachite_float::test_util::generators::{ + float_float_rounding_mode_triple_gen_var_23, float_float_rounding_mode_triple_gen_var_23_rm, + float_float_unsigned_rounding_mode_quadruple_gen_var_4, + float_float_unsigned_rounding_mode_quadruple_gen_var_4_rm, + float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, + float_pair_gen, float_pair_gen_rm, float_rational_pair_gen, float_rational_pair_gen_rm, + float_rational_rounding_mode_triple_gen_var_3_rm, + float_rational_rounding_mode_triple_gen_var_5, float_rational_rounding_mode_triple_gen_var_6, + float_rational_rounding_mode_triple_gen_var_6_rm, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4_rm, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5_rm, + float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_1_rm, +}; +use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; + +pub(crate) fn register(runner: &mut Runner) { + register_demo!(runner, demo_float_div); + register_demo!(runner, demo_float_div_debug); + register_demo!(runner, demo_float_div_val_ref); + register_demo!(runner, demo_float_div_val_ref_debug); + register_demo!(runner, demo_float_div_ref_val); + register_demo!(runner, demo_float_div_ref_val_debug); + register_demo!(runner, demo_float_div_ref_ref); + register_demo!(runner, demo_float_div_ref_ref_debug); + register_demo!(runner, demo_float_div_assign); + register_demo!(runner, demo_float_div_assign_debug); + register_demo!(runner, demo_float_div_assign_ref); + register_demo!(runner, demo_float_div_assign_ref_debug); + register_demo!(runner, demo_float_div_prec); + register_demo!(runner, demo_float_div_prec_debug); + register_demo!(runner, demo_float_div_prec_val_ref); + register_demo!(runner, demo_float_div_prec_val_ref_debug); + register_demo!(runner, demo_float_div_prec_ref_val); + register_demo!(runner, demo_float_div_prec_ref_val_debug); + register_demo!(runner, demo_float_div_prec_ref_ref); + register_demo!(runner, demo_float_div_prec_ref_ref_debug); + register_demo!(runner, demo_float_div_prec_assign); + register_demo!(runner, demo_float_div_prec_assign_debug); + register_demo!(runner, demo_float_div_prec_assign_ref); + register_demo!(runner, demo_float_div_prec_assign_ref_debug); + register_demo!(runner, demo_float_div_round); + register_demo!(runner, demo_float_div_round_debug); + register_demo!(runner, demo_float_div_round_val_ref); + register_demo!(runner, demo_float_div_round_val_ref_debug); + register_demo!(runner, demo_float_div_round_ref_val); + register_demo!(runner, demo_float_div_round_ref_val_debug); + register_demo!(runner, demo_float_div_round_ref_ref); + register_demo!(runner, demo_float_div_round_ref_ref_debug); + register_demo!(runner, demo_float_div_round_assign); + register_demo!(runner, demo_float_div_round_assign_debug); + register_demo!(runner, demo_float_div_round_assign_ref); + register_demo!(runner, demo_float_div_round_assign_ref_debug); + register_demo!(runner, demo_float_div_prec_round); + register_demo!(runner, demo_float_div_prec_round_debug); + register_demo!(runner, demo_float_div_prec_round_val_ref); + register_demo!(runner, demo_float_div_prec_round_val_ref_debug); + register_demo!(runner, demo_float_div_prec_round_ref_val); + register_demo!(runner, demo_float_div_prec_round_ref_val_debug); + register_demo!(runner, demo_float_div_prec_round_ref_ref); + register_demo!(runner, demo_float_div_prec_round_ref_ref_debug); + register_demo!(runner, demo_float_div_prec_round_assign); + register_demo!(runner, demo_float_div_prec_round_assign_debug); + register_demo!(runner, demo_float_div_prec_round_assign_ref); + register_demo!(runner, demo_float_div_prec_round_assign_ref_debug); + register_demo!(runner, demo_float_div_rational); + register_demo!(runner, demo_float_div_rational_debug); + register_demo!(runner, demo_float_div_rational_val_ref); + register_demo!(runner, demo_float_div_rational_val_ref_debug); + register_demo!(runner, demo_float_div_rational_ref_val); + register_demo!(runner, demo_float_div_rational_ref_val_debug); + register_demo!(runner, demo_float_div_rational_ref_ref); + register_demo!(runner, demo_float_div_rational_ref_ref_debug); + register_demo!(runner, demo_float_div_rational_assign); + register_demo!(runner, demo_float_div_rational_assign_debug); + register_demo!(runner, demo_float_div_rational_assign_ref); + register_demo!(runner, demo_float_div_rational_assign_ref_debug); + register_demo!(runner, demo_rational_div_float); + register_demo!(runner, demo_rational_div_float_debug); + register_demo!(runner, demo_rational_div_float_val_ref); + register_demo!(runner, demo_rational_div_float_val_ref_debug); + register_demo!(runner, demo_rational_div_float_ref_val); + register_demo!(runner, demo_rational_div_float_ref_val_debug); + register_demo!(runner, demo_rational_div_float_ref_ref); + register_demo!(runner, demo_rational_div_float_ref_ref_debug); + register_demo!(runner, demo_float_div_rational_prec); + register_demo!(runner, demo_float_div_rational_prec_debug); + register_demo!(runner, demo_float_div_rational_prec_val_ref); + register_demo!(runner, demo_float_div_rational_prec_val_ref_debug); + register_demo!(runner, demo_float_div_rational_prec_ref_val); + register_demo!(runner, demo_float_div_rational_prec_ref_val_debug); + register_demo!(runner, demo_float_div_rational_prec_ref_ref); + register_demo!(runner, demo_float_div_rational_prec_ref_ref_debug); + register_demo!(runner, demo_float_div_rational_prec_assign); + register_demo!(runner, demo_float_div_rational_prec_assign_debug); + register_demo!(runner, demo_float_div_rational_prec_assign_ref); + register_demo!(runner, demo_float_div_rational_prec_assign_ref_debug); + register_demo!(runner, demo_rational_div_float_prec); + register_demo!(runner, demo_rational_div_float_prec_debug); + register_demo!(runner, demo_rational_div_float_prec_val_ref); + register_demo!(runner, demo_rational_div_float_prec_val_ref_debug); + register_demo!(runner, demo_rational_div_float_prec_ref_val); + register_demo!(runner, demo_rational_div_float_prec_ref_val_debug); + register_demo!(runner, demo_rational_div_float_prec_ref_ref); + register_demo!(runner, demo_rational_div_float_prec_ref_ref_debug); + register_demo!(runner, demo_float_div_rational_round); + register_demo!(runner, demo_float_div_rational_round_debug); + register_demo!(runner, demo_float_div_rational_round_val_ref); + register_demo!(runner, demo_float_div_rational_round_val_ref_debug); + register_demo!(runner, demo_float_div_rational_round_ref_val); + register_demo!(runner, demo_float_div_rational_round_ref_val_debug); + register_demo!(runner, demo_float_div_rational_round_ref_ref); + register_demo!(runner, demo_float_div_rational_round_ref_ref_debug); + register_demo!(runner, demo_float_div_rational_round_assign); + register_demo!(runner, demo_float_div_rational_round_assign_debug); + register_demo!(runner, demo_float_div_rational_round_assign_ref); + register_demo!(runner, demo_float_div_rational_round_assign_ref_debug); + register_demo!(runner, demo_rational_div_float_round); + register_demo!(runner, demo_rational_div_float_round_debug); + register_demo!(runner, demo_rational_div_float_round_val_ref); + register_demo!(runner, demo_rational_div_float_round_val_ref_debug); + register_demo!(runner, demo_rational_div_float_round_ref_val); + register_demo!(runner, demo_rational_div_float_round_ref_val_debug); + register_demo!(runner, demo_rational_div_float_round_ref_ref); + register_demo!(runner, demo_rational_div_float_round_ref_ref_debug); + register_demo!(runner, demo_float_div_rational_prec_round); + register_demo!(runner, demo_float_div_rational_prec_round_debug); + register_demo!(runner, demo_float_div_rational_prec_round_val_ref); + register_demo!(runner, demo_float_div_rational_prec_round_val_ref_debug); + register_demo!(runner, demo_float_div_rational_prec_round_ref_val); + register_demo!(runner, demo_float_div_rational_prec_round_ref_val_debug); + register_demo!(runner, demo_float_div_rational_prec_round_ref_ref); + register_demo!(runner, demo_float_div_rational_prec_round_ref_ref_debug); + register_demo!(runner, demo_float_div_rational_prec_round_assign); + register_demo!(runner, demo_float_div_rational_prec_round_assign_debug); + register_demo!(runner, demo_float_div_rational_prec_round_assign_ref); + register_demo!(runner, demo_float_div_rational_prec_round_assign_ref_debug); + register_demo!(runner, demo_rational_div_float_prec_round); + register_demo!(runner, demo_rational_div_float_prec_round_debug); + register_demo!(runner, demo_rational_div_float_prec_round_val_ref); + register_demo!(runner, demo_rational_div_float_prec_round_val_ref_debug); + register_demo!(runner, demo_rational_div_float_prec_round_ref_val); + register_demo!(runner, demo_rational_div_float_prec_round_ref_val_debug); + register_demo!(runner, demo_rational_div_float_prec_round_ref_ref); + register_demo!(runner, demo_rational_div_float_prec_round_ref_ref_debug); + + register_bench!(runner, benchmark_float_div_evaluation_strategy); + register_bench!(runner, benchmark_float_div_library_comparison); + register_bench!(runner, benchmark_float_div_algorithms); + register_bench!(runner, benchmark_float_div_assign_evaluation_strategy); + register_bench!(runner, benchmark_float_div_prec_evaluation_strategy); + register_bench!(runner, benchmark_float_div_prec_library_comparison); + register_bench!(runner, benchmark_float_div_prec_algorithms); + register_bench!(runner, benchmark_float_div_prec_assign_evaluation_strategy); + register_bench!(runner, benchmark_float_div_round_evaluation_strategy); + register_bench!(runner, benchmark_float_div_round_library_comparison); + register_bench!(runner, benchmark_float_div_round_algorithms); + register_bench!(runner, benchmark_float_div_round_assign_evaluation_strategy); + register_bench!(runner, benchmark_float_div_prec_round_evaluation_strategy); + register_bench!(runner, benchmark_float_div_prec_round_library_comparison); + register_bench!(runner, benchmark_float_div_prec_round_algorithms); + register_bench!( + runner, + benchmark_float_div_prec_round_assign_evaluation_strategy + ); + register_bench!(runner, benchmark_float_div_rational_evaluation_strategy); + register_bench!(runner, benchmark_float_div_rational_library_comparison); + register_bench!(runner, benchmark_float_div_rational_algorithms); + register_bench!( + runner, + benchmark_float_div_rational_assign_evaluation_strategy + ); + register_bench!( + runner, + benchmark_float_div_rational_prec_evaluation_strategy + ); + register_bench!(runner, benchmark_float_div_rational_prec_library_comparison); + register_bench!(runner, benchmark_float_div_rational_prec_algorithms); + register_bench!( + runner, + benchmark_float_div_rational_prec_assign_evaluation_strategy + ); + register_bench!( + runner, + benchmark_float_div_rational_round_evaluation_strategy + ); + register_bench!( + runner, + benchmark_float_div_rational_round_library_comparison + ); + register_bench!(runner, benchmark_float_div_rational_round_algorithms); + register_bench!( + runner, + benchmark_float_div_rational_round_assign_evaluation_strategy + ); + register_bench!( + runner, + benchmark_float_div_rational_prec_round_evaluation_strategy + ); + register_bench!( + runner, + benchmark_float_div_rational_prec_round_library_comparison + ); + register_bench!(runner, benchmark_float_div_rational_prec_round_algorithms); + register_bench!( + runner, + benchmark_float_div_rational_prec_round_val_ref_algorithms + ); + register_bench!( + runner, + benchmark_float_div_rational_prec_round_ref_val_algorithms + ); + register_bench!( + runner, + benchmark_float_div_rational_prec_round_ref_ref_algorithms + ); + register_bench!( + runner, + benchmark_float_div_rational_prec_round_assign_evaluation_strategy + ); + + register_bench!(runner, benchmark_rational_div_float_evaluation_strategy); + register_bench!(runner, benchmark_rational_div_float_library_comparison); + register_bench!(runner, benchmark_rational_div_float_algorithms); + register_bench!( + runner, + benchmark_rational_div_float_prec_evaluation_strategy + ); + register_bench!(runner, benchmark_rational_div_float_prec_library_comparison); + register_bench!(runner, benchmark_rational_div_float_prec_algorithms); + register_bench!( + runner, + benchmark_rational_div_float_round_evaluation_strategy + ); + register_bench!( + runner, + benchmark_rational_div_float_round_library_comparison + ); + register_bench!(runner, benchmark_rational_div_float_round_algorithms); + register_bench!( + runner, + benchmark_rational_div_float_prec_round_evaluation_strategy + ); + register_bench!( + runner, + benchmark_rational_div_float_prec_round_library_comparison + ); + register_bench!(runner, benchmark_rational_div_float_prec_round_algorithms); + register_bench!( + runner, + benchmark_rational_div_float_prec_round_val_ref_algorithms + ); + register_bench!( + runner, + benchmark_rational_div_float_prec_round_ref_val_algorithms + ); + register_bench!( + runner, + benchmark_rational_div_float_prec_round_ref_ref_algorithms + ); +} + +fn demo_float_div(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + let y_old = y.clone(); + println!("{} / {} = {}", x_old, y_old, x / y); + } +} + +fn demo_float_div_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "{:#x} / {:#x} = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y_old), + ComparableFloat(x / y) + ); + } +} + +fn demo_float_div_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + println!("{} / &{} = {}", x_old, y, x / &y); + } +} + +fn demo_float_div_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + println!( + "{:#x} / &{:#x} = {:#x}", + ComparableFloat(x_old), + ComparableFloatRef(&y), + ComparableFloat(x / &y) + ); + } +} + +fn demo_float_div_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_pair_gen().get(gm, config).take(limit) { + let y_old = y.clone(); + println!("&{} / {} = {}", x, y_old, &x / y); + } +} + +fn demo_float_div_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_pair_gen().get(gm, config).take(limit) { + let y_old = y.clone(); + println!( + "&{:#x} / {:#x} = {:#x}", + ComparableFloatRef(&x), + ComparableFloat(y_old), + ComparableFloat(&x / y) + ); + } +} + +fn demo_float_div_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_pair_gen().get(gm, config).take(limit) { + println!("&{} / &{} = {}", x, y, &x / &y); + } +} + +fn demo_float_div_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_pair_gen().get(gm, config).take(limit) { + println!( + "&{:#x} / &{:#x} = {:#x}", + ComparableFloatRef(&x), + ComparableFloatRef(&y), + ComparableFloat(&x / &y) + ); + } +} + +fn demo_float_div_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x /= y.clone(); + println!("x := {x_old}; x /= {y}; x = {x}"); + } +} + +fn demo_float_div_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x /= y.clone(); + println!( + "x := {:#x}; x /= {:#x}; x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y), + ComparableFloat(x) + ); + } +} + +fn demo_float_div_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x /= &y; + println!("x := {x_old}; x /= &{y}; x = {x}"); + } +} + +fn demo_float_div_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x /= &y; + println!( + "x := {:#x}; x /= &{:#x}; x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y), + ComparableFloat(x) + ); + } +} + +fn demo_float_div_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "({}).div_prec({}, {}) = {:?}", + x_old, + y_old, + prec, + x.div_prec(y, prec) + ); + } +} + +fn demo_float_div_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = x.div_prec(y, prec); + println!( + "({:#x}).div_prec({:#x}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + ComparableFloat(y_old), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "({}).div_prec_val_ref(&{}, {}) = {:?}", + x_old, + y, + prec, + x.div_prec_val_ref(&y, prec) + ); + } +} + +fn demo_float_div_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = x.div_prec_val_ref(&y, prec); + println!( + "({:#x}).div_prec_val_ref(&{:#x}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + ComparableFloat(y), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "(&{}).div_prec_ref_val({}, {}) = {:?}", + x, + y_old, + prec, + x.div_prec_ref_val(y, prec) + ); + } +} + +fn demo_float_div_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = x.div_prec_ref_val(y, prec); + println!( + "(&{:#x}).div_prec_ref_val({:#x}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + ComparableFloat(y_old), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + println!( + "(&{}).div_prec_ref_ref(&{}, {}) = {:?}", + x, + y, + prec, + x.div_prec_ref_ref(&y, prec) + ); + } +} + +fn demo_float_div_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let (sum, o) = x.div_prec_ref_ref(&y, prec); + println!( + "(&{:#x}).div_prec_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + ComparableFloat(y), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + x.div_prec_assign(y, prec); + println!("x := {x_old}; x.div_prec_assign({y_old}, {prec}); x = {x}"); + } +} + +fn demo_float_div_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_prec_assign(y, prec); + println!( + "x := {:#x}; x.div_prec_assign({:#x}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y_old), + prec, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + x.div_prec_assign_ref(&y, prec); + println!("x := {x_old}; x.div_prec_assign({y}, {prec}); x = {x}"); + } +} + +fn demo_float_div_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_prec_assign_ref(&y, prec); + println!( + "x := {:#x}; x.div_prec_assign({:#x}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y), + prec, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "({}).div_round({}, {}) = {:?}", + x_old, + y_old, + rm, + x.div_round(y, rm) + ); + } +} + +fn demo_float_div_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = x.div_round(y, rm); + println!( + "({:#x}).div_round({:#x}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + ComparableFloat(y_old), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "({}).div_round_val_ref(&{}, {}) = {:?}", + x_old, + y, + rm, + x.div_round_val_ref(&y, rm) + ); + } +} + +fn demo_float_div_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = x.div_round_val_ref(&y, rm); + println!( + "({:#x}).div_round_val_ref(&{:#x}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + ComparableFloat(y), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "(&{}).div_round_ref_val({}, {}) = {:?}", + x, + y_old, + rm, + x.div_round_ref_val(y, rm) + ); + } +} + +fn demo_float_div_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = x.div_round_ref_val(y, rm); + println!( + "(&{:#x}).div_round_ref_val({:#x}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + ComparableFloat(y_old), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + println!( + "(&{}).div_round_ref_ref(&{}, {}) = {:?}", + x, + y, + rm, + x.div_round_ref_ref(&y, rm) + ); + } +} + +fn demo_float_div_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let (sum, o) = x.div_round_ref_ref(&y, rm); + println!( + "(&{:#x}).div_round_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + ComparableFloat(y), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + x.div_round_assign(y, rm); + println!("x := {x_old}; x.div_round_assign({y_old}, {rm}); x = {x}"); + } +} + +fn demo_float_div_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_round_assign(y, rm); + println!( + "x := {:#x}; x.div_round_assign({:#x}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y_old), + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + x.div_round_assign_ref(&y, rm); + println!("x := {x_old}; x.div_round_assign({y}, {rm}); x = {x}"); + } +} + +fn demo_float_div_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_23() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_round_assign_ref(&y, rm); + println!( + "x := {:#x}; x.div_round_assign({:#x}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y), + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "({}).div_prec_round({}, {}, {}) = {:?}", + x_old, + y_old, + prec, + rm, + x.div_prec_round(y, prec, rm) + ); + } +} + +fn demo_float_div_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = x.div_prec_round(y, prec, rm); + println!( + "({:#x}).div_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + ComparableFloat(y_old), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "({}).div_prec_round(&{}, {}, {}) = {:?}", + x_old, + y, + prec, + rm, + x.div_prec_round_val_ref(&y, prec, rm) + ); + } +} + +fn demo_float_div_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = x.div_prec_round_val_ref(&y, prec, rm); + println!( + "({:#x}).div_prec_round_val_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + ComparableFloat(y), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "(&{}).div_prec_round_ref_val({}, {}, {}) = {:?}", + x, + y_old, + prec, + rm, + x.div_prec_round_ref_val(y, prec, rm) + ); + } +} + +fn demo_float_div_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = x.div_prec_round_ref_val(y, prec, rm); + println!( + "(&{:#x}).div_prec_round_ref_val({:#x}, {}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + ComparableFloat(y_old), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + println!( + "({}).div_prec_round({}, {}, {}) = {:?}", + x, + y, + prec, + rm, + x.div_prec_round_ref_ref(&y, prec, rm) + ); + } +} + +fn demo_float_div_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let (sum, o) = x.div_prec_round_ref_ref(&y, prec, rm); + println!( + "({:#x}).div_prec_round_ref_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + ComparableFloat(y), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_prec_round_assign(y, prec, rm); + println!("x := {x_old}; x.div_prec_round({y_old}, {prec}, {rm}) = {o:?}; x = {x}"); + } +} + +fn demo_float_div_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_prec_round_assign(y, prec, rm); + println!( + "x := {:#x}; x.div_prec_round({:#x}, {}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y_old), + prec, + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_prec_round_assign_ref(&y, prec, rm); + println!("x := {x_old}; x.div_prec_round_ref(&{y}, {prec}, {rm}) = {o:?}; x = {x}"); + } +} + +fn demo_float_div_prec_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_prec_round_assign_ref(&y, prec, rm); + println!( + "x := {:#x}; x.div_prec_round_ref(&{:#x}, {}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(y), + prec, + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_rational(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + let y_old = y.clone(); + println!("{} / {} = {}", x_old, y_old, x / y); + } +} + +fn demo_float_div_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "{:#x} / {} = {:#x}", + ComparableFloat(x_old), + y_old, + ComparableFloat(x / y) + ); + } +} + +fn demo_float_div_rational_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + println!("{} / &{} = {}", x_old, y, x / &y); + } +} + +fn demo_float_div_rational_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + println!( + "{:#x} / {} = {:#x}", + ComparableFloat(x_old), + y, + ComparableFloat(x / &y) + ); + } +} + +fn demo_float_div_rational_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let y_old = y.clone(); + println!("&{} / {} = {}", x, y_old, &x / y); + } +} + +fn demo_float_div_rational_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let y_old = y.clone(); + println!( + "&{:#x} / {} = {:#x}", + ComparableFloatRef(&x), + y_old, + ComparableFloat(&x / y) + ); + } +} + +fn demo_float_div_rational_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + println!("&{} / &{} = {}", x, y, &x / &y); + } +} + +fn demo_float_div_rational_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + println!( + "&{:#x} / &{} = {:#x}", + ComparableFloatRef(&x), + y, + ComparableFloat(&x / &y) + ); + } +} + +fn demo_float_div_rational_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x /= y.clone(); + println!("x := {x_old}; x /= {y}; x = {x}"); + } +} + +fn demo_float_div_rational_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x /= y.clone(); + println!( + "x := {:#x}; x /= {}; x = {:#x}", + ComparableFloat(x_old), + y, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_rational_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x /= &y; + println!("x := {x_old}; x /= &{y}; x = {x}"); + } +} + +fn demo_float_div_rational_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x /= &y; + println!( + "x := {:#x}; x /= &{}; x = {:#x}", + ComparableFloat(x_old), + y, + ComparableFloat(x) + ); + } +} + +fn demo_rational_div_float(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + let y_old = y.clone(); + println!("{} / {} = {}", x_old, y_old, x / y); + } +} + +fn demo_rational_div_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "{} / {:#x} = {:#x}", + x_old, + ComparableFloat(y_old), + ComparableFloat(x / y) + ); + } +} + +fn demo_rational_div_float_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + println!("{} / &{} = {}", x_old, y, x / &y); + } +} + +fn demo_rational_div_float_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + println!( + "{} / &{:#x} = {:#x}", + x_old, + ComparableFloatRef(&y), + ComparableFloat(x / &y) + ); + } +} + +fn demo_rational_div_float_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { + let y_old = y.clone(); + println!("&{} / {} = {}", x, y_old, &x / y); + } +} + +fn demo_rational_div_float_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { + let y_old = y.clone(); + println!( + "&{} / {:#x} = {:#x}", + x, + ComparableFloat(y_old), + ComparableFloat(&x / y) + ); + } +} + +fn demo_rational_div_float_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { + println!("&{} / &{} = {}", x, y, &x / &y); + } +} + +fn demo_rational_div_float_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { + println!( + "&{} / &{:#x} = {:#x}", + x, + ComparableFloatRef(&y), + ComparableFloat(&x / &y) + ); + } +} + +fn demo_float_div_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "({}).div_rational_prec({}, {}) = {:?}", + x_old, + y_old, + prec, + x.div_rational_prec(y, prec) + ); + } +} + +fn demo_float_div_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = x.div_rational_prec(y, prec); + println!( + "({:#x}).div_rational_prec({}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + y_old, + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "({}).div_rational_prec({}, &{}) = {:?}", + x_old, + y, + prec, + x.div_rational_prec_val_ref(&y, prec) + ); + } +} + +fn demo_float_div_rational_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = x.div_rational_prec_val_ref(&y, prec); + println!( + "({:#x}).div_rational_prec_val_ref(&{}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + y, + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "(&{}).div_rational_prec_ref_val({}, {}) = {:?}", + x, + y_old, + prec, + x.div_rational_prec_ref_val(y, prec) + ); + } +} + +fn demo_float_div_rational_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = x.div_rational_prec_ref_val(y, prec); + println!( + "(&{:#x}).div_rational_prec_ref_val({}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + y_old, + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + println!( + "(&{}).div_rational_prec_ref_ref(&{}, {}) = {:?}", + x, + y, + prec, + x.div_rational_prec_ref_ref(&y, prec) + ); + } +} + +fn demo_float_div_rational_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let (sum, o) = x.div_rational_prec_ref_ref(&y, prec); + println!( + "(&{:#x}).div_rational_prec_ref_ref(&{}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + y, + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_rational_prec_assign(y, prec); + println!("x := {x_old}; x.div_rational_prec_assign({y_old}, {prec}) = {o:?}; x = {x}"); + } +} + +fn demo_float_div_rational_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_rational_prec_assign(y, prec); + println!( + "x := {:#x}; x.div_rational_prec_assign({}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + y_old, + prec, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_rational_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_rational_prec_assign_ref(&y, prec); + println!("x := {x_old}; x.div_rational_prec_assign_ref({y}, &{prec}) = {o:?}; x = {x}"); + } +} + +fn demo_float_div_rational_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_rational_prec_assign_ref(&y, prec); + println!( + "x := {:#x}; x.div_rational_prec_assign(&{}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + y, + prec, + o, + ComparableFloat(x) + ); + } +} + +fn demo_rational_div_float_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "rational_div_float_prec({}, {}, {}) = {:?}", + x_old, + y_old, + prec, + Float::rational_div_float_prec(x, y, prec) + ); + } +} + +fn demo_rational_div_float_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = Float::rational_div_float_prec(x, y, prec); + println!( + "rational_div_float_prec({}, {:#x}, {}) = ({:#x}, {:?})", + x_old, + ComparableFloat(y_old), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "rational_div_float_prec({}, &{}, {}) = {:?}", + x_old, + y, + prec, + Float::rational_div_float_prec_val_ref(x, &y, prec) + ); + } +} + +fn demo_rational_div_float_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = Float::rational_div_float_prec_val_ref(x, &y, prec); + println!( + "rational_div_float_prec_val_ref({}, &{:#x}, {}) = ({:#x}, {:?})", + x_old, + ComparableFloat(y), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "rational_div_float_prec_ref_val(&{}, {}, {}) = {:?}", + x, + y_old, + prec, + Float::rational_div_float_prec_ref_val(&x, y, prec) + ); + } +} + +fn demo_rational_div_float_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = Float::rational_div_float_prec_ref_val(&x, y, prec); + println!( + "rational_div_float_prec_ref_val(&{}, {:#x}, {}) = ({:#x}, {:?})", + x, + ComparableFloat(y_old), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + println!( + "rational_div_float_prec_ref_ref(&{}, &{}, {}) = {:?}", + x, + y, + prec, + Float::rational_div_float_prec_ref_ref(&x, &y, prec) + ); + } +} + +fn demo_rational_div_float_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let (sum, o) = Float::rational_div_float_prec_ref_ref(&x, &y, prec); + println!( + "rational_div_float_prec_ref_ref(&{}, &{:#x}, {}) = ({:#x}, {:?})", + x, + ComparableFloat(y), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "({}).div_rational_round({}, {}) = {:?}", + x_old, + y_old, + rm, + x.div_rational_round(y, rm) + ); + } +} + +fn demo_float_div_rational_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = x.div_rational_round(y, rm); + println!( + "({:#x}).div_rational_round({}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + y_old, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "({}).div_rational_round_val_ref(&{}, {}) = {:?}", + x_old, + y, + rm, + x.div_rational_round_val_ref(&y, rm) + ); + } +} + +fn demo_float_div_rational_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = x.div_rational_round_val_ref(&y, rm); + println!( + "({:#x}).div_rational_round_val_ref(&{}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + y, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "(&{}).div_rational_round_ref_val(&{}, {}) = {:?}", + x, + y_old, + rm, + x.div_rational_round_ref_val(y, rm) + ); + } +} + +fn demo_float_div_rational_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = x.div_rational_round_ref_val(y, rm); + println!( + "(&{:#x}).div_rational_round_ref_val({}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + y_old, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + println!( + "(&{}).div_rational_round_ref_ref(&{}, {}) = {:?}", + x, + y, + rm, + x.div_rational_round_ref_ref(&y, rm) + ); + } +} + +fn demo_float_div_rational_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let (sum, o) = x.div_rational_round_ref_ref(&y, rm); + println!( + "(&{:#x}).div_rational_round_ref_ref(&{}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + y, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_rational_round_assign(y, rm); + println!("x := {x_old}; x.div_rational_round_assign({y_old}, {rm}) = {o:?}; x = {x}"); + } +} + +fn demo_float_div_rational_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_rational_round_assign(y, rm); + println!( + "x := {:#x}; x.div_rational_round_assign({}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + y_old, + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_rational_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_rational_round_assign_ref(&y, rm); + println!("x := {x_old}; x.div_rational_round_assign_ref(&{y}, {rm}) = {o:?}; x = {x}"); + } +} + +fn demo_float_div_rational_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_rational_round_assign_ref(&y, rm); + println!( + "x := {:#x}; x.div_rational_round_assign_ref(&{}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + y_old, + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_rational_div_float_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "rational_div_float_round({}, {}, {}) = {:?}", + x_old, + y_old, + rm, + Float::rational_div_float_round(x, y, rm) + ); + } +} + +fn demo_rational_div_float_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = Float::rational_div_float_round(x, y, rm); + println!( + "rational_div_float_round({}, {:#x}, {}) = ({:#x}, {:?})", + x_old, + ComparableFloat(y_old), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "rational_div_float_round_val_ref({}, &{}, {}) = {:?}", + x_old, + y, + rm, + Float::rational_div_float_round_val_ref(x, &y, rm) + ); + } +} + +fn demo_rational_div_float_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = Float::rational_div_float_round_val_ref(x, &y, rm); + println!( + "rational_div_float_round_val_ref({}, &{:#x}, {}) = ({:#x}, {:?})", + x_old, + ComparableFloat(y), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "rational_div_float_round_ref_val(&{}, &{}, {}) = {:?}", + x, + y_old, + rm, + Float::rational_div_float_round_ref_val(&x, y, rm) + ); + } +} + +fn demo_rational_div_float_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = Float::rational_div_float_round_ref_val(&x, y, rm); + println!( + "rational_div_float_round_ref_val(&{}, {:#x}, {}) = ({:#x}, {:?})", + x, + ComparableFloat(y_old), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() + .get(gm, config) + .take(limit) + { + println!( + "rational_div_float_round_ref_ref(&{}, &{}, {}) = {:?}", + x, + y, + rm, + Float::rational_div_float_round_ref_ref(&x, &y, rm) + ); + } +} + +fn demo_rational_div_float_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() + .get(gm, config) + .take(limit) + { + let (sum, o) = Float::rational_div_float_round_ref_ref(&x, &y, rm); + println!( + "rational_div_float_round_ref_ref(&{}, &{:#x}, {}) = ({:#x}, {:?})", + x, + ComparableFloat(y), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "({}).div_rational_prec_round({}, {}, {}) = {:?}", + x_old, + y_old, + prec, + rm, + x.div_rational_prec_round(y, prec, rm) + ); + } +} + +fn demo_float_div_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = x.div_rational_prec_round(y, prec, rm); + println!( + "({:#x}).div_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + y_old, + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "({}).div_rational_prec_round_val_ref(&{}, {}, {}) = {:?}", + x_old, + y, + prec, + rm, + x.div_rational_prec_round_val_ref(&y, prec, rm) + ); + } +} + +fn demo_float_div_rational_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = x.div_rational_prec_round_val_ref(&y, prec, rm); + println!( + "({:#x}).div_rational_prec_round_val_ref(&{}, {}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + y, + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "(&{}).div_rational_prec_round_ref_val({}, {}, {}) = {:?}", + x, + y_old, + prec, + rm, + x.div_rational_prec_round_ref_val(y, prec, rm) + ); + } +} + +fn demo_float_div_rational_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = x.div_rational_prec_round_ref_val(y, prec, rm); + println!( + "(&{:#x}).div_rational_prec_round_ref_val({}, {}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + y_old, + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + println!( + "(&{}).div_rational_prec_round_ref_ref(&{}, {}, {}) = {:?}", + x, + y, + prec, + rm, + x.div_rational_prec_round_ref_ref(&y, prec, rm) + ); + } +} + +fn demo_float_div_rational_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let (sum, o) = x.div_rational_prec_round_ref_ref(&y, prec, rm); + println!( + "(&{:#x}).div_rational_prec_round_ref_ref(&{}, {}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + y, + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_div_rational_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_rational_prec_round_assign(y, prec, rm); + println!( + "x := {x_old}; x.div_rational_prec_round_assign({y_old}, {prec}, {rm}) = {o:?}; \ + x = {x}", + ); + } +} + +fn demo_float_div_rational_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let o = x.div_rational_prec_round_assign(y, prec, rm); + println!( + "x := {:#x}; x.div_rational_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + y_old, + prec, + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_div_rational_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_rational_prec_round_assign_ref(&y, prec, rm); + println!( + "x := {x_old}; x.div_rational_prec_round_assign_ref(&{y}, {prec}, {rm}) = {o:?}; \ + x = {x}", + ); + } +} + +fn demo_float_div_rational_prec_round_assign_ref_debug( + gm: GenMode, + config: &GenConfig, + limit: usize, +) { + for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.div_rational_prec_round_assign_ref(&y, prec, rm); + println!( + "x := {:#x}; x.div_rational_prec_round_assign_ref(&{}, {}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + y, + prec, + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_rational_div_float_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + println!( + "rational_div_float_prec_round({}, {}, {}, {}) = {:?}", + x_old, + y_old, + prec, + rm, + Float::rational_div_float_prec_round(x, y, prec, rm) + ); + } +} + +fn demo_rational_div_float_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let y_old = y.clone(); + let (sum, o) = Float::rational_div_float_prec_round(x, y, prec, rm); + println!( + "rational_div_float_rational_prec_round({}, {:#x}, {}, {}) = ({:#x}, {:?})", + x_old, + ComparableFloat(y_old), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "Float::rational_div_float_prec_round_val_ref(&{}, {}, {}, {}) = {:?}", + x_old, + y, + prec, + rm, + Float::rational_div_float_prec_round_val_ref(x, &y, prec, rm) + ); + } +} + +fn demo_rational_div_float_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = Float::rational_div_float_prec_round_val_ref(x, &y, prec, rm); + println!( + "rational_div_float_prec_round_val_ref({}, &{:#x}, {}, {}) = ({:#x}, {:?})", + x_old, + ComparableFloat(y), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + println!( + "rational_div_float_prec_round_ref_val(&{}, {}, {}, {}) = {:?}", + x, + y_old, + prec, + rm, + Float::rational_div_float_prec_round_ref_val(&x, y, prec, rm) + ); + } +} + +fn demo_rational_div_float_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() + .get(gm, config) + .take(limit) + { + let y_old = y.clone(); + let (sum, o) = Float::rational_div_float_prec_round_ref_val(&x, y, prec, rm); + println!( + "rational_div_float_prec_round_ref_val(&{}, {:#x}, {}, {}) = ({:#x}, {:?})", + x, + ComparableFloat(y_old), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_rational_div_float_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() + .get(gm, config) + .take(limit) + { + println!( + "rational_div_float_prec_round_ref_ref(&{}, &{}, {}, {}) = {:?}", + x, + y, + prec, + rm, + Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm) + ); + } +} + +fn demo_rational_div_float_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() + .get(gm, config) + .take(limit) + { + let (sum, o) = Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm); + println!( + "rational_div_float_prec_round_ref_ref(&{}, &{:#x}, {}, {}) = ({:#x}, {:?})", + x, + ComparableFloat(y), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +#[allow(clippy::no_effect, unused_must_use)] +fn benchmark_float_div_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float / Float", + BenchmarkType::EvaluationStrategy, + float_pair_gen().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_max_complexity_bucketer("x", "y"), + &mut [ + ("Float / Float", &mut |(x, y)| no_out!(x / y)), + ("Float / &Float", &mut |(x, y)| no_out!(x / &y)), + ("&Float / Float", &mut |(x, y)| no_out!(&x / y)), + ("&Float / &Float", &mut |(x, y)| no_out!(&x / &y)), + ], + ); +} + +#[allow(unused_must_use, clippy::no_effect)] +fn benchmark_float_div_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float / Float", + BenchmarkType::LibraryComparison, + float_pair_gen_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_pair_float_max_complexity_bucketer("x", "y"), + &mut [ + ("Malachite", &mut |(_, (x, y))| no_out!(&x / &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_div(&x, &y))), + ], + ); +} + +#[allow(unused_must_use, clippy::no_effect)] +fn benchmark_float_div_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { + run_benchmark( + "Float / Float", + BenchmarkType::Algorithms, + float_pair_gen().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_max_complexity_bucketer("x", "y"), + &mut [ + ("default", &mut |(x, y)| no_out!(x / y)), + ("naive", &mut |(x, y)| { + let xsb = x.significant_bits(); + let ysb = y.significant_bits(); + no_out!(div_prec_round_naive(x, y, max(xsb, ysb), Nearest).0) + }), + ], + ); +} + +fn benchmark_float_div_assign_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float /= Float", + BenchmarkType::EvaluationStrategy, + float_pair_gen().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_max_complexity_bucketer("x", "y"), + &mut [ + ("Float /= Float", &mut |(mut x, y)| x /= y), + ("Float /= &Float", &mut |(mut x, y)| x /= &y), + ], + ); +} + +fn benchmark_float_div_prec_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_prec(Float, u64)", + BenchmarkType::EvaluationStrategy, + float_float_unsigned_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Float.div_prec(Float, u64)", &mut |(x, y, prec)| { + no_out!(x.div_prec(y, prec)) + }), + ("Float.div_prec_val_ref(&Float, u64)", &mut |( + x, + y, + prec, + )| { + no_out!(x.div_prec_val_ref(&y, prec)) + }), + ( + "(&Float).div_prec_ref_val(Float, u64)", + &mut |(x, y, prec)| no_out!(x.div_prec_ref_val(y, prec)), + ), + ( + "(&Float).div_prec_ref_ref(&Float, u64)", + &mut |(x, y, prec)| no_out!(x.div_prec_ref_ref(&y, prec)), + ), + ], + ); +} + +fn benchmark_float_div_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_prec(Float, u64)", + BenchmarkType::LibraryComparison, + float_float_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec))| { + no_out!(x.div_prec_ref_ref(&y, prec)) + }), + ("rug", &mut |((x, y, prec), _)| { + no_out!(rug_div_prec(&x, &y, prec)) + }), + ], + ); +} + +fn benchmark_float_div_prec_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_prec(Float, u64)", + BenchmarkType::Algorithms, + float_float_unsigned_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec)| no_out!(x.div_prec(y, prec))), + ("naive", &mut |(x, y, prec)| { + no_out!(div_prec_round_naive(x, y, prec, Nearest)) + }), + ], + ); +} + +fn benchmark_float_div_prec_assign_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_prec_assign(Float, u64)", + BenchmarkType::EvaluationStrategy, + float_float_unsigned_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Float.div_prec_assign(Float, u64)", &mut |( + mut x, + y, + prec, + )| { + no_out!(x.div_prec_assign(y, prec)) + }), + ( + "Float.div_prec_assign_ref(&Float, u64)", + &mut |(mut x, y, prec)| no_out!(x.div_prec_assign_ref(&y, prec)), + ), + ], + ); +} + +fn benchmark_float_div_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_round(Float, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_float_rounding_mode_triple_gen_var_23().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_max_complexity_bucketer("x", "y"), + &mut [ + ("Float.div_round(Float, RoundingMode)", &mut |(x, y, rm)| { + no_out!(x.div_round(y, rm)) + }), + ( + "Float.div_round_val_ref(&Float, RoundingMode)", + &mut |(x, y, rm)| no_out!(x.div_round_val_ref(&y, rm)), + ), + ( + "(&Float).div_round_ref_val(Float, RoundingMode)", + &mut |(x, y, rm)| no_out!(x.div_round_ref_val(y, rm)), + ), + ( + "(&Float).div_round_ref_ref(&Float, RoundingMode)", + &mut |(x, y, rm)| no_out!(x.div_round_ref_ref(&y, rm)), + ), + ], + ); +} + +fn benchmark_float_div_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_round(Float, RoundingMode)", + BenchmarkType::LibraryComparison, + float_float_rounding_mode_triple_gen_var_23_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), + &mut [ + ("Malachite", &mut |(_, (x, y, rm))| { + no_out!(x.div_round_ref_ref(&y, rm)) + }), + ("rug", &mut |((x, y, rm), _)| { + no_out!(rug_div_round(&x, &y, rm)) + }), + ], + ); +} + +fn benchmark_float_div_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_round(Float, RoundingMode)", + BenchmarkType::Algorithms, + float_float_rounding_mode_triple_gen_var_23().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_max_complexity_bucketer("x", "y"), + &mut [ + ("default", &mut |(x, y, rm)| no_out!(x.div_round(y, rm))), + ("naive", &mut |(x, y, rm)| { + let xsb = x.significant_bits(); + let ysb = y.significant_bits(); + div_prec_round_naive(x, y, max(xsb, ysb), rm); + }), + ], + ); +} + +fn benchmark_float_div_round_assign_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_round_assign(Float, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_float_rounding_mode_triple_gen_var_23().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_max_complexity_bucketer("x", "y"), + &mut [ + ( + "Float.div_round_assign(Float, RoundingMode)", + &mut |(mut x, y, rm)| no_out!(x.div_round_assign(y, rm)), + ), + ( + "Float.div_round_assign_ref(&Float, RoundingMode)", + &mut |(mut x, y, rm)| no_out!(x.div_round_assign_ref(&y, rm)), + ), + ], + ); +} + +fn benchmark_float_div_prec_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_prec_round(Float, u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_float_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ( + "Float.div_prec_round(Float, u64, RoundingMode)", + &mut |(x, y, prec, rm)| no_out!(x.div_prec_round(y, prec, rm)), + ), + ( + "Float.div_prec_round_val_ref(&Float, u64, RoundingMode)", + &mut |(x, y, prec, rm)| no_out!(x.div_prec_round_val_ref(&y, prec, rm)), + ), + ( + "(&Float).div_prec_round_ref_val(Float, u64, RoundingMode)", + &mut |(x, y, prec, rm)| no_out!(x.div_prec_round_ref_val(y, prec, rm)), + ), + ( + "(&Float).div_prec_round_ref_ref(&Float, u64, RoundingMode)", + &mut |(x, y, prec, rm)| no_out!(x.div_prec_round_ref_ref(&y, prec, rm)), + ), + ], + ); +} + +fn benchmark_float_div_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_prec_round(Float, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_float_unsigned_rounding_mode_quadruple_gen_var_4_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec, rm))| { + no_out!(x.div_prec_round_ref_ref(&y, prec, rm)) + }), + ("rug", &mut |((x, y, prec, rm), _)| { + no_out!(rug_div_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_div_prec_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_prec_round(Float, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_float_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec, rm)| { + no_out!(x.div_prec_round(y, prec, rm)) + }), + ("naive", &mut |(x, y, prec, rm)| { + no_out!(div_prec_round_naive(x, y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_div_prec_round_assign_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_prec_round_assign(Float, u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_float_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ( + "Float.div_prec_round_assign(Float, u64, RoundingMode)", + &mut |(mut x, y, prec, rm)| no_out!(x.div_prec_round_assign(y, prec, rm)), + ), + ( + "Float.div_prec_round_assign_ref(&Float, u64, RoundingMode)", + &mut |(mut x, y, prec, rm)| no_out!(x.div_prec_round_assign_ref(&y, prec, rm)), + ), + ], + ); +} + +#[allow(unused_must_use, clippy::no_effect)] +fn benchmark_float_div_rational_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float / Rational", + BenchmarkType::EvaluationStrategy, + float_rational_pair_gen().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("Float / Rational", &mut |(x, y)| no_out!(x / y)), + ("Float / &Rational", &mut |(x, y)| no_out!(x / &y)), + ("&Float / Rational", &mut |(x, y)| no_out!(&x / y)), + ("&Float / &Rational", &mut |(x, y)| no_out!(&x / &y)), + ], + ); +} + +#[allow(unused_must_use, clippy::no_effect)] +fn benchmark_float_div_rational_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float / Rational", + BenchmarkType::LibraryComparison, + float_rational_pair_gen_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("Malachite", &mut |(_, (x, y))| no_out!(&x / &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_div_rational(&x, &y))), + ], + ); +} + +#[allow(unused_must_use, clippy::no_effect)] +fn benchmark_float_div_rational_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float / Rational", + BenchmarkType::Algorithms, + float_rational_pair_gen().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("default", &mut |(x, y)| no_out!(x / y)), + ("naive", &mut |(x, y)| { + let xsb = x.significant_bits(); + let ysb = y.significant_bits(); + no_out!(div_rational_prec_round_naive(x, y, max(xsb, ysb), Nearest).0) + }), + ("direct", &mut |(x, y)| { + let xsb = x.significant_bits(); + let ysb = y.significant_bits(); + no_out!(div_rational_prec_round_direct(x, y, max(xsb, ysb), Nearest).0) + }), + ], + ); +} + +fn benchmark_float_div_rational_assign_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float /= Rational", + BenchmarkType::EvaluationStrategy, + float_rational_pair_gen().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("Float /= Rational", &mut |(mut x, y)| x /= y), + ("Float /= &Rational", &mut |(mut x, y)| x /= &y), + ], + ); +} + +fn benchmark_float_div_rational_prec_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec(Rational, u64)", + BenchmarkType::EvaluationStrategy, + float_rational_unsigned_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ( + "Float.div_rational_prec(Rational, u64)", + &mut |(x, y, prec)| no_out!(x.div_rational_prec(y, prec)), + ), + ( + "Float.div_rational_prec_val_ref(&Rational, u64)", + &mut |(x, y, prec)| no_out!(x.div_rational_prec_val_ref(&y, prec)), + ), + ( + "(&Float).div_rational_prec_ref_val(Rational, u64)", + &mut |(x, y, prec)| no_out!(x.div_rational_prec_ref_val(y, prec)), + ), + ( + "(&Float).div_rational_prec_ref_ref(&Rational, u64)", + &mut |(x, y, prec)| no_out!(x.div_rational_prec_ref_ref(&y, prec)), + ), + ], + ); +} + +fn benchmark_float_div_rational_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec(Rational, u64)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec))| { + no_out!(x.div_rational_prec_ref_ref(&y, prec)) + }), + ("rug", &mut |((x, y, prec), _)| { + no_out!(rug_div_rational_prec(&x, &y, prec)) + }), + ], + ); +} + +fn benchmark_float_div_rational_prec_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec(Rational, u64)", + BenchmarkType::Algorithms, + float_rational_unsigned_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec)| { + no_out!(x.div_rational_prec(y, prec)) + }), + ("naive", &mut |(x, y, prec)| { + no_out!(div_rational_prec_round_naive(x, y, prec, Nearest)) + }), + ("direct", &mut |(x, y, prec)| { + no_out!(div_rational_prec_round_direct(x, y, prec, Nearest)) + }), + ], + ); +} + +fn benchmark_float_div_rational_prec_assign_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec_assign(Rational, u64)", + BenchmarkType::EvaluationStrategy, + float_rational_unsigned_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ( + "Float.div_rational_prec_assign(Rational, u64)", + &mut |(mut x, y, prec)| no_out!(x.div_rational_prec_assign(y, prec)), + ), + ( + "Float.div_rational_prec_assign_ref(&Rational, u64)", + &mut |(mut x, y, prec)| no_out!(x.div_rational_prec_assign_ref(&y, prec)), + ), + ], + ); +} + +fn benchmark_float_div_rational_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_round(Rational, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_rational_rounding_mode_triple_gen_var_5().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ( + "Float.div_rational_round(Float, RoundingMode)", + &mut |(x, y, rm)| no_out!(x.div_rational_round(y, rm)), + ), + ( + "Float.div_rational_round_val_ref(&Float, RoundingMode)", + &mut |(x, y, rm)| no_out!(x.div_rational_round_val_ref(&y, rm)), + ), + ( + "(&Float).div_rational_round_ref_val(Float, RoundingMode)", + &mut |(x, y, rm)| no_out!(x.div_rational_round_ref_val(y, rm)), + ), + ( + "(&Float).div_rational_round_ref_ref(&Float, RoundingMode)", + &mut |(x, y, rm)| no_out!(x.div_rational_round_ref_ref(&y, rm)), + ), + ], + ); +} + +fn benchmark_float_div_rational_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_round(Rational, RoundingMode)", + BenchmarkType::LibraryComparison, + float_rational_rounding_mode_triple_gen_var_3_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("Malachite", &mut |(_, (x, y, rm))| { + no_out!(x.div_rational_round_ref_ref(&y, rm)) + }), + ("rug", &mut |((x, y, rm), _)| { + no_out!(rug_div_rational_round(&x, &y, rm)) + }), + ], + ); +} + +fn benchmark_float_div_rational_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_round(Rational, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_rounding_mode_triple_gen_var_5().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("default", &mut |(x, y, rm)| { + no_out!(x.div_rational_round(y, rm)) + }), + ("naive", &mut |(x, y, rm)| { + let ysb = y.significant_bits(); + div_rational_prec_round_naive(x, y, ysb, rm); + }), + ("direct", &mut |(x, y, rm)| { + let ysb = y.significant_bits(); + div_rational_prec_round_direct(x, y, ysb, rm); + }), + ], + ); +} + +fn benchmark_float_div_rational_round_assign_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_round_assign(Rational, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_rational_rounding_mode_triple_gen_var_5().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ( + "Float.div_rational_round_assign(Rational, RoundingMode)", + &mut |(mut x, y, rm)| no_out!(x.div_rational_round_assign(y, rm)), + ), + ( + "Float.div_rational_round_assign_ref(&Rational, RoundingMode)", + &mut |(mut x, y, rm)| no_out!(x.div_rational_round_assign_ref(&y, rm)), + ), + ], + ); +} + +fn benchmark_float_div_rational_prec_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec_round(Rational, u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ( + "Float.div_rational_prec_round(Rational, u64, RoundingMode)", + &mut |(x, y, prec, rm)| no_out!(x.div_rational_prec_round(y, prec, rm)), + ), + ( + "Float.div_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", + &mut |(x, y, prec, rm)| no_out!(x.div_rational_prec_round_val_ref(&y, prec, rm)), + ), + ( + "(&Float).div_rational_prec_round_ref_val(Rational, u64, RoundingMode)", + &mut |(x, y, prec, rm)| no_out!(x.div_rational_prec_round_ref_val(y, prec, rm)), + ), + ( + "(&Float).div_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", + &mut |(x, y, prec, rm)| no_out!(x.div_rational_prec_round_ref_ref(&y, prec, rm)), + ), + ], + ); +} + +fn benchmark_float_div_rational_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec_round(Rational, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( + "x", "y", "prec", + ), + &mut [ + ("Malachite", &mut |(_, (x, y, prec, rm))| { + no_out!(x.div_rational_prec_round_ref_ref(&y, prec, rm)) + }), + ("rug", &mut |((x, y, prec, rm), _)| { + no_out!(rug_div_rational_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_div_rational_prec_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec_round(Rational, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec, rm)| { + no_out!(x.div_rational_prec_round(y, prec, rm)) + }), + ("naive", &mut |(x, y, prec, rm)| { + no_out!(div_rational_prec_round_naive(x, y, prec, rm)) + }), + ("direct", &mut |(x, y, prec, rm)| { + no_out!(div_rational_prec_round_direct(x, y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_div_rational_prec_round_val_ref_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec, rm)| { + no_out!(x.div_rational_prec_round_val_ref(&y, prec, rm)) + }), + ("naive", &mut |(x, y, prec, rm)| { + no_out!(div_rational_prec_round_naive_val_ref(x, &y, prec, rm)) + }), + ("direct", &mut |(x, y, prec, rm)| { + no_out!(div_rational_prec_round_direct_val_ref(x, &y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_div_rational_prec_round_ref_val_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec_round_ref_val(Rational, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec, rm)| { + no_out!(x.div_rational_prec_round_ref_val(y, prec, rm)) + }), + ("naive", &mut |(x, y, prec, rm)| { + no_out!(div_rational_prec_round_naive_ref_val(&x, y, prec, rm)) + }), + ("direct", &mut |(x, y, prec, rm)| { + no_out!(div_rational_prec_round_direct_ref_val(&x, y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_div_rational_prec_round_ref_ref_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec, rm)| { + no_out!(x.div_rational_prec_round_ref_ref(&y, prec, rm)) + }), + ("naive", &mut |(x, y, prec, rm)| { + no_out!(div_rational_prec_round_naive_ref_ref(&x, &y, prec, rm)) + }), + ("direct", &mut |(x, y, prec, rm)| { + no_out!(div_rational_prec_round_direct_ref_ref(&x, &y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_div_rational_prec_round_assign_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.div_rational_prec_round_assign(Rational, u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ( + "Float.div_rational_prec_round_assign(Rational, u64, RoundingMode)", + &mut |(mut x, y, prec, rm)| no_out!(x.div_rational_prec_round_assign(y, prec, rm)), + ), + ( + "Float.div_rational_prec_round_assign_ref(&Rational, u64, RoundingMode)", + &mut |(mut x, y, prec, rm)| { + no_out!(x.div_rational_prec_round_assign_ref(&y, prec, rm)) + }, + ), + ], + ); +} + +#[allow(unused_must_use, clippy::no_effect)] +fn benchmark_rational_div_float_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Rational / Float", + BenchmarkType::EvaluationStrategy, + float_rational_pair_gen().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_rational_max_complexity_bucketer("y", "x"), + &mut [ + ("Rational / Float", &mut |(y, x)| no_out!(x / y)), + ("Rational / &Float", &mut |(y, x)| no_out!(x / &y)), + ("&Rational / Float", &mut |(y, x)| no_out!(&x / y)), + ("&Rational / &Float", &mut |(y, x)| no_out!(&x / &y)), + ], + ); +} + +#[allow(unused_must_use, clippy::no_effect)] +fn benchmark_rational_div_float_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Rational / Float", + BenchmarkType::LibraryComparison, + float_rational_pair_gen_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_pair_float_rational_max_complexity_bucketer("y", "x"), + &mut [ + ("Malachite", &mut |(_, (y, x))| no_out!(&x / &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_div_rational(&x, &y))), + ], + ); +} + +#[allow(unused_must_use, clippy::no_effect)] +fn benchmark_rational_div_float_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Rational / Float", + BenchmarkType::Algorithms, + float_rational_pair_gen().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("default", &mut |(y, x)| no_out!(x / y)), + ("naive", &mut |(y, x)| { + let xsb = x.significant_bits(); + let ysb = y.significant_bits(); + no_out!(rational_div_float_prec_round_naive(x, y, max(xsb, ysb), Nearest).0) + }), + ("direct", &mut |(y, x)| { + let xsb = x.significant_bits(); + let ysb = y.significant_bits(); + no_out!(rational_div_float_prec_round_direct(x, y, max(xsb, ysb), Nearest).0) + }), + ], + ); +} + +fn benchmark_rational_div_float_prec_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_prec(Rational, Float, u64)", + BenchmarkType::EvaluationStrategy, + float_rational_unsigned_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ( + "Float::rational_div_float_prec(Rational, Float, u64)", + &mut |(y, x, prec)| no_out!(Float::rational_div_float_prec(x, y, prec)), + ), + ( + "Float::rational_div_float_prec_val_ref(Rational, &Float, u64)", + &mut |(y, x, prec)| no_out!(Float::rational_div_float_prec_val_ref(x, &y, prec)), + ), + ( + "Float::rational_div_float_prec_ref_val(&Rational, Float, u64)", + &mut |(y, x, prec)| no_out!(Float::rational_div_float_prec_ref_val(&x, y, prec)), + ), + ( + "Float::rational_div_float_prec_ref_ref(&Rational, &Float, u64)", + &mut |(y, x, prec)| no_out!(Float::rational_div_float_prec_ref_ref(&x, &y, prec)), + ), + ], + ); +} + +fn benchmark_rational_div_float_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.rational_div_float_prec(Rational, Float, u64)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (y, x, prec))| { + no_out!(Float::rational_div_float_prec_ref_ref(&x, &y, prec)) + }), + ("rug", &mut |((y, x, prec), _)| { + no_out!(rug_rational_div_float_prec(&x, &y, prec)) + }), + ], + ); +} + +fn benchmark_rational_div_float_prec_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_prec(Rational, Float, u64)", + BenchmarkType::Algorithms, + float_rational_unsigned_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(y, x, prec)| { + no_out!(Float::rational_div_float_prec(x, y, prec)) + }), + ("naive", &mut |(y, x, prec)| { + no_out!(rational_div_float_prec_round_naive(x, y, prec, Nearest)) + }), + ("direct", &mut |(y, x, prec)| { + no_out!(rational_div_float_prec_round_direct(x, y, prec, Nearest)) + }), + ], + ); +} + +fn benchmark_rational_div_float_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_round(Rational, Float, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_rational_rounding_mode_triple_gen_var_6().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ( + "Float::rational_div_float_round(Rational, Float, RoundingMode)", + &mut |(y, x, rm)| no_out!(Float::rational_div_float_round(x, y, rm)), + ), + ( + "Float::rational_div_float_round_val_ref(Rational, &Float, RoundingMode)", + &mut |(y, x, rm)| no_out!(Float::rational_div_float_round_val_ref(x, &y, rm)), + ), + ( + "Float::rational_div_float_round_ref_val(&Rational, Float, RoundingMode)", + &mut |(y, x, rm)| no_out!(Float::rational_div_float_round_ref_val(&x, y, rm)), + ), + ( + "Float::rational_div_float_round_ref_ref(&Rational, &Float, RoundingMode)", + &mut |(y, x, rm)| no_out!(Float::rational_div_float_round_ref_ref(&x, &y, rm)), + ), + ], + ); +} + +fn benchmark_rational_div_float_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.rational_div_float_round(Rational, Float, RoundingMode)", + BenchmarkType::LibraryComparison, + float_rational_rounding_mode_triple_gen_var_6_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("Malachite", &mut |(_, (y, x, rm))| { + no_out!(Float::rational_div_float_round_ref_ref(&x, &y, rm)) + }), + ("rug", &mut |((y, x, rm), _)| { + no_out!(rug_rational_div_float_round(&x, &y, rm)) + }), + ], + ); +} + +fn benchmark_rational_div_float_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_round(Float, Float, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_rounding_mode_triple_gen_var_6().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), + &mut [ + ("default", &mut |(y, x, rm)| { + no_out!(Float::rational_div_float_round(x, y, rm)) + }), + ("naive", &mut |(y, x, rm)| { + let ysb = y.significant_bits(); + rational_div_float_prec_round_naive(x, y, ysb, rm); + }), + ("direct", &mut |(y, x, rm)| { + let ysb = y.significant_bits(); + rational_div_float_prec_round_direct(x, y, ysb, rm); + }), + ], + ); +} + +fn benchmark_rational_div_float_prec_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_prec_round(Rational, Float, u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ( + "Float::rational_div_float_prec_round\ + (Rational, Float, u64, RoundingMode)", + &mut |(y, x, prec, rm)| { + no_out!(Float::rational_div_float_prec_round(x, y, prec, rm)) + }, + ), + ( + "Float::rational_div_float_prec_round_val_ref\ + (Rational, &Float, u64, RoundingMode)", + &mut |(y, x, prec, rm)| { + no_out!(Float::rational_div_float_prec_round_val_ref( + x, &y, prec, rm + )) + }, + ), + ( + "Float::rational_div_float_prec_round_ref_val\ + (&Rational, Float, u64, RoundingMode)", + &mut |(y, x, prec, rm)| { + no_out!(Float::rational_div_float_prec_round_ref_val( + &x, y, prec, rm + )) + }, + ), + ( + "Float::rational_div_float_prec_round_ref_ref\ + (&Rational, &Float, u64, RoundingMode)", + &mut |(y, x, prec, rm)| { + no_out!(Float::rational_div_float_prec_round_ref_ref( + &x, &y, prec, rm + )) + }, + ), + ], + ); +} + +fn benchmark_rational_div_float_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.rational_div_float_prec_round(Rational, Float, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( + "x", "y", "prec", + ), + &mut [ + ("Malachite", &mut |(_, (y, x, prec, rm))| { + no_out!(Float::rational_div_float_prec_round_ref_ref( + &x, &y, prec, rm + )) + }), + ("rug", &mut |((y, x, prec, rm), _)| { + no_out!(rug_rational_div_float_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + +fn benchmark_rational_div_float_prec_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_prec_round(Rational, Float, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(y, x, prec, rm)| { + no_out!(Float::rational_div_float_prec_round(x, y, prec, rm)) + }), + ("naive", &mut |(y, x, prec, rm)| { + no_out!(rational_div_float_prec_round_naive(x, y, prec, rm)) + }), + ("direct", &mut |(y, x, prec, rm)| { + no_out!(rational_div_float_prec_round_direct(x, y, prec, rm)) + }), + ], + ); +} + +fn benchmark_rational_div_float_prec_round_val_ref_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_prec_round_val_ref(Rational, &Float, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(y, x, prec, rm)| { + no_out!(Float::rational_div_float_prec_round_val_ref( + x, &y, prec, rm + )) + }), + ("naive", &mut |(y, x, prec, rm)| { + no_out!(rational_div_float_prec_round_naive_val_ref(x, &y, prec, rm)) + }), + ("direct", &mut |(y, x, prec, rm)| { + no_out!(rational_div_float_prec_round_direct_val_ref( + x, &y, prec, rm + )) + }), + ], + ); +} + +fn benchmark_rational_div_float_prec_round_ref_val_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_prec_round_ref_val(&Rational, Float, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(y, x, prec, rm)| { + no_out!(Float::rational_div_float_prec_round_ref_val( + &x, y, prec, rm + )) + }), + ("naive", &mut |(y, x, prec, rm)| { + no_out!(rational_div_float_prec_round_naive_ref_val(&x, y, prec, rm)) + }), + ("direct", &mut |(y, x, prec, rm)| { + no_out!(rational_div_float_prec_round_direct_ref_val( + &x, y, prec, rm + )) + }), + ], + ); +} + +fn benchmark_rational_div_float_prec_round_ref_ref_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::rational_div_float_prec_round_ref_ref(&Rational, &Float, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(y, x, prec, rm)| { + no_out!(Float::rational_div_float_prec_round_ref_ref( + &x, &y, prec, rm + )) + }), + ("naive", &mut |(y, x, prec, rm)| { + no_out!(rational_div_float_prec_round_naive_ref_ref( + &x, &y, prec, rm + )) + }), + ("direct", &mut |(y, x, prec, rm)| { + no_out!(rational_div_float_prec_round_direct_ref_ref( + &x, &y, prec, rm + )) + }), + ], + ); +} diff --git a/malachite-float/src/bin_util/demo_and_bench/arithmetic/mod.rs b/malachite-float/src/bin_util/demo_and_bench/arithmetic/mod.rs index 83021cdb9..becb1006a 100644 --- a/malachite-float/src/bin_util/demo_and_bench/arithmetic/mod.rs +++ b/malachite-float/src/bin_util/demo_and_bench/arithmetic/mod.rs @@ -11,10 +11,12 @@ use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { abs::register(runner); add::register(runner); + div::register(runner); is_power_of_2::register(runner); mul::register(runner); neg::register(runner); power_of_2::register(runner); + reciprocal::register(runner); shl::register(runner); shr::register(runner); sign::register(runner); @@ -24,10 +26,12 @@ pub(crate) fn register(runner: &mut Runner) { mod abs; mod add; +mod div; mod is_power_of_2; mod mul; mod neg; mod power_of_2; +mod reciprocal; mod shl; mod shr; mod sign; diff --git a/malachite-float/src/bin_util/demo_and_bench/arithmetic/mul.rs b/malachite-float/src/bin_util/demo_and_bench/arithmetic/mul.rs index ebc3e5726..d973e45ec 100644 --- a/malachite-float/src/bin_util/demo_and_bench/arithmetic/mul.rs +++ b/malachite-float/src/bin_util/demo_and_bench/arithmetic/mul.rs @@ -11,15 +11,25 @@ use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; -use malachite_float::arithmetic::mul::mul_rational_prec_round_naive; +use malachite_float::arithmetic::mul::{ + mul_rational_prec_round_direct, mul_rational_prec_round_direct_ref_ref, + mul_rational_prec_round_direct_ref_val, mul_rational_prec_round_direct_val_ref, + mul_rational_prec_round_naive, mul_rational_prec_round_naive_ref_ref, + mul_rational_prec_round_naive_ref_val, mul_rational_prec_round_naive_val_ref, +}; use malachite_float::test_util::arithmetic::mul::{ - mul_prec_round_naive, rug_mul, rug_mul_rational, rug_mul_rational_round, rug_mul_round, + mul_prec_round_naive, rug_mul, rug_mul_prec, rug_mul_prec_round, rug_mul_rational, + rug_mul_rational_prec, rug_mul_rational_prec_round, rug_mul_rational_round, rug_mul_round, }; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_2_pair_float_rational_max_complexity_bucketer, + pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, + pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_max_complexity_bucketer, - pair_2_triple_1_2_float_rational_max_complexity_bucketer, pair_float_max_complexity_bucketer, - pair_float_rational_max_complexity_bucketer, + pair_2_triple_1_2_float_rational_max_complexity_bucketer, + pair_2_triple_float_float_primitive_int_max_complexity_bucketer, + pair_2_triple_float_rational_primitive_int_max_complexity_bucketer, + pair_float_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, triple_1_2_float_max_complexity_bucketer, triple_1_2_float_rational_max_complexity_bucketer, @@ -28,12 +38,15 @@ use malachite_float::test_util::bench::bucketers::{ }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_16, float_float_rounding_mode_triple_gen_var_16_rm, - float_float_unsigned_rounding_mode_quadruple_gen_var_3, float_float_unsigned_triple_gen_var_1, + float_float_unsigned_rounding_mode_quadruple_gen_var_3, + float_float_unsigned_rounding_mode_quadruple_gen_var_3_rm, + float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, float_pair_gen, float_pair_gen_rm, float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_rounding_mode_triple_gen_var_3_rm, float_rational_rounding_mode_triple_gen_var_4, float_rational_unsigned_rounding_mode_quadruple_gen_var_3, - float_rational_unsigned_triple_gen_var_1, + float_rational_unsigned_rounding_mode_quadruple_gen_var_3_rm, + float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_1_rm, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use std::cmp::max; @@ -149,6 +162,7 @@ pub(crate) fn register(runner: &mut Runner) { register_bench!(runner, benchmark_float_mul_algorithms); register_bench!(runner, benchmark_float_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_float_mul_prec_evaluation_strategy); + register_bench!(runner, benchmark_float_mul_prec_library_comparison); register_bench!(runner, benchmark_float_mul_prec_algorithms); register_bench!(runner, benchmark_float_mul_prec_assign_evaluation_strategy); register_bench!(runner, benchmark_float_mul_round_evaluation_strategy); @@ -156,6 +170,7 @@ pub(crate) fn register(runner: &mut Runner) { register_bench!(runner, benchmark_float_mul_round_algorithms); register_bench!(runner, benchmark_float_mul_round_assign_evaluation_strategy); register_bench!(runner, benchmark_float_mul_prec_round_evaluation_strategy); + register_bench!(runner, benchmark_float_mul_prec_round_library_comparison); register_bench!(runner, benchmark_float_mul_prec_round_algorithms); register_bench!( runner, @@ -174,6 +189,7 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_mul_rational_prec_evaluation_strategy ); + register_bench!(runner, benchmark_float_mul_rational_prec_library_comparison); register_bench!(runner, benchmark_float_mul_rational_prec_algorithms); register_bench!( runner, @@ -196,7 +212,23 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_mul_rational_prec_round_evaluation_strategy ); + register_bench!( + runner, + benchmark_float_mul_rational_prec_round_library_comparison + ); register_bench!(runner, benchmark_float_mul_rational_prec_round_algorithms); + register_bench!( + runner, + benchmark_float_mul_rational_prec_round_val_ref_algorithms + ); + register_bench!( + runner, + benchmark_float_mul_rational_prec_round_ref_val_algorithms + ); + register_bench!( + runner, + benchmark_float_mul_rational_prec_round_ref_ref_algorithms + ); register_bench!( runner, benchmark_float_mul_rational_prec_round_assign_evaluation_strategy @@ -1762,8 +1794,8 @@ fn benchmark_float_mul_library_comparison( file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ - ("Malachite", &mut |(_, (x, y))| no_out!(x * y)), - ("rug", &mut |((x, y), _)| no_out!(rug_mul(x, y))), + ("Malachite", &mut |(_, (x, y))| no_out!(&x * &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_mul(&x, &y))), ], ); } @@ -1847,6 +1879,31 @@ fn benchmark_float_mul_prec_evaluation_strategy( ); } +fn benchmark_float_mul_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.mul_prec(Float, u64)", + BenchmarkType::LibraryComparison, + float_float_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec))| { + no_out!(x.mul_prec_ref_ref(&y, prec)) + }), + ("rug", &mut |((x, y, prec), _)| { + no_out!(rug_mul_prec(&x, &y, prec)) + }), + ], + ); +} + fn benchmark_float_mul_prec_algorithms( gm: GenMode, config: &GenConfig, @@ -1950,10 +2007,10 @@ fn benchmark_float_mul_round_library_comparison( &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { - no_out!(x.mul_round(y, rm)) + no_out!(x.mul_round_ref_ref(&y, rm)) }), ("rug", &mut |((x, y, rm), _)| { - no_out!(rug_mul_round(x, y, rm)) + no_out!(rug_mul_round(&x, &y, rm)) }), ], ); @@ -2046,6 +2103,31 @@ fn benchmark_float_mul_prec_round_evaluation_strategy( ); } +fn benchmark_float_mul_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.mul_prec_round(Float, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_float_unsigned_rounding_mode_quadruple_gen_var_3_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec, rm))| { + no_out!(x.mul_prec_round_ref_ref(&y, prec, rm)) + }), + ("rug", &mut |((x, y, prec, rm), _)| { + no_out!(rug_mul_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + fn benchmark_float_mul_prec_round_algorithms( gm: GenMode, config: &GenConfig, @@ -2138,8 +2220,8 @@ fn benchmark_float_mul_rational_library_comparison( file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ - ("Malachite", &mut |(_, (x, y))| no_out!(x * y)), - ("rug", &mut |((x, y), _)| no_out!(rug_mul_rational(x, y))), + ("Malachite", &mut |(_, (x, y))| no_out!(&x * &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_mul_rational(&x, &y))), ], ); } @@ -2166,6 +2248,11 @@ fn benchmark_float_mul_rational_algorithms( let ysb = y.significant_bits(); no_out!(mul_rational_prec_round_naive(x, y, max(xsb, ysb), Nearest).0) }), + ("direct", &mut |(x, y)| { + let xsb = x.significant_bits(); + let ysb = y.significant_bits(); + no_out!(mul_rational_prec_round_direct(x, y, max(xsb, ysb), Nearest).0) + }), ], ); } @@ -2231,8 +2318,8 @@ fn benchmark_rational_mul_float_library_comparison( file_name, &pair_2_pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ - ("Malachite", &mut |(_, (y, x))| no_out!(x * y)), - ("rug", &mut |((x, y), _)| no_out!(rug_mul_rational(x, y))), + ("Malachite", &mut |(_, (y, x))| no_out!(&x * &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_mul_rational(&x, &y))), ], ); } @@ -2272,6 +2359,31 @@ fn benchmark_float_mul_rational_prec_evaluation_strategy( ); } +fn benchmark_float_mul_rational_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.mul_rational_prec(Rational, u64)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec))| { + no_out!(x.mul_rational_prec_ref_ref(&y, prec)) + }), + ("rug", &mut |((x, y, prec), _)| { + no_out!(rug_mul_rational_prec(&x, &y, prec)) + }), + ], + ); +} + fn benchmark_float_mul_rational_prec_algorithms( gm: GenMode, config: &GenConfig, @@ -2293,6 +2405,9 @@ fn benchmark_float_mul_rational_prec_algorithms( ("naive", &mut |(x, y, prec)| { no_out!(mul_rational_prec_round_naive(x, y, prec, Nearest)) }), + ("direct", &mut |(x, y, prec)| { + no_out!(mul_rational_prec_round_direct(x, y, prec, Nearest)) + }), ], ); } @@ -2375,10 +2490,10 @@ fn benchmark_float_mul_rational_round_library_comparison( &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { - no_out!(x.mul_rational_round(y, rm)) + no_out!(x.mul_rational_round_ref_ref(&y, rm)) }), ("rug", &mut |((x, y, rm), _)| { - no_out!(rug_mul_rational_round(x, y, rm)) + no_out!(rug_mul_rational_round(&x, &y, rm)) }), ], ); @@ -2406,6 +2521,10 @@ fn benchmark_float_mul_rational_round_algorithms( let ysb = y.significant_bits(); mul_rational_prec_round_naive(x, y, ysb, rm); }), + ("direct", &mut |(x, y, rm)| { + let ysb = y.significant_bits(); + mul_rational_prec_round_direct(x, y, ysb, rm); + }), ], ); } @@ -2472,6 +2591,33 @@ fn benchmark_float_mul_rational_prec_round_evaluation_strategy( ); } +fn benchmark_float_mul_rational_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.mul_rational_prec_round(Rational, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_rounding_mode_quadruple_gen_var_3_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( + "x", "y", "prec", + ), + &mut [ + ("Malachite", &mut |(_, (x, y, prec, rm))| { + no_out!(x.mul_rational_prec_round_ref_ref(&y, prec, rm)) + }), + ("rug", &mut |((x, y, prec, rm), _)| { + no_out!(rug_mul_rational_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + fn benchmark_float_mul_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, @@ -2493,6 +2639,93 @@ fn benchmark_float_mul_rational_prec_round_algorithms( ("naive", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_naive(x, y, prec, rm)) }), + ("direct", &mut |(x, y, prec, rm)| { + no_out!(mul_rational_prec_round_direct(x, y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_mul_rational_prec_round_val_ref_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.mul_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec, rm)| { + no_out!(x.mul_rational_prec_round_val_ref(&y, prec, rm)) + }), + ("naive", &mut |(x, y, prec, rm)| { + no_out!(mul_rational_prec_round_naive_val_ref(x, &y, prec, rm)) + }), + ("direct", &mut |(x, y, prec, rm)| { + no_out!(mul_rational_prec_round_direct_val_ref(x, &y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_mul_rational_prec_round_ref_val_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "(&Float).mul_rational_prec_round_ref_val(Rational, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec, rm)| { + no_out!(x.mul_rational_prec_round_ref_val(y, prec, rm)) + }), + ("naive", &mut |(x, y, prec, rm)| { + no_out!(mul_rational_prec_round_naive_ref_val(&x, y, prec, rm)) + }), + ("direct", &mut |(x, y, prec, rm)| { + no_out!(mul_rational_prec_round_direct_ref_val(&x, y, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_mul_rational_prec_round_ref_ref_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.mul_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", + BenchmarkType::Algorithms, + float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), + gm.name(), + limit, + file_name, + &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("default", &mut |(x, y, prec, rm)| { + no_out!(x.mul_rational_prec_round_ref_ref(&y, prec, rm)) + }), + ("naive", &mut |(x, y, prec, rm)| { + no_out!(mul_rational_prec_round_naive_ref_ref(&x, &y, prec, rm)) + }), + ("direct", &mut |(x, y, prec, rm)| { + no_out!(mul_rational_prec_round_direct_ref_ref(&x, &y, prec, rm)) + }), ], ); } diff --git a/malachite-float/src/bin_util/demo_and_bench/arithmetic/reciprocal.rs b/malachite-float/src/bin_util/demo_and_bench/arithmetic/reciprocal.rs new file mode 100644 index 000000000..f40f6e47d --- /dev/null +++ b/malachite-float/src/bin_util/demo_and_bench/arithmetic/reciprocal.rs @@ -0,0 +1,781 @@ +// 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::{Reciprocal, ReciprocalAssign}; +use malachite_base::num::logic::traits::SignificantBits; +use malachite_base::rounding_modes::RoundingMode::*; +use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; +use malachite_base::test_util::generators::common::{GenConfig, GenMode}; +use malachite_base::test_util::runner::Runner; +use malachite_float::test_util::arithmetic::reciprocal::{ + reciprocal_prec_round_naive_1, reciprocal_prec_round_naive_2, rug_reciprocal, + rug_reciprocal_prec, rug_reciprocal_prec_round, rug_reciprocal_round, +}; +use malachite_float::test_util::bench::bucketers::{ + float_complexity_bucketer, pair_1_float_complexity_bucketer, pair_2_float_complexity_bucketer, + pair_2_pair_1_float_complexity_bucketer, + pair_2_pair_float_primitive_int_max_complexity_bucketer, + pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer, + pair_float_primitive_int_max_complexity_bucketer, + triple_1_2_float_primitive_int_max_complexity_bucketer, +}; +use malachite_float::test_util::generators::{ + float_gen, float_gen_rm, float_rounding_mode_pair_gen_var_13, + float_rounding_mode_pair_gen_var_13_rm, float_unsigned_pair_gen_var_1, + float_unsigned_pair_gen_var_1_rm, float_unsigned_rounding_mode_triple_gen_var_3, + float_unsigned_rounding_mode_triple_gen_var_3_rm, +}; +use malachite_float::{ComparableFloat, ComparableFloatRef}; + +pub(crate) fn register(runner: &mut Runner) { + register_demo!(runner, demo_float_reciprocal); + register_demo!(runner, demo_float_reciprocal_debug); + register_demo!(runner, demo_float_reciprocal_ref); + register_demo!(runner, demo_float_reciprocal_ref_debug); + register_demo!(runner, demo_float_reciprocal_assign); + register_demo!(runner, demo_float_reciprocal_assign_debug); + register_demo!(runner, demo_float_reciprocal_prec); + register_demo!(runner, demo_float_reciprocal_prec_debug); + register_demo!(runner, demo_float_reciprocal_prec_ref); + register_demo!(runner, demo_float_reciprocal_prec_ref_debug); + register_demo!(runner, demo_float_reciprocal_prec_assign); + register_demo!(runner, demo_float_reciprocal_prec_assign_debug); + register_demo!(runner, demo_float_reciprocal_round); + register_demo!(runner, demo_float_reciprocal_round_debug); + register_demo!(runner, demo_float_reciprocal_round_ref); + register_demo!(runner, demo_float_reciprocal_round_ref_debug); + register_demo!(runner, demo_float_reciprocal_round_assign); + register_demo!(runner, demo_float_reciprocal_round_assign_debug); + register_demo!(runner, demo_float_reciprocal_prec_round); + register_demo!(runner, demo_float_reciprocal_prec_round_debug); + register_demo!(runner, demo_float_reciprocal_prec_round_ref); + register_demo!(runner, demo_float_reciprocal_prec_round_ref_debug); + register_demo!(runner, demo_float_reciprocal_prec_round_assign); + register_demo!(runner, demo_float_reciprocal_prec_round_assign_debug); + + register_bench!(runner, benchmark_float_reciprocal_evaluation_strategy); + register_bench!(runner, benchmark_float_reciprocal_library_comparison); + register_bench!(runner, benchmark_float_reciprocal_algorithms); + register_bench!(runner, benchmark_float_reciprocal_assign); + register_bench!(runner, benchmark_float_reciprocal_prec_evaluation_strategy); + register_bench!(runner, benchmark_float_reciprocal_prec_library_comparison); + register_bench!(runner, benchmark_float_reciprocal_prec_algorithms); + register_bench!(runner, benchmark_float_reciprocal_prec_assign); + register_bench!(runner, benchmark_float_reciprocal_round_evaluation_strategy); + register_bench!(runner, benchmark_float_reciprocal_round_library_comparison); + register_bench!(runner, benchmark_float_reciprocal_round_algorithms); + register_bench!(runner, benchmark_float_reciprocal_round_assign); + register_bench!( + runner, + benchmark_float_reciprocal_prec_round_evaluation_strategy + ); + register_bench!( + runner, + benchmark_float_reciprocal_prec_round_library_comparison + ); + register_bench!(runner, benchmark_float_reciprocal_prec_round_algorithms); + register_bench!(runner, benchmark_float_reciprocal_prec_round_assign); +} + +fn demo_float_reciprocal(gm: GenMode, config: &GenConfig, limit: usize) { + for x in float_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + println!("({}).reciprocal() = {}", x_old, x.reciprocal()); + } +} + +fn demo_float_reciprocal_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for x in float_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + println!( + "({:#x}).reciprocal() = {:#x}", + ComparableFloat(x_old), + ComparableFloat(x.reciprocal()) + ); + } +} + +fn demo_float_reciprocal_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for x in float_gen().get(gm, config).take(limit) { + println!("(&{}).reciprocal() = {}", x, (&x).reciprocal()); + } +} + +fn demo_float_reciprocal_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for x in float_gen().get(gm, config).take(limit) { + println!( + "(&{:#x}).reciprocal() = {:#x}", + ComparableFloatRef(&x), + ComparableFloat((&x).reciprocal()) + ); + } +} + +fn demo_float_reciprocal_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for mut x in float_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x.reciprocal_assign(); + println!("x := {x_old}; x.reciprocal_assign(); x = {x}"); + } +} + +fn demo_float_reciprocal_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for mut x in float_gen().get(gm, config).take(limit) { + let x_old = x.clone(); + x.reciprocal_assign(); + println!( + "x := {:#x}; x.reciprocal_assign(); x = {:#x}", + ComparableFloat(x_old), + ComparableFloat(x) + ); + } +} + +fn demo_float_reciprocal_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let x_old = x.clone(); + println!( + "({}).reciprocal_prec({}) = {:?}", + x_old, + prec, + x.reciprocal_prec(prec) + ); + } +} + +fn demo_float_reciprocal_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let x_old = x.clone(); + let (sum, o) = x.reciprocal_prec(prec); + println!( + "({:#x}).reciprocal_prec({}) = ({:#x}, {:?})", + ComparableFloat(x_old), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_reciprocal_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + println!( + "(&{}).reciprocal_prec_ref({}) = {:?}", + x, + prec, + x.reciprocal_prec_ref(prec) + ); + } +} + +fn demo_float_reciprocal_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let (sum, o) = x.reciprocal_prec_ref(prec); + println!( + "(&{:#x}).reciprocal_prec_ref({}) = ({:#x}, {:?})", + ComparableFloat(x), + prec, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_reciprocal_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let x_old = x.clone(); + x.reciprocal_prec_assign(prec); + println!("x := {x_old}; x.reciprocal_prec_assign({prec}); x = {x}"); + } +} + +fn demo_float_reciprocal_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let x_old = x.clone(); + let o = x.reciprocal_prec_assign(prec); + println!( + "x := {:#x}; x.reciprocal_prec_assign({}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + prec, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_reciprocal_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, rm) in float_rounding_mode_pair_gen_var_13() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "({}).reciprocal_round({}) = {:?}", + x_old, + rm, + x.reciprocal_round(rm) + ); + } +} + +fn demo_float_reciprocal_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, rm) in float_rounding_mode_pair_gen_var_13() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = x.reciprocal_round(rm); + println!( + "({:#x}).reciprocal_round({}) = ({:#x}, {:?})", + ComparableFloat(x_old), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_reciprocal_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, rm) in float_rounding_mode_pair_gen_var_13() + .get(gm, config) + .take(limit) + { + println!( + "(&{}).reciprocal_round_ref({}) = {:?}", + x, + rm, + x.reciprocal_round_ref(rm) + ); + } +} + +fn demo_float_reciprocal_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, rm) in float_rounding_mode_pair_gen_var_13() + .get(gm, config) + .take(limit) + { + let (sum, o) = x.reciprocal_round_ref(rm); + println!( + "(&{:#x}).reciprocal_round_ref({}) = ({:#x}, {:?})", + ComparableFloat(x), + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_reciprocal_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, rm) in float_rounding_mode_pair_gen_var_13() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + x.reciprocal_round_assign(rm); + println!("x := {x_old}; x.reciprocal_round_assign({rm}); x = {x}"); + } +} + +fn demo_float_reciprocal_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, rm) in float_rounding_mode_pair_gen_var_13() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.reciprocal_round_assign(rm); + println!( + "x := {:#x}; x.reciprocal_round_assign({}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + rm, + o, + ComparableFloat(x) + ); + } +} + +fn demo_float_reciprocal_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + println!( + "({}).reciprocal_prec_round({}, {}) = {:?}", + x_old, + prec, + rm, + x.reciprocal_prec_round(prec, rm) + ); + } +} + +fn demo_float_reciprocal_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let (sum, o) = x.reciprocal_prec_round(prec, rm); + println!( + "({:#x}).reciprocal_prec_round({}, {}) = ({:#x}, {:?})", + ComparableFloat(x_old), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_reciprocal_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() + .get(gm, config) + .take(limit) + { + println!( + "({}).reciprocal_prec_round_ref({}, {}) = {:?}", + x, + prec, + rm, + x.reciprocal_prec_round_ref(prec, rm) + ); + } +} + +fn demo_float_reciprocal_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() + .get(gm, config) + .take(limit) + { + let (sum, o) = x.reciprocal_prec_round_ref(prec, rm); + println!( + "({:#x}).reciprocal_prec_round_ref({}, {}) = ({:#x}, {:?})", + ComparableFloat(x), + prec, + rm, + ComparableFloat(sum), + o + ); + } +} + +fn demo_float_reciprocal_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.reciprocal_prec_round_assign(prec, rm); + println!("x := {x_old}; x.reciprocal_prec_round({prec}, {rm}) = {o:?}; x = {x}"); + } +} + +fn demo_float_reciprocal_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() + .get(gm, config) + .take(limit) + { + let x_old = x.clone(); + let o = x.reciprocal_prec_round_assign(prec, rm); + println!( + "x := {:#x}; x.reciprocal_prec_round({}, {}) = {:?}; x = {:#x}", + ComparableFloat(x_old), + prec, + rm, + o, + ComparableFloat(x) + ); + } +} + +fn benchmark_float_reciprocal_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal()", + BenchmarkType::EvaluationStrategy, + float_gen().get(gm, config), + gm.name(), + limit, + file_name, + &float_complexity_bucketer("x"), + &mut [ + ("Float.reciprocal()", &mut |x| no_out!(x.reciprocal())), + ("(&Float).reciprocal()", &mut |x| no_out!((&x).reciprocal())), + ], + ); +} + +fn benchmark_float_reciprocal_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal()", + BenchmarkType::LibraryComparison, + float_gen_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_float_complexity_bucketer("x"), + &mut [ + ("Malachite", &mut |(_, x)| no_out!((&x).reciprocal())), + ("rug", &mut |(x, _)| no_out!(rug_reciprocal(&x))), + ], + ); +} + +fn benchmark_float_reciprocal_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal()", + BenchmarkType::Algorithms, + float_gen().get(gm, config), + gm.name(), + limit, + file_name, + &float_complexity_bucketer("x"), + &mut [ + ("default", &mut |x| no_out!(x.reciprocal())), + ("naive 1", &mut |x| { + let xsb = x.significant_bits(); + no_out!(reciprocal_prec_round_naive_1(x, xsb, Nearest).0) + }), + ("naive 2", &mut |x| { + let xsb = x.significant_bits(); + no_out!(reciprocal_prec_round_naive_2(x, xsb, Nearest).0) + }), + ], + ); +} + +fn benchmark_float_reciprocal_assign( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_assign()", + BenchmarkType::Single, + float_gen().get(gm, config), + gm.name(), + limit, + file_name, + &float_complexity_bucketer("x"), + &mut [("Float.reciprocal_assign()", &mut |mut x| { + x.reciprocal_assign() + })], + ); +} + +fn benchmark_float_reciprocal_prec_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_prec(u64)", + BenchmarkType::EvaluationStrategy, + float_unsigned_pair_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [ + ("Float.reciprocal_prec(u64)", &mut |(x, prec)| { + no_out!(x.reciprocal_prec(prec)) + }), + ("(&Float).reciprocal_prec_ref(u64)", &mut |(x, prec)| { + no_out!(x.reciprocal_prec_ref(prec)) + }), + ], + ); +} + +fn benchmark_float_reciprocal_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_prec(u64)", + BenchmarkType::LibraryComparison, + float_unsigned_pair_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_pair_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, prec))| { + no_out!(x.reciprocal_prec_ref(prec)) + }), + ("rug", &mut |((x, prec), _)| { + no_out!(rug_reciprocal_prec(&x, prec)) + }), + ], + ); +} + +fn benchmark_float_reciprocal_prec_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_prec(u64)", + BenchmarkType::Algorithms, + float_unsigned_pair_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [ + ("default", &mut |(x, prec)| no_out!(x.reciprocal_prec(prec))), + ("naive 1", &mut |(x, prec)| { + no_out!(reciprocal_prec_round_naive_1(x, prec, Nearest)) + }), + ("naive 2", &mut |(x, prec)| { + no_out!(reciprocal_prec_round_naive_2(x, prec, Nearest)) + }), + ], + ); +} + +fn benchmark_float_reciprocal_prec_assign( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_prec_assign(u64)", + BenchmarkType::Single, + float_unsigned_pair_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [("Float.reciprocal_prec_assign(u64)", &mut |(mut x, prec)| { + no_out!(x.reciprocal_prec_assign(prec)) + })], + ); +} + +fn benchmark_float_reciprocal_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_round(RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_rounding_mode_pair_gen_var_13().get(gm, config), + gm.name(), + limit, + file_name, + &pair_1_float_complexity_bucketer("x"), + &mut [ + ("Float.reciprocal_round(RoundingMode)", &mut |(x, rm)| { + no_out!(x.reciprocal_round(rm)) + }), + ( + "(&Float).reciprocal_round_ref(RoundingMode)", + &mut |(x, rm)| no_out!(x.reciprocal_round_ref(rm)), + ), + ], + ); +} + +fn benchmark_float_reciprocal_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_round(u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_rounding_mode_pair_gen_var_13_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_pair_1_float_complexity_bucketer("x"), + &mut [ + ("Malachite", &mut |(_, (x, rm))| { + no_out!(x.reciprocal_round_ref(rm)) + }), + ("rug", &mut |((x, rm), _)| { + no_out!(rug_reciprocal_round(&x, rm)) + }), + ], + ); +} + +fn benchmark_float_reciprocal_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_round(RoundingMode)", + BenchmarkType::Algorithms, + float_rounding_mode_pair_gen_var_13().get(gm, config), + gm.name(), + limit, + file_name, + &pair_1_float_complexity_bucketer("x"), + &mut [ + ("default", &mut |(x, rm)| no_out!(x.reciprocal_round(rm))), + ("naive 1", &mut |(x, rm)| { + let xsb = x.significant_bits(); + reciprocal_prec_round_naive_1(x, xsb, rm); + }), + ("naive 2", &mut |(x, rm)| { + let xsb = x.significant_bits(); + reciprocal_prec_round_naive_2(x, xsb, rm); + }), + ], + ); +} + +fn benchmark_float_reciprocal_round_assign( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_round_assign(RoundingMode)", + BenchmarkType::Single, + float_rounding_mode_pair_gen_var_13().get(gm, config), + gm.name(), + limit, + file_name, + &pair_1_float_complexity_bucketer("x"), + &mut [( + "Float.reciprocal_round_assign(RoundingMode)", + &mut |(mut x, rm)| no_out!(x.reciprocal_round_assign(rm)), + )], + ); +} + +fn benchmark_float_reciprocal_prec_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_prec_round(u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [ + ( + "Float.reciprocal_prec_round(u64, RoundingMode)", + &mut |(x, prec, rm)| no_out!(x.reciprocal_prec_round(prec, rm)), + ), + ( + "(&Float).reciprocal_prec_round_ref(u64, RoundingMode)", + &mut |(x, prec, rm)| no_out!(x.reciprocal_prec_round_ref(prec, rm)), + ), + ], + ); +} + +fn benchmark_float_reciprocal_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_prec_round(u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_unsigned_rounding_mode_triple_gen_var_3_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, prec, rm))| { + no_out!(x.reciprocal_prec_round_ref(prec, rm)) + }), + ("rug", &mut |((x, prec, rm), _)| { + no_out!(rug_reciprocal_prec_round(&x, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_reciprocal_prec_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_prec_round(u64, RoundingMode)", + BenchmarkType::Algorithms, + float_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [ + ("default", &mut |(x, prec, rm)| { + no_out!(x.reciprocal_prec_round(prec, rm)) + }), + ("naive 1", &mut |(x, prec, rm)| { + no_out!(reciprocal_prec_round_naive_1(x, prec, rm)) + }), + ("naive 2", &mut |(x, prec, rm)| { + no_out!(reciprocal_prec_round_naive_2(x, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_reciprocal_prec_round_assign( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.reciprocal_prec_round_assign(u64, RoundingMode)", + BenchmarkType::Single, + float_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [( + "Float.reciprocal_prec_round_assign(u64, RoundingMode)", + &mut |(mut x, prec, rm)| no_out!(x.reciprocal_prec_round_assign(prec, rm)), + )], + ); +} diff --git a/malachite-float/src/bin_util/demo_and_bench/arithmetic/square.rs b/malachite-float/src/bin_util/demo_and_bench/arithmetic/square.rs index e1700da7b..773e8cc36 100644 --- a/malachite-float/src/bin_util/demo_and_bench/arithmetic/square.rs +++ b/malachite-float/src/bin_util/demo_and_bench/arithmetic/square.rs @@ -13,16 +13,22 @@ use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::arithmetic::square::square_prec_round_naive; -use malachite_float::test_util::arithmetic::square::{rug_square, rug_square_round}; +use malachite_float::test_util::arithmetic::square::{ + rug_square, rug_square_prec, rug_square_prec_round, rug_square_round, +}; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, pair_2_float_complexity_bucketer, - pair_2_pair_1_float_complexity_bucketer, pair_float_primitive_int_max_complexity_bucketer, + pair_2_pair_1_float_complexity_bucketer, + pair_2_pair_float_primitive_int_max_complexity_bucketer, + pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer, + pair_float_primitive_int_max_complexity_bucketer, triple_1_2_float_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_rm, float_rounding_mode_pair_gen_var_7, float_rounding_mode_pair_gen_var_7_rm, float_unsigned_pair_gen_var_1, - float_unsigned_rounding_mode_triple_gen_var_2, + float_unsigned_pair_gen_var_1_rm, float_unsigned_rounding_mode_triple_gen_var_2, + float_unsigned_rounding_mode_triple_gen_var_2_rm, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; @@ -57,6 +63,7 @@ pub(crate) fn register(runner: &mut Runner) { register_bench!(runner, benchmark_float_square_algorithms); register_bench!(runner, benchmark_float_square_assign); register_bench!(runner, benchmark_float_square_prec_evaluation_strategy); + register_bench!(runner, benchmark_float_square_prec_library_comparison); register_bench!(runner, benchmark_float_square_prec_algorithms); register_bench!(runner, benchmark_float_square_prec_assign); register_bench!(runner, benchmark_float_square_round_evaluation_strategy); @@ -67,6 +74,7 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_square_prec_round_evaluation_strategy ); + register_bench!(runner, benchmark_float_square_prec_round_library_comparison); register_bench!(runner, benchmark_float_square_prec_round_algorithms); register_bench!(runner, benchmark_float_square_prec_round_assign); } @@ -419,8 +427,8 @@ fn benchmark_float_square_library_comparison( file_name, &pair_2_float_complexity_bucketer("x"), &mut [ - ("Malachite", &mut |(_, x)| no_out!(x.square())), - ("rug", &mut |(x, _)| no_out!(rug_square(x))), + ("Malachite", &mut |(_, x)| no_out!((&x).square())), + ("rug", &mut |(x, _)| no_out!(rug_square(&x))), ], ); } @@ -487,6 +495,31 @@ fn benchmark_float_square_prec_evaluation_strategy( ); } +fn benchmark_float_square_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.square_prec(u64)", + BenchmarkType::LibraryComparison, + float_unsigned_pair_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_pair_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, prec))| { + no_out!(x.square_prec_ref(prec)) + }), + ("rug", &mut |((x, prec), _)| { + no_out!(rug_square_prec(&x, prec)) + }), + ], + ); +} + fn benchmark_float_square_prec_algorithms( gm: GenMode, config: &GenConfig, @@ -570,8 +603,10 @@ fn benchmark_float_square_round_library_comparison( file_name, &pair_2_pair_1_float_complexity_bucketer("x"), &mut [ - ("Malachite", &mut |(_, (x, rm))| no_out!(x.square_round(rm))), - ("rug", &mut |((x, rm), _)| no_out!(rug_square_round(x, rm))), + ("Malachite", &mut |(_, (x, rm))| { + no_out!(x.square_round_ref(rm)) + }), + ("rug", &mut |((x, rm), _)| no_out!(rug_square_round(&x, rm))), ], ); } @@ -650,6 +685,31 @@ fn benchmark_float_square_prec_round_evaluation_strategy( ); } +fn benchmark_float_square_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.square_prec_round(u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_unsigned_rounding_mode_triple_gen_var_2_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, prec, rm))| { + no_out!(x.square_prec_round_ref(prec, rm)) + }), + ("rug", &mut |((x, prec, rm), _)| { + no_out!(rug_square_prec_round(&x, prec, rm)) + }), + ], + ); +} + fn benchmark_float_square_prec_round_algorithms( gm: GenMode, config: &GenConfig, diff --git a/malachite-float/src/bin_util/demo_and_bench/arithmetic/sub.rs b/malachite-float/src/bin_util/demo_and_bench/arithmetic/sub.rs index 53c3438d7..10b215c49 100644 --- a/malachite-float/src/bin_util/demo_and_bench/arithmetic/sub.rs +++ b/malachite-float/src/bin_util/demo_and_bench/arithmetic/sub.rs @@ -15,13 +15,18 @@ use malachite_float::test_util::arithmetic::add::{ add_prec_round_naive, add_rational_prec_round_naive, }; use malachite_float::test_util::arithmetic::sub::{ - rug_sub, rug_sub_rational, rug_sub_rational_round, rug_sub_round, + rug_sub, rug_sub_prec, rug_sub_prec_round, rug_sub_rational, rug_sub_rational_prec, + rug_sub_rational_prec_round, rug_sub_rational_round, rug_sub_round, }; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_2_pair_float_rational_max_complexity_bucketer, + pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, + pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_max_complexity_bucketer, - pair_2_triple_1_2_float_rational_max_complexity_bucketer, pair_float_max_complexity_bucketer, - pair_float_rational_max_complexity_bucketer, + pair_2_triple_1_2_float_rational_max_complexity_bucketer, + pair_2_triple_float_float_primitive_int_max_complexity_bucketer, + pair_2_triple_float_rational_primitive_int_max_complexity_bucketer, + pair_float_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, triple_1_2_float_max_complexity_bucketer, triple_1_2_float_rational_max_complexity_bucketer, @@ -30,12 +35,15 @@ use malachite_float::test_util::bench::bucketers::{ }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_1_rm, float_float_rounding_mode_triple_gen_var_2, - float_float_unsigned_rounding_mode_quadruple_gen_var_2, float_float_unsigned_triple_gen_var_1, + float_float_unsigned_rounding_mode_quadruple_gen_var_2, + float_float_unsigned_rounding_mode_quadruple_gen_var_2_rm, + float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, float_pair_gen, float_pair_gen_rm, float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_rounding_mode_triple_gen_var_2, float_rational_rounding_mode_triple_gen_var_3_rm, float_rational_unsigned_rounding_mode_quadruple_gen_var_2, - float_rational_unsigned_triple_gen_var_1, + float_rational_unsigned_rounding_mode_quadruple_gen_var_2_rm, + float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_1_rm, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use std::cmp::max; @@ -151,6 +159,7 @@ pub(crate) fn register(runner: &mut Runner) { register_bench!(runner, benchmark_float_sub_algorithms); register_bench!(runner, benchmark_float_sub_assign_evaluation_strategy); register_bench!(runner, benchmark_float_sub_prec_evaluation_strategy); + register_bench!(runner, benchmark_float_sub_prec_library_comparison); register_bench!(runner, benchmark_float_sub_prec_algorithms); register_bench!(runner, benchmark_float_sub_prec_assign_evaluation_strategy); register_bench!(runner, benchmark_float_sub_round_evaluation_strategy); @@ -158,6 +167,7 @@ pub(crate) fn register(runner: &mut Runner) { register_bench!(runner, benchmark_float_sub_round_algorithms); register_bench!(runner, benchmark_float_sub_round_assign_evaluation_strategy); register_bench!(runner, benchmark_float_sub_prec_round_evaluation_strategy); + register_bench!(runner, benchmark_float_sub_prec_round_library_comparison); register_bench!(runner, benchmark_float_sub_prec_round_algorithms); register_bench!( runner, @@ -176,6 +186,7 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_sub_rational_prec_evaluation_strategy ); + register_bench!(runner, benchmark_float_sub_rational_prec_library_comparison); register_bench!(runner, benchmark_float_sub_rational_prec_algorithms); register_bench!( runner, @@ -198,6 +209,10 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_sub_rational_prec_round_evaluation_strategy ); + register_bench!( + runner, + benchmark_float_sub_rational_prec_round_library_comparison + ); register_bench!(runner, benchmark_float_sub_rational_prec_round_algorithms); register_bench!( runner, @@ -1764,8 +1779,8 @@ fn benchmark_float_sub_library_comparison( file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ - ("Malachite", &mut |(_, (x, y))| no_out!(x - y)), - ("rug", &mut |((x, y), _)| no_out!(rug_sub(x, y))), + ("Malachite", &mut |(_, (x, y))| no_out!(&x - &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_sub(&x, &y))), ], ); } @@ -1849,6 +1864,31 @@ fn benchmark_float_sub_prec_evaluation_strategy( ); } +fn benchmark_float_sub_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.sub_prec(Float, u64)", + BenchmarkType::LibraryComparison, + float_float_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec))| { + no_out!(x.sub_prec_ref_ref(&y, prec)) + }), + ("rug", &mut |((x, y, prec), _)| { + no_out!(rug_sub_prec(&x, &y, prec)) + }), + ], + ); +} + fn benchmark_float_sub_prec_algorithms( gm: GenMode, config: &GenConfig, @@ -1952,10 +1992,10 @@ fn benchmark_float_sub_round_library_comparison( &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { - no_out!(x.sub_round(y, rm)) + no_out!(x.sub_round_ref_ref(&y, rm)) }), ("rug", &mut |((x, y, rm), _)| { - no_out!(rug_sub_round(x, y, rm)) + no_out!(rug_sub_round(&x, &y, rm)) }), ], ); @@ -2048,6 +2088,31 @@ fn benchmark_float_sub_prec_round_evaluation_strategy( ); } +fn benchmark_float_sub_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.sub_prec_round(Float, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_float_unsigned_rounding_mode_quadruple_gen_var_2_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec, rm))| { + no_out!(x.sub_prec_round_ref_ref(&y, prec, rm)) + }), + ("rug", &mut |((x, y, prec, rm), _)| { + no_out!(rug_sub_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + fn benchmark_float_sub_prec_round_algorithms( gm: GenMode, config: &GenConfig, @@ -2140,8 +2205,8 @@ fn benchmark_float_sub_rational_library_comparison( file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ - ("Malachite", &mut |(_, (x, y))| no_out!(x - y)), - ("rug", &mut |((x, y), _)| no_out!(rug_sub_rational(x, y))), + ("Malachite", &mut |(_, (x, y))| no_out!(&x - &y)), + ("rug", &mut |((x, y), _)| no_out!(rug_sub_rational(&x, &y))), ], ); } @@ -2233,8 +2298,8 @@ fn benchmark_rational_sub_float_library_comparison( file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ - ("Malachite", &mut |(_, (y, x))| no_out!(x - y)), - ("rug", &mut |((y, x), _)| no_out!(-rug_sub_rational(y, x))), + ("Malachite", &mut |(_, (y, x))| no_out!(&x - &y)), + ("rug", &mut |((y, x), _)| no_out!(-rug_sub_rational(&y, &x))), ], ); } @@ -2274,6 +2339,31 @@ fn benchmark_float_sub_rational_prec_evaluation_strategy( ); } +fn benchmark_float_sub_rational_prec_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.sub_rational_prec(Rational, u64)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), + &mut [ + ("Malachite", &mut |(_, (x, y, prec))| { + no_out!(x.sub_rational_prec_ref_ref(&y, prec)) + }), + ("rug", &mut |((x, y, prec), _)| { + no_out!(rug_sub_rational_prec(&x, &y, prec)) + }), + ], + ); +} + fn benchmark_float_sub_rational_prec_algorithms( gm: GenMode, config: &GenConfig, @@ -2377,10 +2467,10 @@ fn benchmark_float_sub_rational_round_library_comparison( &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { - no_out!(x.sub_rational_round(y, rm)) + no_out!(x.sub_rational_round_ref_ref(&y, rm)) }), ("rug", &mut |((x, y, rm), _)| { - no_out!(rug_sub_rational_round(x, y, rm)) + no_out!(rug_sub_rational_round(&x, &y, rm)) }), ], ); @@ -2474,6 +2564,33 @@ fn benchmark_float_sub_rational_prec_round_evaluation_strategy( ); } +fn benchmark_float_sub_rational_prec_round_library_comparison( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.sub_rational_prec_round(Rational, u64, RoundingMode)", + BenchmarkType::LibraryComparison, + float_rational_unsigned_rounding_mode_quadruple_gen_var_2_rm().get(gm, config), + gm.name(), + limit, + file_name, + &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( + "x", "y", "prec", + ), + &mut [ + ("Malachite", &mut |(_, (x, y, prec, rm))| { + no_out!(x.sub_rational_prec_round_ref_ref(&y, prec, rm)) + }), + ("rug", &mut |((x, y, prec, rm), _)| { + no_out!(rug_sub_rational_prec_round(&x, &y, prec, rm)) + }), + ], + ); +} + fn benchmark_float_sub_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, diff --git a/malachite-float/src/bin_util/demo_and_bench/basic/constants.rs b/malachite-float/src/bin_util/demo_and_bench/basic/constants.rs index e14c731a9..d19f628d6 100644 --- a/malachite-float/src/bin_util/demo_and_bench/basic/constants.rs +++ b/malachite-float/src/bin_util/demo_and_bench/basic/constants.rs @@ -102,7 +102,7 @@ fn benchmark_float_one_prec_library_comparison( file_name: &str, ) { run_benchmark( - "Float.one_prec()", + "Float.one_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), @@ -125,7 +125,7 @@ fn benchmark_float_two_prec_library_comparison( file_name: &str, ) { run_benchmark( - "Float.two_prec()", + "Float.two_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), @@ -148,7 +148,7 @@ fn benchmark_float_negative_one_prec_library_comparison( file_name: &str, ) { run_benchmark( - "Float.negative_one_prec()", + "Float.negative_one_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), @@ -171,7 +171,7 @@ fn benchmark_float_one_half_prec_library_comparison( file_name: &str, ) { run_benchmark( - "Float.one_half_prec()", + "Float.one_half_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), diff --git a/malachite-float/src/bin_util/demo_and_bench/basic/get_and_set.rs b/malachite-float/src/bin_util/demo_and_bench/basic/get_and_set.rs index 8e3e08207..14190259c 100644 --- a/malachite-float/src/bin_util/demo_and_bench/basic/get_and_set.rs +++ b/malachite-float/src/bin_util/demo_and_bench/basic/get_and_set.rs @@ -11,7 +11,8 @@ use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ - float_complexity_bucketer, pair_2_float_complexity_bucketer, + float_complexity_bucketer, max_pair_1_complexity_pair_2_bucketer, + max_triple_1_float_complexity_triple_2_bucketer, pair_2_float_complexity_bucketer, pair_2_max_pair_1_complexity_pair_2_bucketer, pair_2_max_triple_1_float_complexity_triple_2_bucketer, }; @@ -20,7 +21,7 @@ use malachite_float::test_util::generators::{ float_unsigned_rounding_mode_triple_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1_rm, }; -use malachite_float::{ComparableFloat, ComparableFloatRef}; +use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_to_significand); @@ -39,6 +40,14 @@ pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_set_prec_round_debug); register_demo!(runner, demo_float_set_prec); register_demo!(runner, demo_float_set_prec_debug); + register_demo!(runner, demo_float_from_float_prec_round); + register_demo!(runner, demo_float_from_float_prec_round_debug); + register_demo!(runner, demo_float_from_float_prec_round_ref); + register_demo!(runner, demo_float_from_float_prec_round_ref_debug); + register_demo!(runner, demo_float_from_float_prec); + register_demo!(runner, demo_float_from_float_prec_debug); + register_demo!(runner, demo_float_from_float_prec_ref); + register_demo!(runner, demo_float_from_float_prec_ref_debug); register_bench!(runner, benchmark_float_to_significand_evaluation_strategy); register_bench!(runner, benchmark_float_significand_ref_library_comparison); @@ -46,7 +55,9 @@ pub(crate) fn register(runner: &mut Runner) { register_bench!(runner, benchmark_float_get_prec_library_comparison); register_bench!(runner, benchmark_float_get_min_prec); register_bench!(runner, benchmark_float_set_prec_round_library_comparison); + register_bench!(runner, benchmark_float_set_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_set_prec_library_comparison); + register_bench!(runner, benchmark_float_set_prec_evaluation_strategy); } fn demo_float_to_significand(gm: GenMode, config: &GenConfig, limit: usize) { @@ -150,27 +161,27 @@ fn demo_float_get_min_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) } fn demo_float_set_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { - for (mut x, p, rm) in float_unsigned_rounding_mode_triple_gen_var_1() + for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let old_x = x.clone(); - let o = x.set_prec_round(p, rm); - println!("x := {old_x}; x.set_prec_round({p}, {rm}) = {o:?}; x = {x}"); + let o = x.set_prec_round(prec, rm); + println!("x := {old_x}; x.set_prec_round({prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_set_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { - for (mut x, p, rm) in float_unsigned_rounding_mode_triple_gen_var_1() + for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let old_x = x.clone(); - let o = x.set_prec_round(p, rm); + let o = x.set_prec_round(prec, rm); println!( "x := {:#x}; x.set_prec_round({}, {}) = {:?}; x = {:#x}", ComparableFloat(old_x), - p, + prec, rm, o, ComparableFloat(x) @@ -179,27 +190,95 @@ fn demo_float_set_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize } fn demo_float_set_prec(gm: GenMode, config: &GenConfig, limit: usize) { - for (mut x, p) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let old_x = x.clone(); - let o = x.set_prec(p); - println!("x := {old_x}; x.set_prec({p}) = {o:?}; x = {x}"); + let o = x.set_prec(prec); + println!("x := {old_x}; x.set_prec({prec}) = {o:?}; x = {x}"); } } fn demo_float_set_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { - for (mut x, p) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let old_x = x.clone(); - let o = x.set_prec(p); + let o = x.set_prec(prec); println!( "x := {:#x}; x.set_prec({}) = {:?}; x = {:#x}", ComparableFloat(old_x), - p, + prec, o, ComparableFloat(x) ); } } +fn demo_float_from_float_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let (y, o) = Float::from_float_prec_round(x.clone(), prec, rm); + println!("Float::from_float_prec_round({x}, {prec}, {rm}) = ({y}, {o:?})"); + } +} + +fn demo_float_from_float_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let (y, o) = Float::from_float_prec_round(x.clone(), prec, rm); + println!("Float::from_float_prec_round({x:#x}, {prec}, {rm}) = ({y:#x}, {o:?})"); + } +} + +fn demo_float_from_float_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let (y, o) = Float::from_float_prec_round_ref(&x, prec, rm); + println!("Float::from_float_prec_round_ref(&{x}, {prec}, {rm}) = ({y}, {o:?})"); + } +} + +fn demo_float_from_float_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() + .get(gm, config) + .take(limit) + { + let (y, o) = Float::from_float_prec_round_ref(&x, prec, rm); + println!("Float::from_float_prec_round_ref(&{x:#x}, {prec}, {rm}) = ({y:#x}, {o:?})"); + } +} + +fn demo_float_from_float_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let (y, o) = Float::from_float_prec(x.clone(), prec); + println!("Float::from_float_prec({x}, {prec}) = ({y}, {o:?})"); + } +} + +fn demo_float_from_float_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let (y, o) = Float::from_float_prec(x.clone(), prec); + println!("Float::from_float_prec({x:#x}, {prec}) = ({y:#x}, {o:?})"); + } +} + +fn demo_float_from_float_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let (y, o) = Float::from_float_prec_ref(&x, prec); + println!("Float::from_float_prec_ref(&{x}, {prec}) = ({y}, {o:?})"); + } +} + +fn demo_float_from_float_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { + let (y, o) = Float::from_float_prec_ref(&x, prec); + println!("Float::from_float_prec_ref(&{x:#x}, {prec}) = ({y:#x}, {o:?})"); + } +} + fn benchmark_float_to_significand_evaluation_strategy( gm: GenMode, config: &GenConfig, @@ -319,11 +398,43 @@ fn benchmark_float_set_prec_round_library_comparison( file_name, &pair_2_max_triple_1_float_complexity_triple_2_bucketer("x", "precision"), &mut [ - ("Malachite", &mut |(_, (mut x, p, rm))| { - no_out!(x.set_prec_round(p, rm)) + ("Malachite", &mut |(_, (mut x, prec, rm))| { + no_out!(x.set_prec_round(prec, rm)) }), - ("rug", &mut |((mut x, p, rm), _)| { - no_out!(x.set_prec_round(u32::exact_from(p), rm)) + ("rug", &mut |((mut x, prec, rm), _)| { + no_out!(x.set_prec_round(u32::exact_from(prec), rm)) + }), + ], + ); +} + +fn benchmark_float_set_prec_round_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.set_prec_round(u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + float_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &max_triple_1_float_complexity_triple_2_bucketer("x", "precision"), + &mut [ + ("Float::set_prec_round", &mut |(mut x, prec, rm)| { + no_out!(x.set_prec_round(prec, rm)) + }), + ("Float::from_float_prec_round", &mut |(x, prec, rm)| { + no_out!(Float::from_float_prec_round(x, prec, rm)) + }), + ("Float::from_float_prec_round_ref", &mut |(x, prec, rm)| { + no_out!(Float::from_float_prec_round_ref(&x, prec, rm)) + }), + ("clone and Float::set_prec_round", &mut |(x, prec, rm)| { + let mut x = x.clone(); + no_out!(x.set_prec_round(prec, rm)) }), ], ); @@ -344,9 +455,43 @@ fn benchmark_float_set_prec_library_comparison( file_name, &pair_2_max_pair_1_complexity_pair_2_bucketer("x", "precision"), &mut [ - ("Malachite", &mut |(_, (mut x, p))| no_out!(x.set_prec(p))), - ("rug", &mut |((mut x, p), _)| { - no_out!(x.set_prec(u32::exact_from(p))) + ("Malachite", &mut |(_, (mut x, prec))| { + no_out!(x.set_prec(prec)) + }), + ("rug", &mut |((mut x, prec), _)| { + no_out!(x.set_prec(u32::exact_from(prec))) + }), + ], + ); +} + +fn benchmark_float_set_prec_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float.set_prec(u64)", + BenchmarkType::EvaluationStrategy, + float_unsigned_pair_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &max_pair_1_complexity_pair_2_bucketer("x", "precision"), + &mut [ + ("Float::set_prec", &mut |(mut x, prec)| { + no_out!(x.set_prec(prec)) + }), + ("Float::from_float_prec", &mut |(x, prec)| { + no_out!(Float::from_float_prec(x, prec)) + }), + ("Float::from_float_prec_ref", &mut |(x, prec)| { + no_out!(Float::from_float_prec_ref(&x, prec)) + }), + ("clone and Float::set_prec", &mut |(x, prec)| { + let mut x = x.clone(); + no_out!(x.set_prec(prec)); }), ], ); diff --git a/malachite-float/src/bin_util/demo_and_bench/constants/mod.rs b/malachite-float/src/bin_util/demo_and_bench/constants/mod.rs new file mode 100644 index 000000000..e699054f6 --- /dev/null +++ b/malachite-float/src/bin_util/demo_and_bench/constants/mod.rs @@ -0,0 +1,17 @@ +// 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::test_util::runner::Runner; + +pub(crate) fn register(runner: &mut Runner) { + prime_constant::register(runner); + thue_morse_constant::register(runner); +} + +mod prime_constant; +mod thue_morse_constant; diff --git a/malachite-float/src/bin_util/demo_and_bench/constants/prime_constant.rs b/malachite-float/src/bin_util/demo_and_bench/constants/prime_constant.rs new file mode 100644 index 000000000..253478147 --- /dev/null +++ b/malachite-float/src/bin_util/demo_and_bench/constants/prime_constant.rs @@ -0,0 +1,129 @@ +// 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::rounding_modes::RoundingMode::*; +use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; +use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; +use malachite_base::test_util::generators::common::{GenConfig, GenMode}; +use malachite_base::test_util::generators::{ + unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, +}; +use malachite_base::test_util::runner::Runner; +use malachite_float::test_util::constants::prime_constant::prime_constant_prec_round_naive; +use malachite_float::ComparableFloat; +use malachite_float::Float; + +pub(crate) fn register(runner: &mut Runner) { + register_demo!(runner, demo_float_prime_constant_prec_round); + register_demo!(runner, demo_float_prime_constant_prec_round_debug); + register_demo!(runner, demo_float_prime_constant_prec); + register_demo!(runner, demo_float_prime_constant_prec_debug); + + register_bench!(runner, benchmark_float_prime_constant_prec_round_algorithms); + register_bench!(runner, benchmark_float_prime_constant_prec_algorithms); +} + +fn demo_float_prime_constant_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() + .get(gm, config) + .take(limit) + { + println!( + "prime_constant_prec_round({}, {}) = {:?}", + p, + rm, + Float::prime_constant_prec_round(p, rm) + ); + } +} + +fn demo_float_prime_constant_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() + .get(gm, config) + .take(limit) + { + let (pc, o) = Float::prime_constant_prec_round(p, rm); + println!( + "prime_constant_prec_round({}, {}) = ({:#x}, {:?})", + p, + rm, + ComparableFloat(pc), + o + ); + } +} + +fn demo_float_prime_constant_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for p in unsigned_gen_var_11().get(gm, config).take(limit) { + println!( + "prime_constant_prec({}) = {:?}", + p, + Float::prime_constant_prec(p) + ); + } +} + +fn demo_float_prime_constant_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for p in unsigned_gen_var_11().get(gm, config).take(limit) { + let (pc, o) = Float::prime_constant_prec(p); + println!( + "prime_constant_prec({}) = ({:#x}, {:?})", + p, + ComparableFloat(pc), + o + ); + } +} + +fn benchmark_float_prime_constant_prec_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::prime_constant_prec_round(u64, RoundingMode)", + BenchmarkType::Algorithms, + unsigned_rounding_mode_pair_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &pair_1_bucketer("prec"), + &mut [ + ("default", &mut |(p, rm)| { + no_out!(Float::prime_constant_prec_round(p, rm)) + }), + ("naive", &mut |(p, rm)| { + no_out!(prime_constant_prec_round_naive(p, rm)) + }), + ], + ); +} + +fn benchmark_float_prime_constant_prec_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::prime_constant_prec(u64)", + BenchmarkType::Algorithms, + unsigned_gen_var_11().get(gm, config), + gm.name(), + limit, + file_name, + &unsigned_direct_bucketer(), + &mut [ + ("default", &mut |p| no_out!(Float::prime_constant_prec(p))), + ("naive", &mut |p| { + no_out!(prime_constant_prec_round_naive(p, Nearest)) + }), + ], + ); +} diff --git a/malachite-float/src/bin_util/demo_and_bench/constants/thue_morse_constant.rs b/malachite-float/src/bin_util/demo_and_bench/constants/thue_morse_constant.rs new file mode 100644 index 000000000..2786690e8 --- /dev/null +++ b/malachite-float/src/bin_util/demo_and_bench/constants/thue_morse_constant.rs @@ -0,0 +1,134 @@ +// 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::rounding_modes::RoundingMode::*; +use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; +use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; +use malachite_base::test_util::generators::common::{GenConfig, GenMode}; +use malachite_base::test_util::generators::{ + unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, +}; +use malachite_base::test_util::runner::Runner; +use malachite_float::test_util::constants::thue_morse_constant::*; +use malachite_float::ComparableFloat; +use malachite_float::Float; + +pub(crate) fn register(runner: &mut Runner) { + register_demo!(runner, demo_float_thue_morse_constant_prec_round); + register_demo!(runner, demo_float_thue_morse_constant_prec_round_debug); + register_demo!(runner, demo_float_thue_morse_constant_prec); + register_demo!(runner, demo_float_thue_morse_constant_prec_debug); + + register_bench!( + runner, + benchmark_float_thue_morse_constant_prec_round_algorithms + ); + register_bench!(runner, benchmark_float_thue_morse_constant_prec_algorithms); +} + +fn demo_float_thue_morse_constant_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { + for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() + .get(gm, config) + .take(limit) + { + println!( + "thue_morse_constant_prec_round({}, {}) = {:?}", + p, + rm, + Float::thue_morse_constant_prec_round(p, rm) + ); + } +} + +fn demo_float_thue_morse_constant_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() + .get(gm, config) + .take(limit) + { + let (tmc, o) = Float::thue_morse_constant_prec_round(p, rm); + println!( + "thue_morse_constant_prec_round({}, {}) = ({:#x}, {:?})", + p, + rm, + ComparableFloat(tmc), + o + ); + } +} + +fn demo_float_thue_morse_constant_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for p in unsigned_gen_var_11().get(gm, config).take(limit) { + println!( + "thue_morse_constant_prec({}) = {:?}", + p, + Float::thue_morse_constant_prec(p) + ); + } +} + +fn demo_float_thue_morse_constant_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for p in unsigned_gen_var_11().get(gm, config).take(limit) { + let (tmc, o) = Float::thue_morse_constant_prec(p); + println!( + "thue_morse_constant_prec({}) = ({:#x}, {:?})", + p, + ComparableFloat(tmc), + o + ); + } +} + +fn benchmark_float_thue_morse_constant_prec_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::thue_morse_constant_prec_round(u64, RoundingMode)", + BenchmarkType::Algorithms, + unsigned_rounding_mode_pair_gen_var_4().get(gm, config), + gm.name(), + limit, + file_name, + &pair_1_bucketer("prec"), + &mut [ + ("default", &mut |(p, rm)| { + no_out!(Float::thue_morse_constant_prec_round(p, rm)) + }), + ("naive", &mut |(p, rm)| { + no_out!(thue_morse_constant_prec_round_naive(p, rm)) + }), + ], + ); +} + +fn benchmark_float_thue_morse_constant_prec_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::thue_morse_constant_prec(u64)", + BenchmarkType::Algorithms, + unsigned_gen_var_11().get(gm, config), + gm.name(), + limit, + file_name, + &unsigned_direct_bucketer(), + &mut [ + ("default", &mut |p| { + no_out!(Float::thue_morse_constant_prec(p)) + }), + ("naive", &mut |p| { + no_out!(thue_morse_constant_prec_round_naive(p, Nearest)) + }), + ], + ); +} diff --git a/malachite-float/src/bin_util/demo_and_bench/conversion/from_integer.rs b/malachite-float/src/bin_util/demo_and_bench/conversion/from_integer.rs index 5b2b838f7..0e0cc22df 100644 --- a/malachite-float/src/bin_util/demo_and_bench/conversion/from_integer.rs +++ b/malachite-float/src/bin_util/demo_and_bench/conversion/from_integer.rs @@ -37,6 +37,10 @@ pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_from_integer_prec_round_debug); register_demo!(runner, demo_float_from_integer_prec_round_ref); register_demo!(runner, demo_float_from_integer_prec_round_ref_debug); + register_demo!(runner, demo_float_from_integer_min_prec); + register_demo!(runner, demo_float_from_integer_min_prec_debug); + register_demo!(runner, demo_float_from_integer_min_prec_ref); + register_demo!(runner, demo_float_from_integer_min_prec_ref_debug); register_bench!(runner, benchmark_float_from_integer_evaluation_strategy); register_bench!(runner, benchmark_float_from_integer_library_comparison); @@ -53,6 +57,10 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_from_integer_prec_round_library_comparison ); + register_bench!( + runner, + benchmark_float_from_integer_min_prec_evaluation_strategy + ); } fn demo_float_from_integer(gm: GenMode, config: &GenConfig, limit: usize) { @@ -208,6 +216,46 @@ fn demo_float_from_integer_prec_round_ref_debug(gm: GenMode, config: &GenConfig, } } +fn demo_float_from_integer_min_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for n in integer_gen().get(gm, config).take(limit) { + println!( + "Float::from_integer_min_prec({}) = {}", + n.clone(), + Float::from_integer_min_prec(n) + ); + } +} + +fn demo_float_from_integer_min_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for n in integer_gen().get(gm, config).take(limit) { + println!( + "Float::from_integer_min_prec({:#x}) = {:#x}", + n.clone(), + ComparableFloat(Float::from_integer_min_prec(n)) + ); + } +} + +fn demo_float_from_integer_min_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for n in integer_gen().get(gm, config).take(limit) { + println!( + "Float::from_integer_min_prec_ref(&{}) = {}", + n, + Float::from_integer_min_prec_ref(&n) + ); + } +} + +fn demo_float_from_integer_min_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for n in integer_gen().get(gm, config).take(limit) { + println!( + "Float::from_integer_min_prec_ref(&{:#x}) = {:#x}", + n, + ComparableFloat(Float::from_integer_min_prec_ref(&n)) + ); + } +} + #[allow(unused_must_use)] fn benchmark_float_from_integer_evaluation_strategy( gm: GenMode, @@ -367,3 +415,28 @@ fn benchmark_float_from_integer_prec_round_library_comparison( ], ); } + +fn benchmark_float_from_integer_min_prec_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::from_integer_min_prec(Integer)", + BenchmarkType::EvaluationStrategy, + integer_gen().get(gm, config), + gm.name(), + limit, + file_name, + &integer_bit_bucketer("n"), + &mut [ + ("Float::from(Integer)", &mut |n| { + no_out!(Float::from_integer_min_prec(n)) + }), + ("Float::from(&Integer)", &mut |n| { + no_out!(Float::from_integer_min_prec_ref(&n)) + }), + ], + ); +} diff --git a/malachite-float/src/bin_util/demo_and_bench/conversion/from_natural.rs b/malachite-float/src/bin_util/demo_and_bench/conversion/from_natural.rs index f1ff07f05..30eb149b1 100644 --- a/malachite-float/src/bin_util/demo_and_bench/conversion/from_natural.rs +++ b/malachite-float/src/bin_util/demo_and_bench/conversion/from_natural.rs @@ -37,6 +37,10 @@ pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_from_natural_prec_round_debug); register_demo!(runner, demo_float_from_natural_prec_round_ref); register_demo!(runner, demo_float_from_natural_prec_round_ref_debug); + register_demo!(runner, demo_float_from_natural_min_prec); + register_demo!(runner, demo_float_from_natural_min_prec_debug); + register_demo!(runner, demo_float_from_natural_min_prec_ref); + register_demo!(runner, demo_float_from_natural_min_prec_ref_debug); register_bench!(runner, benchmark_float_from_natural_evaluation_strategy); register_bench!(runner, benchmark_float_from_natural_library_comparison); @@ -53,6 +57,10 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_from_natural_prec_round_library_comparison ); + register_bench!( + runner, + benchmark_float_from_natural_min_prec_evaluation_strategy + ); } fn demo_float_from_natural(gm: GenMode, config: &GenConfig, limit: usize) { @@ -208,6 +216,46 @@ fn demo_float_from_natural_prec_round_ref_debug(gm: GenMode, config: &GenConfig, } } +fn demo_float_from_natural_min_prec(gm: GenMode, config: &GenConfig, limit: usize) { + for n in natural_gen().get(gm, config).take(limit) { + println!( + "Float::from_natural_min_prec({}) = {}", + n.clone(), + Float::from_natural_min_prec(n) + ); + } +} + +fn demo_float_from_natural_min_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for n in natural_gen().get(gm, config).take(limit) { + println!( + "Float::from_natural_min_prec({:#x}) = {:#x}", + n.clone(), + ComparableFloat(Float::from_natural_min_prec(n)) + ); + } +} + +fn demo_float_from_natural_min_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { + for n in natural_gen().get(gm, config).take(limit) { + println!( + "Float::from_natural_min_prec_ref(&{}) = {}", + n, + Float::from_natural_min_prec_ref(&n) + ); + } +} + +fn demo_float_from_natural_min_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for n in natural_gen().get(gm, config).take(limit) { + println!( + "Float::from_natural_min_prec_ref(&{:#x}) = {:#x}", + n, + ComparableFloat(Float::from_natural_min_prec_ref(&n)) + ); + } +} + #[allow(unused_must_use)] fn benchmark_float_from_natural_evaluation_strategy( gm: GenMode, @@ -367,3 +415,28 @@ fn benchmark_float_from_natural_prec_round_library_comparison( ], ); } + +fn benchmark_float_from_natural_min_prec_evaluation_strategy( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::from_natural_min_prec(Natural)", + BenchmarkType::EvaluationStrategy, + natural_gen().get(gm, config), + gm.name(), + limit, + file_name, + &natural_bit_bucketer("n"), + &mut [ + ("Float::from(Natural)", &mut |n| { + no_out!(Float::from_natural_min_prec(n)) + }), + ("Float::from(&Natural)", &mut |n| { + no_out!(Float::from_natural_min_prec_ref(&n)) + }), + ], + ); +} diff --git a/malachite-float/src/bin_util/demo_and_bench/conversion/from_primitive_int.rs b/malachite-float/src/bin_util/demo_and_bench/conversion/from_primitive_int.rs index 877e4b03a..c1ef3a8c4 100644 --- a/malachite-float/src/bin_util/demo_and_bench/conversion/from_primitive_int.rs +++ b/malachite-float/src/bin_util/demo_and_bench/conversion/from_primitive_int.rs @@ -10,13 +10,14 @@ use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::{ - pair_primitive_int_bit_u64_max_bucketer, signed_bit_bucketer, + pair_1_bit_bucketer, pair_primitive_int_bit_u64_max_bucketer, signed_bit_bucketer, triple_1_2_primitive_int_bit_u64_max_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ - signed_gen, signed_unsigned_pair_gen_var_20, unsigned_gen, unsigned_pair_gen_var_32, + signed_gen, signed_pair_gen_var_2, signed_unsigned_pair_gen_var_20, unsigned_gen, + unsigned_pair_gen_var_32, unsigned_signed_pair_gen_var_1, }; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; @@ -40,6 +41,13 @@ pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_from_unsigned_prec_debug); register_unsigned_demos!(runner, demo_float_from_unsigned_prec_round); register_unsigned_demos!(runner, demo_float_from_unsigned_prec_round_debug); + register_demo!(runner, demo_float_const_from_unsigned); + register_demo!(runner, demo_float_const_from_unsigned_debug); + register_demo!(runner, demo_float_const_from_unsigned_times_power_of_2); + register_demo!( + runner, + demo_float_const_from_unsigned_times_power_of_2_debug + ); register_signed_demos!(runner, demo_float_from_signed); register_signed_demos!(runner, demo_float_from_signed_debug); @@ -47,6 +55,10 @@ pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_float_from_signed_prec_debug); register_signed_demos!(runner, demo_float_from_signed_prec_round); register_signed_demos!(runner, demo_float_from_signed_prec_round_debug); + register_demo!(runner, demo_float_const_from_signed); + register_demo!(runner, demo_float_const_from_signed_debug); + register_demo!(runner, demo_float_const_from_signed_times_power_of_2); + register_demo!(runner, demo_float_const_from_signed_times_power_of_2_debug); register_unsigned_benches!(runner, benchmark_float_from_unsigned_library_comparison); register_unsigned_benches!( @@ -57,6 +69,8 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_from_unsigned_prec_round_library_comparison ); + register_bench!(runner, benchmark_float_const_from_unsigned); + register_bench!(runner, benchmark_float_const_from_unsigned_times_power_of_2); register_signed_benches!(runner, benchmark_float_from_signed_library_comparison); register_signed_benches!(runner, benchmark_float_from_signed_prec_library_comparison); @@ -64,6 +78,8 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_from_signed_prec_round_library_comparison ); + register_bench!(runner, benchmark_float_const_from_signed); + register_bench!(runner, benchmark_float_const_from_signed_times_power_of_2); } fn demo_float_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) @@ -176,6 +192,52 @@ fn demo_float_from_unsigned_prec_round_debug( } } +fn demo_float_const_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { + for n in unsigned_gen().get(gm, config).take(limit) { + println!( + "Float::const_from_unsigned({}) = {}", + n, + Float::const_from_unsigned(n) + ); + } +} + +fn demo_float_const_from_unsigned_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for n in unsigned_gen().get(gm, config).take(limit) { + println!( + "Float::const_from_unsigned({:#x}) = {:#x}", + n, + ComparableFloat(Float::const_from_unsigned(n)) + ); + } +} + +fn demo_float_const_from_unsigned_times_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { + for (n, pow) in unsigned_signed_pair_gen_var_1().get(gm, config).take(limit) { + println!( + "Float::const_from_unsigned_times_power_of_2({}, {}) = {}", + n, + pow, + Float::const_from_unsigned_times_power_of_2(n, pow) + ); + } +} + +fn demo_float_const_from_unsigned_times_power_of_2_debug( + gm: GenMode, + config: &GenConfig, + limit: usize, +) { + for (n, pow) in unsigned_signed_pair_gen_var_1().get(gm, config).take(limit) { + println!( + "Float::const_from_unsigned_times_power_of_2({:#x}, {}) = {:#x}", + n, + pow, + Float::const_from_unsigned_times_power_of_2(n, pow) + ); + } +} + fn demo_float_from_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: From, @@ -280,6 +342,52 @@ fn demo_float_from_signed_prec_round_debug( } } +fn demo_float_const_from_signed(gm: GenMode, config: &GenConfig, limit: usize) { + for n in signed_gen().get(gm, config).take(limit) { + println!( + "Float::const_from_signed({}) = {}", + n, + Float::const_from_signed(n) + ); + } +} + +fn demo_float_const_from_signed_debug(gm: GenMode, config: &GenConfig, limit: usize) { + for n in signed_gen().get(gm, config).take(limit) { + println!( + "Float::const_from_signed({:#x}) = {:#x}", + n, + ComparableFloat(Float::const_from_signed(n)) + ); + } +} + +fn demo_float_const_from_signed_times_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { + for (n, pow) in signed_pair_gen_var_2().get(gm, config).take(limit) { + println!( + "Float::const_from_signed_times_power_of_2({}, {}) = {}", + n, + pow, + Float::const_from_signed_times_power_of_2(n, pow) + ); + } +} + +fn demo_float_const_from_signed_times_power_of_2_debug( + gm: GenMode, + config: &GenConfig, + limit: usize, +) { + for (n, pow) in signed_pair_gen_var_2().get(gm, config).take(limit) { + println!( + "Float::const_from_signed_times_power_of_2({:#x}, {}) = {:#x}", + n, + pow, + Float::const_from_signed_times_power_of_2(n, pow) + ); + } +} + #[allow(unused_must_use)] fn benchmark_float_from_unsigned_library_comparison( gm: GenMode, @@ -375,6 +483,44 @@ fn benchmark_float_from_unsigned_prec_round_library_comparison( gm: GenMode, @@ -469,3 +615,41 @@ fn benchmark_float_from_signed_prec_round_library_comparison ], ); } + +fn benchmark_float_const_from_signed( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::const_from_signed(Limb)", + BenchmarkType::Single, + signed_gen().get(gm, config), + gm.name(), + limit, + file_name, + &signed_bit_bucketer(), + &mut [("Malachite", &mut |n| no_out!(Float::const_from_signed(n)))], + ); +} + +fn benchmark_float_const_from_signed_times_power_of_2( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::const_from_signed_times_power_of_2(Limb)", + BenchmarkType::Single, + signed_pair_gen_var_2().get(gm, config), + gm.name(), + limit, + file_name, + &pair_1_bit_bucketer("n"), + &mut [("Malachite", &mut |(n, pow)| { + no_out!(Float::const_from_signed_times_power_of_2(n, pow)) + })], + ); +} diff --git a/malachite-float/src/bin_util/demo_and_bench/conversion/from_rational.rs b/malachite-float/src/bin_util/demo_and_bench/conversion/from_rational.rs index 0385d959d..c4da99428 100644 --- a/malachite-float/src/bin_util/demo_and_bench/conversion/from_rational.rs +++ b/malachite-float/src/bin_util/demo_and_bench/conversion/from_rational.rs @@ -10,6 +10,10 @@ use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom}; use malachite_base::test_util::bench::{run_benchmark, BenchmarkType}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; +use malachite_float::conversion::from_rational::{ + from_rational_prec_round_direct, from_rational_prec_round_ref_direct, + from_rational_prec_round_ref_using_div, from_rational_prec_round_using_div, +}; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; use malachite_float::test_util::generators::{ rational_unsigned_rounding_mode_triple_gen_var_1, @@ -48,6 +52,11 @@ pub(crate) fn register(runner: &mut Runner) { runner, benchmark_float_from_rational_prec_round_evaluation_strategy ); + register_bench!(runner, benchmark_float_from_rational_prec_round_algorithms); + register_bench!( + runner, + benchmark_float_from_rational_prec_round_ref_algorithms + ); register_bench!( runner, benchmark_float_from_rational_prec_round_library_comparison @@ -303,6 +312,62 @@ fn benchmark_float_from_rational_prec_round_evaluation_strategy( ); } +fn benchmark_float_from_rational_prec_round_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::from_rational_prec_round(Rational, u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + rational_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), + &mut [ + ("default", &mut |(n, prec, rm)| { + no_out!(Float::from_rational_prec_round(n, prec, rm)) + }), + ("direct", &mut |(n, prec, rm)| { + no_out!(from_rational_prec_round_direct(n, prec, rm)) + }), + ("using div", &mut |(n, prec, rm)| { + no_out!(from_rational_prec_round_using_div(n, prec, rm)) + }), + ], + ); +} + +fn benchmark_float_from_rational_prec_round_ref_algorithms( + gm: GenMode, + config: &GenConfig, + limit: usize, + file_name: &str, +) { + run_benchmark( + "Float::from_rational_prec_round_ref(&Rational, u64, RoundingMode)", + BenchmarkType::EvaluationStrategy, + rational_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), + gm.name(), + limit, + file_name, + &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), + &mut [ + ("default", &mut |(n, prec, rm)| { + no_out!(Float::from_rational_prec_round_ref(&n, prec, rm)) + }), + ("direct", &mut |(n, prec, rm)| { + no_out!(from_rational_prec_round_ref_direct(&n, prec, rm)) + }), + ("using div", &mut |(n, prec, rm)| { + no_out!(from_rational_prec_round_ref_using_div(&n, prec, rm)) + }), + ], + ); +} + fn benchmark_float_from_rational_prec_round_library_comparison( gm: GenMode, config: &GenConfig, diff --git a/malachite-float/src/bin_util/demo_and_bench/mod.rs b/malachite-float/src/bin_util/demo_and_bench/mod.rs index d526df23d..428afc9b8 100644 --- a/malachite-float/src/bin_util/demo_and_bench/mod.rs +++ b/malachite-float/src/bin_util/demo_and_bench/mod.rs @@ -12,10 +12,12 @@ pub(crate) fn register(runner: &mut Runner) { arithmetic::register(runner); basic::register(runner); comparison::register(runner); + constants::register(runner); conversion::register(runner); } mod arithmetic; mod basic; mod comparison; +mod constants; mod conversion; diff --git a/malachite-float/src/constants/mod.rs b/malachite-float/src/constants/mod.rs new file mode 100644 index 000000000..c051ff711 --- /dev/null +++ b/malachite-float/src/constants/mod.rs @@ -0,0 +1,14 @@ +// 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 . + +/// Functions for approximating the prime constant (the constant whose $n$th bit is 1 if and only if +/// $n$ is prime). +pub mod prime_constant; +/// Functions for approximating the Thue-Morse constant (the constant whose bits are the Thue-Morse +/// sequence). +pub mod thue_morse_constant; diff --git a/malachite-float/src/constants/prime_constant.rs b/malachite-float/src/constants/prime_constant.rs new file mode 100644 index 000000000..37d4eaf6c --- /dev/null +++ b/malachite-float/src/constants/prime_constant.rs @@ -0,0 +1,116 @@ +// 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 crate::Float; +use core::cmp::Ordering; +use malachite_base::num::factorization::primes::prime_indicator_sequence_less_than_or_equal_to; +use malachite_base::rounding_modes::RoundingMode::{self, *}; + +impl Float { + /// Returns an approximation to the prime constant, with the given precision and rounded using + /// the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded + /// value is less than or greater than the exact value of the constant. (Since the constant is + /// irrational, the rounded value is never equal to the exact value.) + /// + /// The prime constant is the real number whose $n$th bit is prime if and only if $n$ is prime. + /// That is, + /// $$ + /// P = \sum_{p\ text{prime}\}2^{-p}. + /// $$ + /// + /// The constant is irrational. + /// + /// The output has precision `prec`. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero or if `rm` is `Exact`. + /// + /// # Examples + /// ``` + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (pc, o) = Float::prime_constant_prec_round(100, Floor); + /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221542"); + /// assert_eq!(o, Less); + /// + /// let (pc, o) = Float::prime_constant_prec_round(100, Ceiling); + /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221546"); + /// assert_eq!(o, Greater); + /// ``` + pub fn prime_constant_prec_round(prec: u64, rm: RoundingMode) -> (Float, Ordering) { + // Strictly speaking, this call violates the preconditions for + // `non_dyadic_from_bits_prec_round`, because the iterator passed in is finite. But since we + // know exactly how many bits `non_dyadic_from_bits_prec_round` will read, we can get away + // with this. + Float::non_dyadic_from_bits_prec_round( + prime_indicator_sequence_less_than_or_equal_to(if rm == Nearest { + prec + 2 + } else { + prec + 1 + }), + prec, + rm, + ) + } + + /// Returns an approximation to the prime constant, with the given precision and rounded to the + /// nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether + /// the rounded value is less than or greater than the exact value of the constant. (Since the + /// constant is irrational, the rounded value is never equal to the exact value.) + /// + /// The prime constant is the real number whose $n$th bit is prime if and only if $n$ is prime. + /// That is, + /// $$ + /// P = \sum_{p\ text{prime}\}2^{-p}. + /// $$ + /// + /// The constant is irrational. + /// + /// The output has precision `prec`. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (pc, o) = Float::prime_constant_prec(1); + /// assert_eq!(pc.to_string(), "0.5"); + /// assert_eq!(o, Greater); + /// + /// let (pc, o) = Float::prime_constant_prec(10); + /// assert_eq!(pc.to_string(), "0.4146"); + /// assert_eq!(o, Less); + /// + /// let (pc, o) = Float::prime_constant_prec(100); + /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221542"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn prime_constant_prec(prec: u64) -> (Float, Ordering) { + Float::prime_constant_prec_round(prec, Nearest) + } +} diff --git a/malachite-float/src/constants/thue_morse_constant.rs b/malachite-float/src/constants/thue_morse_constant.rs new file mode 100644 index 000000000..7f6dda262 --- /dev/null +++ b/malachite-float/src/constants/thue_morse_constant.rs @@ -0,0 +1,183 @@ +// 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 crate::Float; +use crate::InnerFloat::Finite; +use alloc::vec; +use core::cmp::Ordering::{self, *}; +use malachite_base::iterators::thue_morse_sequence; +use malachite_base::num::arithmetic::traits::{NegModPowerOf2, PowerOf2, ShrRound}; +use malachite_base::num::basic::integers::PrimitiveInt; +use malachite_base::num::basic::traits::OneHalf; +use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_nz::natural::Natural; +use malachite_nz::platform::Limb; + +#[cfg(feature = "32_bit_limbs")] +const LIMB_0: Limb = 0xd32d2cd2; +#[cfg(feature = "32_bit_limbs")] +const LIMB_1: Limb = 0x2cd2d32c; + +#[cfg(not(feature = "32_bit_limbs"))] +const LIMB_0: Limb = 0xd32d2cd32cd2d32c; +#[cfg(not(feature = "32_bit_limbs"))] +const LIMB_1: Limb = 0x2cd2d32cd32d2cd2; + +impl Float { + /// Returns an approximation to the Thue-Morse constant, with the given precision and rounded + /// using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the + /// rounded value is less than or greater than the exact value of the constant. (Since the + /// constant is irrational, the rounded value is never equal to the exact value.) + /// + /// The Thue-Morse constant is the real number whose bits are the Thue-Morse sequence. That is, + /// $$ + /// \tau = \sum_{k=0}^\infty\frac{t_n}{2^{n+1}}, + /// $$ + /// where $t_n$ is the Thue-Morse sequence. + /// + /// An alternative expression, from , is + /// $$ + /// \tau = \frac{1}{4}\left[2-\prod_{k=0}^\infty\left(1-\frac{1}{2^{2^k}}\right)\right]. + /// $$ + /// + /// The constant is irrational and transcendental. + /// + /// The output has precision `prec`. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero or if `rm` is `Exact`. + /// + /// # Examples + /// ``` + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (tmc, o) = Float::thue_morse_constant_prec_round(100, Floor); + /// assert_eq!(tmc.to_string(), "0.4124540336401075977833613682584"); + /// assert_eq!(o, Less); + /// + /// let (tmc, o) = Float::thue_morse_constant_prec_round(100, Ceiling); + /// assert_eq!(tmc.to_string(), "0.4124540336401075977833613682588"); + /// assert_eq!(o, Greater); + /// ``` + pub fn thue_morse_constant_prec_round(prec: u64, rm: RoundingMode) -> (Float, Ordering) { + assert_ne!(prec, 0); + assert_ne!(rm, Exact); + // If the result is 1/2 then the exponent is 0 rather than -1, so we handle that case + // separately. + if prec == 1 && (rm == Nearest || rm == Ceiling || rm == Up) { + return (Float::ONE_HALF, Greater); + } else if prec == 2 && (rm == Ceiling || rm == Up) { + // TODO implement const_from_unsigned_prec_times_power_of_2 + return (Float::one_half_prec(2), Greater); + } + let len = usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0); + let mut limbs = vec![0; len]; + let mut tms = thue_morse_sequence(); + for (i, b) in (0..len).rev().zip(&mut tms) { + limbs[i] = if b { + limbs[i + 1] |= 1; + LIMB_1 + } else { + LIMB_0 + }; + } + let lsb = Limb::power_of_2(prec.neg_mod_power_of_2(Limb::LOG_WIDTH)); + let mut next_tms = false; + if lsb == 1 { + next_tms = tms.next().unwrap(); + if next_tms { + limbs[0] |= 1; + } + } + let increment = match rm { + Up | Ceiling | Exact => true, // Exact never happens + Down | Floor => false, + Nearest => match lsb { + 1 => !next_tms, + 2 => tms.next().unwrap(), + _ => limbs[0] & (lsb >> 1) != 0, + }, + }; + limbs[0] &= !(lsb - 1); + let mut significand = Natural::from_owned_limbs_asc(limbs); + if increment { + significand += Natural::from(lsb); + } + ( + Float(Finite { + sign: true, + exponent: -1, + precision: prec, + significand, + }), + if increment { Greater } else { Less }, + ) + } + + /// Returns an approximation to the Thue-Morse constant, with the given precision and rounded to + /// the nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating + /// whether the rounded value is less than or greater than the exact value of the constant. + /// (Since the constant is irrational, the rounded value is never equal to the exact value.) + /// + /// The Thue-Morse constant is the real number whose bits are the Thue-Morse sequence. That is, + /// $$ + /// \tau = \sum_{k=0}^\infty\frac{t_n}{2^{n+1}}, + /// $$ + /// where $t_n$ is the Thue-Morse sequence. + /// + /// An alternative expression, from , is + /// $$ + /// \tau = \frac{1}{4}\left[2-\prod_{k=0}^\infty\left(1-\frac{1}{2^{2^k}}\right)\right]. + /// $$ + /// + /// The constant is irrational and transcendental. + /// + /// The output has precision `prec`. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// let (tmc, o) = Float::thue_morse_constant_prec(1); + /// assert_eq!(tmc.to_string(), "0.5"); + /// assert_eq!(o, Greater); + /// + /// let (tmc, o) = Float::thue_morse_constant_prec(10); + /// assert_eq!(tmc.to_string(), "0.4126"); + /// assert_eq!(o, Greater); + /// + /// let (tmc, o) = Float::thue_morse_constant_prec(100); + /// assert_eq!(tmc.to_string(), "0.4124540336401075977833613682584"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn thue_morse_constant_prec(prec: u64) -> (Float, Ordering) { + Float::thue_morse_constant_prec_round(prec, Nearest) + } +} diff --git a/malachite-float/src/conversion/from_bits.rs b/malachite-float/src/conversion/from_bits.rs new file mode 100644 index 000000000..1ef351891 --- /dev/null +++ b/malachite-float/src/conversion/from_bits.rs @@ -0,0 +1,262 @@ +// 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 crate::Float; +use crate::InnerFloat::Finite; +use alloc::vec; +use core::cmp::Ordering::{self, *}; +use malachite_base::num::arithmetic::traits::{ + DivisibleByPowerOf2, NegModPowerOf2, PowerOf2, ShrRound, +}; +use malachite_base::num::basic::integers::PrimitiveInt; +use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::num::logic::traits::SignificantBits; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_nz::natural::Natural; +use malachite_nz::platform::Limb; + +const HIGH_BIT: Limb = 1 << (Limb::WIDTH - 1); + +impl Float { + /// Returns an approximation of a real number, given the number's bits. To avoid troublesome + /// edge cases, the number should not be a dyadic rational (and the iterator of bits should + /// therefore be infinite, and not eventually 0 or 1). Given this assumption, the rounding mode + /// `Exact` should never be passed. + /// + /// The approximation has precision `prec` and is rounded according to the provided rounding + /// mode. + /// + /// This function reads `prec + z` bits, or `prec + z + 1` bits if `rm` is `Nearest`, where `z` + /// is the number of leading false bits in `bits`. + /// + /// $$ + /// f((x_k),p,m) = C+\varepsilon, + /// $$ + /// where + /// $$ + /// C=\sum_{k=0}^\infty x_k 2^{-(k+1)}. + /// $$ + /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p+1}$. + /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p}$. + /// + /// The output has precision `prec`. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero or `rm` is `Exact`. + /// + /// # Examples + /// ``` + /// use malachite_base::rounding_modes::RoundingMode::*; + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// // Produces 10100100010000100000... + /// struct Bits { + /// b: bool, + /// k: usize, + /// j: usize, + /// } + /// + /// impl Iterator for Bits { + /// type Item = bool; + /// + /// fn next(&mut self) -> Option { + /// Some(if self.b { + /// self.b = false; + /// self.j = self.k; + /// true + /// } else { + /// self.j -= 1; + /// if self.j == 0 { + /// self.k += 1; + /// self.b = true; + /// } + /// false + /// }) + /// } + /// } + /// + /// impl Bits { + /// fn new() -> Bits { + /// Bits { + /// b: true, + /// k: 1, + /// j: 1, + /// } + /// } + /// } + /// + /// let (c, o) = Float::non_dyadic_from_bits_prec_round(Bits::new(), 100, Floor); + /// assert_eq!(c.to_string(), "0.6416325606551538662938427702254"); + /// assert_eq!(o, Less); + /// + /// let (c, o) = Float::non_dyadic_from_bits_prec_round(Bits::new(), 100, Ceiling); + /// assert_eq!(c.to_string(), "0.641632560655153866293842770226"); + /// assert_eq!(o, Greater); + /// ``` + pub fn non_dyadic_from_bits_prec_round>( + mut bits: I, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + assert_ne!(prec, 0); + assert_ne!(rm, Exact); + let len = usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0); + let mut limbs = vec![0; len]; + let mut limbs_it = limbs.iter_mut().rev(); + let mut x = limbs_it.next().unwrap(); + let mut mask = HIGH_BIT; + let mut seen_one = false; + let mut exponent: i32 = 0; + let mut remaining = prec; + for b in &mut bits { + if !seen_one { + if b { + seen_one = true; + } else { + exponent = exponent.checked_sub(1).unwrap(); + continue; + } + } + if b { + *x |= mask; + } + remaining -= 1; + if remaining == 0 { + break; + } + if mask == 1 { + x = limbs_it.next().unwrap(); + mask = HIGH_BIT; + } else { + mask >>= 1; + } + } + let mut significand = Natural::from_owned_limbs_asc(limbs); + let increment = rm == Up || rm == Ceiling || (rm == Nearest && bits.next() == Some(true)); + if increment { + significand += + Natural::from(Limb::power_of_2(prec.neg_mod_power_of_2(Limb::LOG_WIDTH))); + if !significand + .significant_bits() + .divisible_by_power_of_2(Limb::LOG_WIDTH) + { + significand >>= 1; + exponent += 1; + } + } + ( + Float(Finite { + sign: true, + exponent, + precision: prec, + significand, + }), + if increment { Greater } else { Less }, + ) + } + + /// Returns an approximation of a real number, given the number's bits. To avoid troublesome + /// edge cases, the number should not be a dyadic rational (and the iterator of bits should + /// therefore be infinite, and not eventually 0 or 1). + /// + /// The approximation has precision `prec` and is rounded according to the `Nearest` rounding + /// mode. + /// + /// This function reads `prec + z + 1` bits, where `z` is the number of leading false bits in + /// `bits`. + /// + /// $$ + /// f((x_k),p,m) = C+\varepsilon, + /// $$ + /// where + /// $$ + /// C=\sum_{k=0}^\infty x_k 2^{-(k+1)} + /// $$ + /// and $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p}$. + /// + /// The output has precision `prec`. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(n)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. + /// + /// # Panics + /// Panics if `prec` is zero. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// use std::cmp::Ordering::*; + /// + /// // Produces 10100100010000100000... + /// struct Bits { + /// b: bool, + /// k: usize, + /// j: usize, + /// } + /// + /// impl Iterator for Bits { + /// type Item = bool; + /// + /// fn next(&mut self) -> Option { + /// Some(if self.b { + /// self.b = false; + /// self.j = self.k; + /// true + /// } else { + /// self.j -= 1; + /// if self.j == 0 { + /// self.k += 1; + /// self.b = true; + /// } + /// false + /// }) + /// } + /// } + /// + /// impl Bits { + /// fn new() -> Bits { + /// Bits { + /// b: true, + /// k: 1, + /// j: 1, + /// } + /// } + /// } + /// + /// let (c, o) = Float::non_dyadic_from_bits_prec(Bits::new(), 1); + /// assert_eq!(c.to_string(), "0.5"); + /// assert_eq!(o, Less); + /// + /// let (c, o) = Float::non_dyadic_from_bits_prec(Bits::new(), 10); + /// assert_eq!(c.to_string(), "0.642"); + /// assert_eq!(o, Less); + /// + /// let (c, o) = Float::non_dyadic_from_bits_prec(Bits::new(), 100); + /// assert_eq!(c.to_string(), "0.6416325606551538662938427702254"); + /// assert_eq!(o, Less); + /// ``` + #[inline] + pub fn non_dyadic_from_bits_prec>( + bits: I, + prec: u64, + ) -> (Float, Ordering) { + Float::non_dyadic_from_bits_prec_round(bits, prec, Nearest) + } +} diff --git a/malachite-float/src/conversion/from_integer.rs b/malachite-float/src/conversion/from_integer.rs index 6a22b3db0..2ffc0c6f6 100644 --- a/malachite-float/src/conversion/from_integer.rs +++ b/malachite-float/src/conversion/from_integer.rs @@ -21,11 +21,12 @@ impl Float { /// If you're only using [`Nearest`], try using [`Float::from_integer_prec`] instead. /// /// # Worst-case complexity - /// $T(n) = O(n)$ + /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. + /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is + /// `prec`. /// /// # Examples /// ``` @@ -92,11 +93,12 @@ impl Float { /// as well as a precision, try [`Float::from_integer_prec_round`]. /// /// # Worst-case complexity - /// $T(n) = O(n)$ + /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. + /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is + /// `prec`. /// /// # Examples /// ``` @@ -142,11 +144,12 @@ impl Float { /// If you're only using [`Nearest`], try using [`Float::from_integer_prec_ref`] instead. /// /// # Worst-case complexity - /// $T(n) = O(n)$ + /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. + /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is + /// `prec`. /// /// # Examples /// ``` @@ -221,11 +224,12 @@ impl Float { /// as well as a precision, try [`Float::from_integer_prec_round_ref`]. /// /// # Worst-case complexity - /// $T(n) = O(n)$ + /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. + /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is + /// `prec`. /// /// # Examples /// ``` @@ -268,15 +272,122 @@ impl Float { (-f, o.reverse()) } } + + /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by value. + /// + /// If the [`Integer`] is nonzero, the precision of the [`Float`] is the minimum possible + /// precision to represent the [`Integer`] exactly. If you instead want to use the precision + /// equal to the [`Integer`]'s number of significant bits, try `from`. If you want to specify + /// some other precision, try [`Float::from_integer_prec`]. This may require rounding, which + /// uses [`Nearest`] by default. To specify a rounding mode as well as a precision, try + /// [`Float::from_integer_prec_round`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(1)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `n.significant_bits()`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::Zero; + /// use malachite_float::Float; + /// use malachite_nz::integer::Integer; + /// + /// assert_eq!( + /// Float::from_integer_min_prec(Integer::ZERO).to_string(), + /// "0.0" + /// ); + /// assert_eq!( + /// Float::from_integer_min_prec(Integer::from(100)).to_string(), + /// "100.0" + /// ); + /// assert_eq!( + /// Float::from_integer_min_prec(Integer::from(100)).get_prec(), + /// Some(5) + /// ); + /// assert_eq!( + /// Float::from_integer_min_prec(Integer::from(-100)).to_string(), + /// "-100.0" + /// ); + /// assert_eq!( + /// Float::from_integer_min_prec(Integer::from(-100)).get_prec(), + /// Some(5) + /// ); + /// ``` + pub fn from_integer_min_prec(x: Integer) -> Float { + let sign = x >= 0; + let abs = Float::from_natural_min_prec(x.unsigned_abs()); + if sign { + abs + } else { + -abs + } + } + + /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by reference. + /// + /// If the [`Integer`] is nonzero, the precision of the [`Float`] is the minimum possible + /// precision to represent the [`Integer`] exactly. If you instead want to use the precision + /// equal to the [`Integer`]'s number of significant bits, try `from`. If you want to specify + /// some other precision, try [`Float::from_integer_prec_ref`]. This may require rounding, which + /// uses [`Nearest`] by default. To specify a rounding mode as well as a precision, try + /// [`Float::from_integer_prec_round_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(1)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `n.significant_bits()`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::Zero; + /// use malachite_float::Float; + /// use malachite_nz::integer::Integer; + /// + /// assert_eq!( + /// Float::from_integer_min_prec_ref(&Integer::ZERO).to_string(), + /// "0.0" + /// ); + /// assert_eq!( + /// Float::from_integer_min_prec_ref(&Integer::from(100)).to_string(), + /// "100.0" + /// ); + /// assert_eq!( + /// Float::from_integer_min_prec_ref(&Integer::from(100)).get_prec(), + /// Some(5) + /// ); + /// assert_eq!( + /// Float::from_integer_min_prec_ref(&Integer::from(-100)).to_string(), + /// "-100.0" + /// ); + /// assert_eq!( + /// Float::from_integer_min_prec_ref(&Integer::from(-100)).get_prec(), + /// Some(5) + /// ); + /// ``` + pub fn from_integer_min_prec_ref(x: &Integer) -> Float { + let abs = Float::from_natural_min_prec_ref(x.unsigned_abs_ref()); + if *x >= 0 { + abs + } else { + -abs + } + } } impl From for Float { /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by value. /// /// If the [`Integer`] is nonzero, the precision of the [`Float`] is equal to the [`Integer`]'s - /// number of significant bits. If you want to specify a different precision, try - /// [`Float::from_integer_prec`]. This may require rounding, which uses [`Nearest`] by default. - /// To specify a rounding mode as well as a precision, try [`Float::from_integer_prec_round`]. + /// number of significant bits. If you instead want to use the minimum possible precision to + /// represent the [`Integer`] exactly, try [`Float::from_integer_min_prec`]. If you want to + /// specify some other precision, try [`Float::from_integer_prec`]. This may require rounding, + /// which uses [`Nearest`] by default. To specify a rounding mode as well as a precision, try + /// [`Float::from_integer_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ @@ -312,10 +423,11 @@ impl<'a> From<&'a Integer> for Float { /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by reference. /// /// If the [`Integer`] is nonzero, the precision of the [`Float`] is equal to the [`Integer`]'s - /// number of significant bits. If you want to specify a different precision, try - /// [`Float::from_integer_prec_ref`]. This may require rounding, which uses [`Nearest`] by - /// default. To specify a rounding mode as well as a precision, try - /// [`Float::from_integer_prec_round_ref`]. + /// number of significant bits. If you instead want to use the minimum possible precision to + /// represent the [`Integer`] exactly, try [`Float::from_integer_min_prec_ref`]. If you want to + /// specify some other precision, try [`Float::from_integer_prec_ref`]. This may require + /// rounding, which uses [`Nearest`] by default. To specify a rounding mode as well as a + /// precision, try [`Float::from_integer_prec_round_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ diff --git a/malachite-float/src/conversion/from_natural.rs b/malachite-float/src/conversion/from_natural.rs index 78365a9b7..d974b5002 100644 --- a/malachite-float/src/conversion/from_natural.rs +++ b/malachite-float/src/conversion/from_natural.rs @@ -9,15 +9,144 @@ use crate::Float; use crate::InnerFloat::Finite; use core::cmp::Ordering::{self, *}; -use malachite_base::num::arithmetic::traits::NegModPowerOf2; +use malachite_base::num::arithmetic::traits::{ + DivisibleByPowerOf2, ModPowerOf2, NegModPowerOf2, PowerOf2, RoundToMultipleOfPowerOf2Assign, + SaturatingSubAssign, ShrRound, +}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; -use malachite_base::num::logic::traits::SignificantBits; +use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; +fn from_natural_prec_round_helper( + x: &Natural, + prec: u64, + rm: RoundingMode, + bits: u64, +) -> (Float, Ordering) { + let mut needed_bits = prec; + let sig_bits_in_highest_limb = bits.mod_power_of_2(Limb::LOG_WIDTH); + let mut needed_limbs = 1; + needed_bits.saturating_sub_assign(sig_bits_in_highest_limb); + if needed_bits != 0 { + needed_limbs += needed_bits.shr_round(Limb::LOG_WIDTH, Ceiling).0; + } + let mut rev_limbs = x.limbs().rev(); + let mut significand = Natural::from_owned_limbs_desc( + (&mut rev_limbs) + .take(usize::exact_from(needed_limbs)) + .collect(), + ); + significand <<= significand + .significant_bits() + .neg_mod_power_of_2(Limb::LOG_WIDTH); + let mut mask_width = significand.significant_bits() - prec; + let mut erased_limb = 0; + if mask_width >= Limb::WIDTH { + erased_limb = significand.limbs()[0]; + significand >>= Limb::WIDTH; + mask_width -= Limb::WIDTH; + } + let mut exponent = i32::exact_from(bits); + let o = match rm { + Exact => { + let inexact = erased_limb != 0 + || !significand.divisible_by_power_of_2(mask_width) + || rev_limbs.any(|y| y != 0); + assert!(!inexact, "Inexact conversion from Natural"); + Equal + } + Floor | Down => { + let inexact = erased_limb != 0 + || !significand.divisible_by_power_of_2(mask_width) + || rev_limbs.any(|y| y != 0); + if inexact { + significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); + Less + } else { + Equal + } + } + Ceiling | Up => { + let inexact = erased_limb != 0 + || !significand.divisible_by_power_of_2(mask_width) + || rev_limbs.any(|y| y != 0); + if inexact { + let original_limb_count = significand.limb_count(); + significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); + significand += Natural::power_of_2(mask_width); + if significand.limb_count() > original_limb_count { + significand >>= 1; + exponent = exponent.checked_add(1).unwrap(); + } + Greater + } else { + Equal + } + } + Nearest => { + let half_bit = x.get_bit(bits - prec - 1); + let inexact_after_half = !x.divisible_by_power_of_2(bits - prec - 1); + let inexact = half_bit || inexact_after_half; + if half_bit && (inexact_after_half || x.get_bit(bits - prec)) { + let original_limb_count = significand.limb_count(); + significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); + significand += Natural::power_of_2(mask_width); + if significand.limb_count() > original_limb_count { + significand >>= 1; + exponent = exponent.checked_add(1).unwrap(); + } + Greater + } else if inexact { + significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); + Less + } else { + Equal + } + } + }; + ( + Float(Finite { + sign: true, + exponent, + precision: prec, + significand, + }), + o, + ) +} + +fn from_natural_prec_round_helper_no_round(x: &Natural, prec: u64, bits: u64) -> Float { + let mut needed_bits = prec; + let sig_bits_in_highest_limb = bits.mod_power_of_2(Limb::LOG_WIDTH); + let mut needed_limbs = 1; + needed_bits.saturating_sub_assign(sig_bits_in_highest_limb); + if needed_bits != 0 { + needed_limbs += needed_bits.shr_round(Limb::LOG_WIDTH, Ceiling).0; + } + let mut rev_limbs = x.limbs().rev(); + let mut significand = Natural::from_owned_limbs_desc( + (&mut rev_limbs) + .take(usize::exact_from(needed_limbs)) + .collect(), + ); + significand <<= significand + .significant_bits() + .neg_mod_power_of_2(Limb::LOG_WIDTH); + if significand.significant_bits() - prec >= Limb::WIDTH { + significand >>= Limb::WIDTH; + } + Float(Finite { + sign: true, + exponent: i32::exact_from(bits), + precision: prec, + significand, + }) +} + impl Float { /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by value. If the [`Float`] is /// nonzero, it has the specified precision. If rounding is needed, the specified rounding mode @@ -27,11 +156,12 @@ impl Float { /// If you're only using [`Nearest`], try using [`Float::from_natural_prec`] instead. /// /// # Worst-case complexity - /// $T(n) = O(n)$ + /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. + /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is + /// `prec`. /// /// # Examples /// ``` @@ -77,110 +207,115 @@ impl Float { (f, o) } - /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by value. If the [`Float`] is - /// nonzero, it has the specified precision. An [`Ordering`] is also returned, indicating - /// whether the returned value is less than, equal to, or greater than the original value. - /// - /// If you want the [`Float`]'s precision to be equal to the [`Natural`]'s number of significant - /// bits, try just using `Float::from` instead. + /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by reference. If the [`Float`] + /// is nonzero, it has the specified precision. If rounding is needed, the specified rounding + /// mode is used. An [`Ordering`] is also returned, indicating whether the returned value is + /// less than, equal to, or greater than the original value. /// - /// Rounding may occur, in which case [`Nearest`] is used by default. To specify a rounding mode - /// as well as a precision, try [`Float::from_natural_prec_round`]. + /// If you're only using [`Nearest`], try using [`Float::from_natural_prec_ref`] instead. /// /// # Worst-case complexity - /// $T(n) = O(n)$ + /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. + /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is + /// `prec`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; + /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use std::cmp::Ordering::*; /// - /// let (x, o) = Float::from_natural_prec(Natural::ZERO, 10); + /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::ZERO, 10, Exact); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// - /// let (x, o) = Float::from_natural_prec(Natural::from(123u32), 20); + /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 20, Exact); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// - /// let (x, o) = Float::from_natural_prec(Natural::from(123u32), 4); + /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 4, Floor); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); + /// + /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 4, Ceiling); + /// assert_eq!(x.to_string(), "1.3e2"); + /// assert_eq!(x.get_prec(), Some(4)); + /// assert_eq!(o, Greater); /// ``` #[inline] - pub fn from_natural_prec(x: Natural, prec: u64) -> (Float, Ordering) { - Float::from_natural_prec_round(x, prec, Nearest) + pub fn from_natural_prec_round_ref( + x: &Natural, + prec: u64, + rm: RoundingMode, + ) -> (Float, Ordering) { + assert_ne!(prec, 0); + if *x == 0u32 { + return (Float::ZERO, Equal); + } + let bits = x.significant_bits(); + if bits <= prec { + let mut f = Float(Finite { + sign: true, + exponent: i32::exact_from(bits), + precision: bits, + significand: x << bits.neg_mod_power_of_2(Limb::LOG_WIDTH), + }); + let o = f.set_prec_round(prec, rm); + (f, o) + } else { + from_natural_prec_round_helper(x, prec, rm, bits) + } } - /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by reference. If the [`Float`] - /// is nonzero, it has the specified precision. If rounding is needed, the specified rounding - /// mode is used. An [`Ordering`] is also returned, indicating whether the returned value is - /// less than, equal to, or greater than the original value. + /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by value. If the [`Float`] is + /// nonzero, it has the specified precision. An [`Ordering`] is also returned, indicating + /// whether the returned value is less than, equal to, or greater than the original value. /// - /// If you're only using [`Nearest`], try using [`Float::from_natural_prec_ref`] instead. + /// If you want the [`Float`]'s precision to be equal to the [`Natural`]'s number of significant + /// bits, try just using `Float::from` instead. + /// + /// Rounding may occur, in which case [`Nearest`] is used by default. To specify a rounding mode + /// as well as a precision, try [`Float::from_natural_prec_round`]. /// /// # Worst-case complexity - /// $T(n) = O(n)$ + /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. + /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is + /// `prec`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; - /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use std::cmp::Ordering::*; /// - /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::ZERO, 10, Exact); + /// let (x, o) = Float::from_natural_prec(Natural::ZERO, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// - /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 20, Exact); + /// let (x, o) = Float::from_natural_prec(Natural::from(123u32), 20); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// - /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 4, Floor); + /// let (x, o) = Float::from_natural_prec(Natural::from(123u32), 4); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); - /// - /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 4, Ceiling); - /// assert_eq!(x.to_string(), "1.3e2"); - /// assert_eq!(x.get_prec(), Some(4)); - /// assert_eq!(o, Greater); /// ``` #[inline] - pub fn from_natural_prec_round_ref( - x: &Natural, - prec: u64, - rm: RoundingMode, - ) -> (Float, Ordering) { - // TODO be more efficient when x is large and prec is small - assert_ne!(prec, 0); - if *x == 0u32 { - return (Float::ZERO, Equal); - } - let bits = x.significant_bits(); - let mut f = Float(Finite { - sign: true, - exponent: i32::exact_from(bits), - precision: bits, - significand: x << bits.neg_mod_power_of_2(Limb::LOG_WIDTH), - }); - let o = f.set_prec_round(prec, rm); - (f, o) + pub fn from_natural_prec(x: Natural, prec: u64) -> (Float, Ordering) { + Float::from_natural_prec_round(x, prec, Nearest) } /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by reference. If the [`Float`] @@ -194,11 +329,12 @@ impl Float { /// as well as a precision, try [`Float::from_natural_prec_round_ref`]. /// /// # Worst-case complexity - /// $T(n) = O(n)$ + /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// - /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. + /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is + /// `prec`. /// /// # Examples /// ``` @@ -223,20 +359,97 @@ impl Float { /// ``` #[inline] pub fn from_natural_prec_ref(x: &Natural, prec: u64) -> (Float, Ordering) { - // TODO be more efficient when x is large and prec is small - assert_ne!(prec, 0); - if *x == 0u32 { - return (Float::ZERO, Equal); + Float::from_natural_prec_round_ref(x, prec, Nearest) + } + + /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by reference. + /// + /// If the [`Natural`] is nonzero, the precision of the [`Float`] is the minimum possible + /// precision to represent the [`Natural`] exactly. If you instead want to use the precision + /// equal to the [`Natural`]'s number of significant bits, try `from`. If you want to specify + /// some other precision, try [`Float::from_natural_prec_ref`]. This may require rounding, which + /// uses [`Nearest`] by default. To specify a rounding mode as well as a precision, try + /// [`Float::from_natural_prec_round_ref`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(1)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `n.significant_bits()`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::Zero; + /// use malachite_float::Float; + /// use malachite_nz::natural::Natural; + /// + /// assert_eq!( + /// Float::from_natural_min_prec_ref(&Natural::ZERO).to_string(), + /// "0.0" + /// ); + /// assert_eq!( + /// Float::from_natural_min_prec_ref(&Natural::from(100u32)).to_string(), + /// "100.0" + /// ); + /// assert_eq!( + /// Float::from_natural_min_prec_ref(&Natural::from(100u32)).get_prec(), + /// Some(5) + /// ); + /// ``` + pub fn from_natural_min_prec(x: Natural) -> Float { + if x == 0 { + Float::ZERO + } else { + let bits = x.significant_bits(); + let prec = bits - x.trailing_zeros().unwrap(); + Float::from_natural_prec_round(x, prec, Floor).0 + } + } + + /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by value. + /// + /// If the [`Natural`] is nonzero, the precision of the [`Float`] is the minimum possible + /// precision to represent the [`Natural`] exactly. If you instead want to use the precision + /// equal to the [`Natural`]'s number of significant bits, try `from`. If you want to specify + /// some other precision, try [`Float::from_natural_prec`]. This may require rounding, which + /// uses [`Nearest`] by default. To specify a rounding mode as well as a precision, try + /// [`Float::from_natural_prec_round`]. + /// + /// # Worst-case complexity + /// $T(n) = O(n)$ + /// + /// $M(n) = O(1)$ + /// + /// where $T$ is time, $M$ is additional memory, and $n$ is `n.significant_bits()`. + /// + /// # Examples + /// ``` + /// use malachite_base::num::basic::traits::Zero; + /// use malachite_float::Float; + /// use malachite_nz::natural::Natural; + /// + /// assert_eq!( + /// Float::from_natural_min_prec(Natural::ZERO).to_string(), + /// "0.0" + /// ); + /// assert_eq!( + /// Float::from_natural_min_prec(Natural::from(100u32)).to_string(), + /// "100.0" + /// ); + /// assert_eq!( + /// Float::from_natural_min_prec(Natural::from(100u32)).get_prec(), + /// Some(5) + /// ); + /// ``` + pub fn from_natural_min_prec_ref(x: &Natural) -> Float { + if *x == 0 { + Float::ZERO + } else { + let bits = x.significant_bits(); + let prec = bits - x.trailing_zeros().unwrap(); + from_natural_prec_round_helper_no_round(x, prec, bits) } - let bits = x.significant_bits(); - let mut f = Float(Finite { - sign: true, - exponent: i32::exact_from(bits), - precision: bits, - significand: x << bits.neg_mod_power_of_2(Limb::LOG_WIDTH), - }); - let o = f.set_prec(prec); - (f, o) } } @@ -244,9 +457,11 @@ impl From for Float { /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by value. /// /// If the [`Natural`] is nonzero, the precision of the [`Float`] is equal to the [`Natural`]'s - /// number of significant bits. If you want to specify a different precision, try - /// [`Float::from_natural_prec`]. This may require rounding, which uses [`Nearest`] by default. - /// To specify a rounding mode as well as a precision, try [`Float::from_natural_prec_round`]. + /// number of significant bits. If you instead want to use the minimum possible precision to + /// represent the [`Natural`] exactly, try [`Float::from_natural_min_prec`]. If you want to + /// specify some other precision, try [`Float::from_natural_prec`]. This may require rounding, + /// which uses [`Nearest`] by default. To specify a rounding mode as well as a precision, try + /// [`Float::from_natural_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ @@ -283,10 +498,11 @@ impl<'a> From<&'a Natural> for Float { /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by reference. /// /// If the [`Natural`] is nonzero, the precision of the [`Float`] is equal to the [`Natural`]'s - /// number of significant bits. If you want to specify a different precision, try - /// [`Float::from_natural_prec_ref`]. This may require rounding, which uses [`Nearest`] by - /// default. To specify a rounding mode as well as a precision, try - /// [`Float::from_natural_prec_round_ref`]. + /// number of significant bits. If you instead want to use the minimum possible precision to + /// represent the [`Natural`] exactly, try [`Float::from_natural_min_prec_ref`]. If you want to + /// specify some other precision, try [`Float::from_natural_prec_ref`]. This may require + /// rounding, which uses [`Nearest`] by default. To specify a rounding mode as well as a + /// precision, try [`Float::from_natural_prec_round_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ diff --git a/malachite-float/src/conversion/from_primitive_int.rs b/malachite-float/src/conversion/from_primitive_int.rs index 025f61dbc..e9e6723b3 100644 --- a/malachite-float/src/conversion/from_primitive_int.rs +++ b/malachite-float/src/conversion/from_primitive_int.rs @@ -16,7 +16,7 @@ use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::rounding_modes::RoundingMode; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; -use malachite_nz::platform::Limb; +use malachite_nz::platform::{Limb, SignedLimb}; const fn const_limb_significant_bits(x: Limb) -> u64 { Limb::WIDTH - (x.leading_zeros() as u64) @@ -54,24 +54,216 @@ const fn const_i64_convertible_from_limb(value: Limb) -> bool { } impl Float { - // TODO test - pub const fn const_from_unsigned(x: Limb) -> Float { + /// Converts an unsigned primitive integer to a [`Float`], after multiplying it by the specified + /// power of 2. + /// + /// The type of the integer is `u64`, unless the `32_bit_limbs` feature is set, in which case + /// the type is `u32`. + /// + /// If the integer is nonzero, the precision of the [`Float`] is equal to the integer's number + /// of significant bits. + /// + /// If you don't need to use this function in a const context, try just using `from` instead, + /// followed by `>>` or `<<`. + /// + /// $$ + /// f(x,k) = x2^k. + /// $$ + /// + /// # Worst-case complexity + /// Constant time and additional memory. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// + /// assert_eq!( + /// Float::const_from_unsigned_times_power_of_2(0, 0).to_string(), + /// "0.0" + /// ); + /// assert_eq!( + /// Float::const_from_unsigned_times_power_of_2(123, 0).to_string(), + /// "123.0" + /// ); + /// assert_eq!( + /// Float::const_from_unsigned_times_power_of_2(123, 1).to_string(), + /// "246.0" + /// ); + /// assert_eq!( + /// Float::const_from_unsigned_times_power_of_2(123, -1).to_string(), + /// "61.5" + /// ); + /// #[cfg(not(feature = "32_bit_limbs"))] + /// { + /// assert_eq!( + /// Float::const_from_unsigned_times_power_of_2(884279719003555, -48).to_string(), + /// "3.141592653589793" + /// ); + /// } + /// ``` + pub const fn const_from_unsigned_times_power_of_2(x: Limb, pow: i32) -> Float { if x == 0 { return Float::ZERO; } assert!(const_i64_convertible_from_limb(x)); let bits = const_limb_significant_bits(x); + let bits_i32 = bits as i32; + let exponent = bits_i32.wrapping_add(pow); + if pow >= 0 { + assert!(exponent >= bits_i32); + } else { + assert!(exponent < bits_i32); + } Float(Finite { sign: true, - exponent: bits as i32, + exponent, precision: bits, significand: Natural::const_from( - // TODO simplify? x << const_u64_neg_mod_power_of_2(bits, Limb::LOG_WIDTH), ), }) } + /// Converts an unsigned primitive integer to a [`Float`]. + /// + /// The type of the integer is `u64`, unless the `32_bit_limbs` feature is set, in which case + /// the type is `u32`. + /// + /// If the integer is nonzero, the precision of the [`Float`] is equal to the integer's number + /// of significant bits. + /// + /// If you don't need to use this function in a const context, try just using `from` instead; it + /// will probably be slightly faster. + /// + /// # Worst-case complexity + /// Constant time and additional memory. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// + /// assert_eq!(Float::const_from_unsigned(0).to_string(), "0.0"); + /// assert_eq!(Float::const_from_unsigned(123).to_string(), "123.0"); + /// ``` + #[inline] + pub const fn const_from_unsigned(x: Limb) -> Float { + Float::const_from_unsigned_times_power_of_2(x, 0) + } + + /// Converts a signed primitive integer to a [`Float`], after multiplying it by the specified + /// power of 2. + /// + /// The type of the integer is `i64`, unless the `32_bit_limbs` feature is set, in which case + /// the type is `i32`. + /// + /// If the integer is nonzero, the precision of the [`Float`] is equal to the integer's number + /// of significant bits. + /// + /// If you don't need to use this function in a const context, try just using `from` instead, + /// followed by `>>` or `<<`. + /// + /// $$ + /// f(x,k) = x2^k. + /// $$ + /// + /// # Worst-case complexity + /// Constant time and additional memory. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(0, 0).to_string(), + /// "0.0" + /// ); + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(123, 0).to_string(), + /// "123.0" + /// ); + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(123, 1).to_string(), + /// "246.0" + /// ); + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(123, -1).to_string(), + /// "61.5" + /// ); + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(-123, 0).to_string(), + /// "-123.0" + /// ); + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(-123, 1).to_string(), + /// "-246.0" + /// ); + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(-123, -1).to_string(), + /// "-61.5" + /// ); + /// #[cfg(not(feature = "32_bit_limbs"))] + /// { + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(884279719003555, -48).to_string(), + /// "3.141592653589793" + /// ); + /// assert_eq!( + /// Float::const_from_signed_times_power_of_2(-884279719003555, -48).to_string(), + /// "-3.141592653589793" + /// ); + /// } + /// ``` + pub const fn const_from_signed_times_power_of_2(x: SignedLimb, pow: i32) -> Float { + if x == 0 { + return Float::ZERO; + } + let x_abs = x.unsigned_abs(); + assert!(const_i64_convertible_from_limb(x_abs)); + let bits = const_limb_significant_bits(x_abs); + let bits_i32 = bits as i32; + let exponent = bits_i32.wrapping_add(pow); + if pow >= 0 { + assert!(exponent >= bits_i32); + } else { + assert!(exponent < bits_i32); + } + Float(Finite { + sign: x > 0, + exponent, + precision: bits, + significand: Natural::const_from( + x_abs << const_u64_neg_mod_power_of_2(bits, Limb::LOG_WIDTH), + ), + }) + } + + /// Converts a signed primitive integer to a [`Float`]. + /// + /// The type of the integer is `i64`, unless the `32_bit_limbs` feature is set, in which case + /// the type is `i32`. + /// + /// If the integer is nonzero, the precision of the [`Float`] is equal to the integer's number + /// of significant bits. + /// + /// If you don't need to use this function in a const context, try just using `from` instead; it + /// will probably be slightly faster. + /// + /// # Worst-case complexity + /// Constant time and additional memory. + /// + /// # Examples + /// ``` + /// use malachite_float::Float; + /// + /// assert_eq!(Float::const_from_signed(0).to_string(), "0.0"); + /// assert_eq!(Float::const_from_signed(123).to_string(), "123.0"); + /// assert_eq!(Float::const_from_signed(-123).to_string(), "-123.0"); + /// ``` + #[inline] + pub const fn const_from_signed(x: SignedLimb) -> Float { + Float::const_from_signed_times_power_of_2(x, 0) + } + /// Converts a primitive unsigned integer to a [`Float`]. If the [`Float`] is nonzero, it has /// the specified precision. If rounding is needed, the specified rounding mode is used. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to, @@ -194,6 +386,9 @@ macro_rules! impl_from_unsigned { /// default. To specify a rounding mode as well as a precision, try /// [`Float::from_unsigned_prec_round`]. /// + /// If you want to create a [`Float`] from an unsigned primitive integer in a const + /// context, try [`Float::const_from_unsigned`] instead. + /// /// # Worst-case complexity /// Constant time and additional memory. /// @@ -219,6 +414,9 @@ macro_rules! impl_from_signed { /// default. To specify a rounding mode as well as a precision, try /// [`Float::from_signed_prec_round`]. /// + /// If you want to create a [`Float`] from an signed primitive integer in a const + /// context, try [`Float::const_from_signed`] instead. + /// /// # Worst-case complexity /// Constant time and additional memory. /// diff --git a/malachite-float/src/conversion/from_rational.rs b/malachite-float/src/conversion/from_rational.rs index 93fd97fde..dfa5a041e 100644 --- a/malachite-float/src/conversion/from_rational.rs +++ b/malachite-float/src/conversion/from_rational.rs @@ -8,12 +8,12 @@ use crate::InnerFloat::Finite; use crate::{significand_bits, Float}; +use core::cmp::max; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ - CheckedLogBase2, IsPowerOf2, NegModPowerOf2, RoundToMultipleOfPowerOf2, UnsignedAbs, + CheckedLogBase2, IsPowerOf2, NegAssign, NegModPowerOf2, RoundToMultipleOfPowerOf2, UnsignedAbs, }; use malachite_base::num::basic::integers::PrimitiveInt; -use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; @@ -22,6 +22,186 @@ use malachite_nz::platform::Limb; use malachite_q::conversion::primitive_float_from_rational::FloatFromRationalError; use malachite_q::Rational; +pub_test! {from_rational_prec_round_direct( + x: Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + if let Some(pow) = x.denominator_ref().checked_log_base_2() { + let sign = x >= 0; + let (y, o) = Float::from_integer_prec_round( + Integer::from_sign_and_abs(sign, x.into_numerator()), + prec, + rm, + ); + (y >> pow, o) + } else { + let mut exponent = i32::exact_from(x.floor_log_base_2_abs()); + let (significand, o) = + Integer::rounding_from(x << (i32::exact_from(prec) - exponent - 1), rm); + let sign = significand >= 0; + let mut significand = significand.unsigned_abs(); + let away_from_0 = if sign { Greater } else { Less }; + if o == away_from_0 && significand.is_power_of_2() { + exponent += 1; + } + significand <<= significand + .significant_bits() + .neg_mod_power_of_2(Limb::LOG_WIDTH); + let target_bits = prec + .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) + .0; + let current_bits = significand_bits(&significand); + if current_bits > target_bits { + significand >>= current_bits - target_bits; + } + ( + Float(Finite { + sign, + exponent: exponent + 1, + precision: prec, + significand, + }), + o, + ) + } +}} + +pub_test! {from_rational_prec_round_using_div( + x: Rational, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + let sign = x >= 0; + if !sign { + rm.neg_assign(); + } + let (n, d) = x.into_numerator_and_denominator(); + let (f, o) = match ( + if n == 0 { None } else { n.checked_log_base_2() }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => ( + Float::power_of_2_prec(i64::exact_from(log_n) - i64::exact_from(log_d), prec), + Equal, + ), + (None, Some(log_d)) => { + let (f, o) = Float::from_natural_prec_round(n, prec, rm); + (f >> log_d, o) + } + (Some(log_n), None) => { + let (f, o) = Float::from_natural_min_prec(d).reciprocal_prec_round(prec, rm); + (f << log_n, o) + } + (None, None) => Float::from_natural_min_prec(n).div_prec_round( + Float::from_natural_min_prec(d), + prec, + rm, + ), + }; + if sign { + (f, o) + } else { + (-f, o.reverse()) + } +}} + +pub fn from_rational_prec_round_ref_direct( + x: &Rational, + prec: u64, + rm: RoundingMode, +) -> (Float, Ordering) { + assert_ne!(prec, 0); + if let Some(pow) = x.denominator_ref().checked_log_base_2() { + let sign = *x >= 0; + let (y, o) = Float::from_natural_prec_round_ref( + x.numerator_ref(), + prec, + if sign { rm } else { -rm }, + ); + if sign { + (y >> pow, o) + } else { + (-y >> pow, o.reverse()) + } + } else { + let mut exponent = i32::exact_from(x.floor_log_base_2_abs()); + let (significand, o) = + Integer::rounding_from(x << (i32::exact_from(prec) - exponent - 1), rm); + let sign = significand >= 0; + let mut significand = significand.unsigned_abs(); + let away_from_0 = if sign { Greater } else { Less }; + if o == away_from_0 && significand.is_power_of_2() { + exponent += 1; + } + significand <<= significand + .significant_bits() + .neg_mod_power_of_2(Limb::LOG_WIDTH); + let target_bits = prec + .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) + .0; + let current_bits = significand_bits(&significand); + if current_bits > target_bits { + significand >>= current_bits - target_bits; + } + ( + Float(Finite { + sign, + exponent: exponent + 1, + precision: prec, + significand, + }), + o, + ) + } +} + +pub fn from_rational_prec_round_ref_using_div( + x: &Rational, + prec: u64, + mut rm: RoundingMode, +) -> (Float, Ordering) { + let sign = *x >= 0; + if !sign { + rm.neg_assign(); + } + let (n, d) = x.numerator_and_denominator_ref(); + let (f, o) = match ( + if *n == 0 { + None + } else { + n.checked_log_base_2() + }, + d.checked_log_base_2(), + ) { + (Some(log_n), Some(log_d)) => ( + Float::power_of_2_prec(i64::exact_from(log_n) - i64::exact_from(log_d), prec), + Equal, + ), + (None, Some(log_d)) => { + let (f, o) = Float::from_natural_prec_round_ref(n, prec, rm); + (f >> log_d, o) + } + (Some(log_n), None) => { + let (f, o) = Float::from_natural_min_prec_ref(d).reciprocal_prec_round(prec, rm); + (f << log_n, o) + } + (None, None) => Float::from_natural_min_prec_ref(n).div_prec_round( + Float::from_natural_min_prec_ref(d), + prec, + rm, + ), + }; + if sign { + (f, o) + } else { + (-f, o.reverse()) + } +} + +const FROM_RATIONAL_THRESHOLD: u64 = 100; + impl Float { /// Converts a [`Rational`] to a [`Float`], taking the [`Rational`] by value. If the [`Float`] /// is nonzero, it has the specified precision. If rounding is needed, the specified rounding @@ -76,38 +256,10 @@ impl Float { /// ``` #[inline] pub fn from_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) { - assert_ne!(prec, 0); - if x == 0 { - (Float::ZERO, Equal) + if max(x.significant_bits(), prec) < FROM_RATIONAL_THRESHOLD { + from_rational_prec_round_direct(x, prec, rm) } else { - let mut exponent = i32::exact_from(x.floor_log_base_2_abs()); - let (significand, o) = - Integer::rounding_from(x << (i32::exact_from(prec) - exponent - 1), rm); - let sign = significand >= 0; - let mut significand = significand.unsigned_abs(); - let away_from_0 = if sign { Greater } else { Less }; - if o == away_from_0 && significand.is_power_of_2() { - exponent += 1; - } - significand <<= significand - .significant_bits() - .neg_mod_power_of_2(Limb::LOG_WIDTH); - let target_bits = prec - .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) - .0; - let current_bits = significand_bits(&significand); - if current_bits > target_bits { - significand >>= current_bits - target_bits; - } - ( - Float(Finite { - sign, - exponent: exponent + 1, - precision: prec, - significand, - }), - o, - ) + from_rational_prec_round_using_div(x, prec, rm) } } @@ -226,38 +378,10 @@ impl Float { prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { - assert_ne!(prec, 0); - if *x == 0 { - (Float::ZERO, Equal) + if max(x.significant_bits(), prec) < FROM_RATIONAL_THRESHOLD { + from_rational_prec_round_ref_direct(x, prec, rm) } else { - let mut exponent = i32::exact_from(x.floor_log_base_2_abs()); - let (significand, o) = - Integer::rounding_from(x << (i32::exact_from(prec) - exponent - 1), rm); - let sign = significand >= 0; - let mut significand = significand.unsigned_abs(); - let away_from_0 = if sign { Greater } else { Less }; - if o == away_from_0 && significand.is_power_of_2() { - exponent += 1; - } - significand <<= significand - .significant_bits() - .neg_mod_power_of_2(Limb::LOG_WIDTH); - let target_bits = prec - .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) - .0; - let current_bits = significand_bits(&significand); - if current_bits > target_bits { - significand >>= current_bits - target_bits; - } - ( - Float(Finite { - sign, - exponent: exponent + 1, - precision: prec, - significand, - }), - o, - ) + from_rational_prec_round_ref_using_div(x, prec, rm) } } diff --git a/malachite-float/src/conversion/mod.rs b/malachite-float/src/conversion/mod.rs index 85a0a75da..99f830f1d 100644 --- a/malachite-float/src/conversion/mod.rs +++ b/malachite-float/src/conversion/mod.rs @@ -6,6 +6,8 @@ // 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 . +/// Functions for creating a [`Float`](crate::Float) from an infinite iterator of bits. +pub mod from_bits; /// Implementations of the [`From`] trait for converting an /// [`Integer`](malachite_nz::integer::Integer) to a [`Float`](crate::Float). pub mod from_integer; diff --git a/malachite-float/src/lib.rs b/malachite-float/src/lib.rs index 1bcf1ee12..658461d47 100644 --- a/malachite-float/src/lib.rs +++ b/malachite-float/src/lib.rs @@ -290,6 +290,9 @@ pub mod arithmetic; pub mod basic; /// Traits for comparing [`Float`]s for equality or order. pub mod comparison; +/// Functions that produce [`Float`] approximations of mathematical constants, using a given +/// precision and rounding mode. +pub mod constants; /// Traits for converting to and from [`Float`]s, including converting [`Float`]s to and from /// strings. pub mod conversion; diff --git a/malachite-float/src/test_util/arithmetic/add.rs b/malachite-float/src/test_util/arithmetic/add.rs index 6fd6625ed..e18d6142b 100644 --- a/malachite-float/src/test_util/arithmetic/add.rs +++ b/malachite-float/src/test_util/arithmetic/add.rs @@ -14,46 +14,75 @@ use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use rug::float::Round; -use rug::ops::AddAssignRound; +use rug::ops::AssignRound; +use std::cmp::max; use std::cmp::Ordering::{self, *}; -use std::ops::AddAssign; -pub fn rug_add_round(x: rug::Float, y: rug::Float, rm: Round) -> (rug::Float, Ordering) { - let xsb = rug_float_significant_bits(&x); - let ysb = rug_float_significant_bits(&y); - let mut sum = x; - if sum == 0u32 || xsb < ysb { - sum.set_prec(u32::exact_from(ysb)); - } - let o = sum.add_assign_round(y, rm); +pub fn rug_add_prec_round( + x: &rug::Float, + y: &rug::Float, + prec: u64, + rm: Round, +) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x + y, rm); (sum, o) } -pub fn rug_add(x: rug::Float, y: rug::Float) -> rug::Float { - let xsb = rug_float_significant_bits(&x); - let ysb = rug_float_significant_bits(&y); - let mut sum = x; - if sum == 0u32 || xsb < ysb { - sum.set_prec(u32::exact_from(ysb)); - } - sum.add_assign(y); - sum +#[inline] +pub fn rug_add_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { + rug_add_prec_round( + x, + y, + max(rug_float_significant_bits(x), rug_float_significant_bits(y)), + rm, + ) } -pub fn rug_add_rational_round( - x: rug::Float, - y: rug::Rational, +#[inline] +pub fn rug_add_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { + rug_add_prec_round(x, y, prec, Round::Nearest) +} + +pub fn rug_add(x: &rug::Float, y: &rug::Float) -> rug::Float { + rug_add_prec_round( + x, + y, + max(rug_float_significant_bits(x), rug_float_significant_bits(y)), + Round::Nearest, + ) + .0 +} + +pub fn rug_add_rational_prec_round( + x: &rug::Float, + y: &rug::Rational, + prec: u64, rm: Round, ) -> (rug::Float, Ordering) { - let mut sum = x; - let o = sum.add_assign_round(y, rm); + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x + y, rm); (sum, o) } -pub fn rug_add_rational(x: rug::Float, y: rug::Rational) -> rug::Float { - let mut sum = x; - sum.add_assign(y); - sum +pub fn rug_add_rational_round( + x: &rug::Float, + y: &rug::Rational, + rm: Round, +) -> (rug::Float, Ordering) { + rug_add_rational_prec_round(x, y, rug_float_significant_bits(x), rm) +} + +pub fn rug_add_rational_prec( + x: &rug::Float, + y: &rug::Rational, + prec: u64, +) -> (rug::Float, Ordering) { + rug_add_rational_prec_round(x, y, prec, Round::Nearest) +} + +pub fn rug_add_rational(x: &rug::Float, y: &rug::Rational) -> rug::Float { + rug_add_rational_prec_round(x, y, rug_float_significant_bits(x), Round::Nearest).0 } pub fn add_prec_round_naive(x: Float, y: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { diff --git a/malachite-float/src/test_util/arithmetic/div.rs b/malachite-float/src/test_util/arithmetic/div.rs new file mode 100644 index 000000000..d80db29c5 --- /dev/null +++ b/malachite-float/src/test_util/arithmetic/div.rs @@ -0,0 +1,158 @@ +// 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 crate::test_util::common::rug_float_significant_bits; +use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; +use crate::{float_either_infinity, float_either_zero, float_nan, Float}; +use core::cmp::Ordering::{self, *}; +use malachite_base::num::arithmetic::traits::NegAssign; +use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_q::Rational; +use rug::float::Round; +use rug::ops::AssignRound; +use std::cmp::max; + +pub fn div_prec_round_naive(x: Float, y: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { + assert_ne!(prec, 0); + match (x, y) { + (float_nan!(), _) + | (_, float_nan!()) + | (float_either_infinity!(), float_either_infinity!()) + | (float_either_zero!(), float_either_zero!()) => (float_nan!(), Equal), + ( + Float(Infinity { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => ( + Float(Infinity { + sign: x_sign == y_sign, + }), + Equal, + ), + ( + Float(Zero { sign: x_sign }), + Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), + ) + | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => ( + Float(Zero { + sign: x_sign == y_sign, + }), + Equal, + ), + (x, y) => { + let (mut quotient, o) = Float::from_rational_prec_round( + Rational::exact_from(x) / Rational::exact_from(y), + prec, + rm, + ); + if rm == Floor && o == Equal && quotient == 0u32 { + quotient.neg_assign(); + } + (quotient, o) + } + } +} + +pub fn rug_div_prec_round( + x: &rug::Float, + y: &rug::Float, + prec: u64, + rm: Round, +) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x / y, rm); + (sum, o) +} + +#[inline] +pub fn rug_div_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { + rug_div_prec_round( + x, + y, + max(rug_float_significant_bits(x), rug_float_significant_bits(y)), + rm, + ) +} + +#[inline] +pub fn rug_div_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { + rug_div_prec_round(x, y, prec, Round::Nearest) +} + +pub fn rug_div(x: &rug::Float, y: &rug::Float) -> rug::Float { + rug_div_prec_round( + x, + y, + max(rug_float_significant_bits(x), rug_float_significant_bits(y)), + Round::Nearest, + ) + .0 +} + +pub fn rug_div_rational_prec_round( + x: &rug::Float, + y: &rug::Rational, + prec: u64, + rm: Round, +) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x / y, rm); + (sum, o) +} + +pub fn rug_div_rational_round( + x: &rug::Float, + y: &rug::Rational, + rm: Round, +) -> (rug::Float, Ordering) { + rug_div_rational_prec_round(x, y, rug_float_significant_bits(x), rm) +} + +pub fn rug_div_rational_prec( + x: &rug::Float, + y: &rug::Rational, + prec: u64, +) -> (rug::Float, Ordering) { + rug_div_rational_prec_round(x, y, prec, Round::Nearest) +} + +pub fn rug_div_rational(x: &rug::Float, y: &rug::Rational) -> rug::Float { + rug_div_rational_prec_round(x, y, rug_float_significant_bits(x), Round::Nearest).0 +} + +pub fn rug_rational_div_float_prec_round( + x: &rug::Rational, + y: &rug::Float, + prec: u64, + rm: Round, +) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x / y, rm); + (sum, o) +} + +pub fn rug_rational_div_float_round( + x: &rug::Rational, + y: &rug::Float, + rm: Round, +) -> (rug::Float, Ordering) { + rug_rational_div_float_prec_round(x, y, rug_float_significant_bits(y), rm) +} + +pub fn rug_rational_div_float_prec( + x: &rug::Rational, + y: &rug::Float, + prec: u64, +) -> (rug::Float, Ordering) { + rug_rational_div_float_prec_round(x, y, prec, Round::Nearest) +} + +pub fn rug_rational_div_float(x: &rug::Rational, y: &rug::Float) -> rug::Float { + rug_rational_div_float_prec_round(x, y, rug_float_significant_bits(y), Round::Nearest).0 +} diff --git a/malachite-float/src/test_util/arithmetic/mod.rs b/malachite-float/src/test_util/arithmetic/mod.rs index f69e8bbe7..dbaabc42c 100644 --- a/malachite-float/src/test_util/arithmetic/mod.rs +++ b/malachite-float/src/test_util/arithmetic/mod.rs @@ -7,6 +7,8 @@ // 3 of the License, or (at your option) any later version. See . pub mod add; +pub mod div; pub mod mul; +pub mod reciprocal; pub mod square; pub mod sub; diff --git a/malachite-float/src/test_util/arithmetic/mul.rs b/malachite-float/src/test_util/arithmetic/mul.rs index beaba9d79..b5a91ba9f 100644 --- a/malachite-float/src/test_util/arithmetic/mul.rs +++ b/malachite-float/src/test_util/arithmetic/mul.rs @@ -15,8 +15,8 @@ use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use rug::float::Round; -use rug::ops::MulAssignRound; -use std::ops::MulAssign; +use rug::ops::AssignRound; +use std::cmp::max; pub fn mul_prec_round_naive(x: Float, y: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { assert_ne!(prec, 0); @@ -59,40 +59,69 @@ pub fn mul_prec_round_naive(x: Float, y: Float, prec: u64, rm: RoundingMode) -> } } -pub fn rug_mul_round(x: rug::Float, y: rug::Float, rm: Round) -> (rug::Float, Ordering) { - let xsb = rug_float_significant_bits(&x); - let ysb = rug_float_significant_bits(&y); - let mut product = x; - if product == 0u32 || xsb < ysb { - product.set_prec(u32::exact_from(ysb)); - } - let o = product.mul_assign_round(y, rm); - (product, o) +pub fn rug_mul_prec_round( + x: &rug::Float, + y: &rug::Float, + prec: u64, + rm: Round, +) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x * y, rm); + (sum, o) } -pub fn rug_mul(x: rug::Float, y: rug::Float) -> rug::Float { - let xsb = rug_float_significant_bits(&x); - let ysb = rug_float_significant_bits(&y); - let mut product = x; - if product == 0u32 || xsb < ysb { - product.set_prec(u32::exact_from(ysb)); - } - product.mul_assign(y); - product +#[inline] +pub fn rug_mul_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { + rug_mul_prec_round( + x, + y, + max(rug_float_significant_bits(x), rug_float_significant_bits(y)), + rm, + ) +} + +#[inline] +pub fn rug_mul_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { + rug_mul_prec_round(x, y, prec, Round::Nearest) +} + +pub fn rug_mul(x: &rug::Float, y: &rug::Float) -> rug::Float { + rug_mul_prec_round( + x, + y, + max(rug_float_significant_bits(x), rug_float_significant_bits(y)), + Round::Nearest, + ) + .0 +} + +pub fn rug_mul_rational_prec_round( + x: &rug::Float, + y: &rug::Rational, + prec: u64, + rm: Round, +) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x * y, rm); + (sum, o) } pub fn rug_mul_rational_round( - x: rug::Float, - y: rug::Rational, + x: &rug::Float, + y: &rug::Rational, rm: Round, ) -> (rug::Float, Ordering) { - let mut product = x; - let o = product.mul_assign_round(y, rm); - (product, o) + rug_mul_rational_prec_round(x, y, rug_float_significant_bits(x), rm) +} + +pub fn rug_mul_rational_prec( + x: &rug::Float, + y: &rug::Rational, + prec: u64, +) -> (rug::Float, Ordering) { + rug_mul_rational_prec_round(x, y, prec, Round::Nearest) } -pub fn rug_mul_rational(x: rug::Float, y: rug::Rational) -> rug::Float { - let mut product = x; - product.mul_assign(y); - product +pub fn rug_mul_rational(x: &rug::Float, y: &rug::Rational) -> rug::Float { + rug_mul_rational_prec_round(x, y, rug_float_significant_bits(x), Round::Nearest).0 } diff --git a/malachite-float/src/test_util/arithmetic/reciprocal.rs b/malachite-float/src/test_util/arithmetic/reciprocal.rs new file mode 100644 index 000000000..d74632df6 --- /dev/null +++ b/malachite-float/src/test_util/arithmetic/reciprocal.rs @@ -0,0 +1,43 @@ +// 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 crate::test_util::common::rug_float_significant_bits; +use crate::Float; +use core::cmp::Ordering; +use malachite_base::num::basic::traits::One; +use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::rounding_modes::RoundingMode; +use malachite_q::Rational; +use rug::float::Round; +use rug::ops::AssignRound; + +pub fn reciprocal_prec_round_naive_1(x: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { + Float::rational_div_float_prec_round(Rational::ONE, x, prec, rm) +} + +pub fn reciprocal_prec_round_naive_2(x: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { + Float::ONE.div_prec_round(x, prec, rm) +} + +pub fn rug_reciprocal_prec_round(x: &rug::Float, prec: u64, rm: Round) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(rug::Rational::ONE / x, rm); + (sum, o) +} + +pub fn rug_reciprocal_prec(x: &rug::Float, prec: u64) -> (rug::Float, Ordering) { + rug_reciprocal_prec_round(x, prec, Round::Nearest) +} + +pub fn rug_reciprocal_round(x: &rug::Float, rm: Round) -> (rug::Float, Ordering) { + rug_reciprocal_prec_round(x, rug_float_significant_bits(x), rm) +} + +pub fn rug_reciprocal(x: &rug::Float) -> rug::Float { + rug_reciprocal_prec_round(x, rug_float_significant_bits(x), Round::Nearest).0 +} diff --git a/malachite-float/src/test_util/arithmetic/square.rs b/malachite-float/src/test_util/arithmetic/square.rs index 3b92efe6b..84bddb01c 100644 --- a/malachite-float/src/test_util/arithmetic/square.rs +++ b/malachite-float/src/test_util/arithmetic/square.rs @@ -6,14 +6,26 @@ // 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 crate::test_util::common::rug_float_significant_bits; use core::cmp::Ordering; +use malachite_base::num::conversion::traits::ExactFrom; use rug::float::Round; +use rug::ops::AssignRound; -pub fn rug_square_round(mut x: rug::Float, rm: Round) -> (rug::Float, Ordering) { - let o = x.square_round(rm); - (x, o) +pub fn rug_square_prec_round(x: &rug::Float, prec: u64, rm: Round) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x.square_ref(), rm); + (sum, o) } -pub fn rug_square(x: rug::Float) -> rug::Float { - x.square() +pub fn rug_square_prec(x: &rug::Float, prec: u64) -> (rug::Float, Ordering) { + rug_square_prec_round(x, prec, Round::Nearest) +} + +pub fn rug_square_round(x: &rug::Float, rm: Round) -> (rug::Float, Ordering) { + rug_square_prec_round(x, rug_float_significant_bits(x), rm) +} + +pub fn rug_square(x: &rug::Float) -> rug::Float { + rug_square_prec_round(x, rug_float_significant_bits(x), Round::Nearest).0 } diff --git a/malachite-float/src/test_util/arithmetic/sub.rs b/malachite-float/src/test_util/arithmetic/sub.rs index b9ed67f35..6a6a02a10 100644 --- a/malachite-float/src/test_util/arithmetic/sub.rs +++ b/malachite-float/src/test_util/arithmetic/sub.rs @@ -9,44 +9,72 @@ use crate::test_util::common::rug_float_significant_bits; use malachite_base::num::conversion::traits::ExactFrom; use rug::float::Round; -use rug::ops::SubAssignRound; -use std::cmp::Ordering; -use std::ops::SubAssign; - -pub fn rug_sub_round(x: rug::Float, y: rug::Float, rm: Round) -> (rug::Float, Ordering) { - let xsb = rug_float_significant_bits(&x); - let ysb = rug_float_significant_bits(&y); - let mut diff = x; - if diff == 0u32 || xsb < ysb { - diff.set_prec(u32::exact_from(ysb)); - } - let o = diff.sub_assign_round(y, rm); - (diff, o) -} - -pub fn rug_sub(x: rug::Float, y: rug::Float) -> rug::Float { - let xsb = rug_float_significant_bits(&x); - let ysb = rug_float_significant_bits(&y); - let mut diff = x; - if diff == 0u32 || xsb < ysb { - diff.set_prec(u32::exact_from(ysb)); - } - diff.sub_assign(y); - diff +use rug::ops::AssignRound; +use std::cmp::{max, Ordering}; + +pub fn rug_sub_prec_round( + x: &rug::Float, + y: &rug::Float, + prec: u64, + rm: Round, +) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x - y, rm); + (sum, o) +} + +#[inline] +pub fn rug_sub_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { + rug_sub_prec_round( + x, + y, + max(rug_float_significant_bits(x), rug_float_significant_bits(y)), + rm, + ) +} + +#[inline] +pub fn rug_sub_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { + rug_sub_prec_round(x, y, prec, Round::Nearest) +} + +pub fn rug_sub(x: &rug::Float, y: &rug::Float) -> rug::Float { + rug_sub_prec_round( + x, + y, + max(rug_float_significant_bits(x), rug_float_significant_bits(y)), + Round::Nearest, + ) + .0 +} + +pub fn rug_sub_rational_prec_round( + x: &rug::Float, + y: &rug::Rational, + prec: u64, + rm: Round, +) -> (rug::Float, Ordering) { + let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); + let o = sum.assign_round(x - y, rm); + (sum, o) } pub fn rug_sub_rational_round( - x: rug::Float, - y: rug::Rational, + x: &rug::Float, + y: &rug::Rational, rm: Round, ) -> (rug::Float, Ordering) { - let mut diff = x; - let o = diff.sub_assign_round(y, rm); - (diff, o) + rug_sub_rational_prec_round(x, y, rug_float_significant_bits(x), rm) +} + +pub fn rug_sub_rational_prec( + x: &rug::Float, + y: &rug::Rational, + prec: u64, +) -> (rug::Float, Ordering) { + rug_sub_rational_prec_round(x, y, prec, Round::Nearest) } -pub fn rug_sub_rational(x: rug::Float, y: rug::Rational) -> rug::Float { - let mut diff = x; - diff.sub_assign(y); - diff +pub fn rug_sub_rational(x: &rug::Float, y: &rug::Rational) -> rug::Float { + rug_sub_rational_prec_round(x, y, rug_float_significant_bits(x), Round::Nearest).0 } diff --git a/malachite-float/src/test_util/bench/bucketers.rs b/malachite-float/src/test_util/bench/bucketers.rs index 0cfdca811..3b684fa7e 100644 --- a/malachite-float/src/test_util/bench/bucketers.rs +++ b/malachite-float/src/test_util/bench/bucketers.rs @@ -113,6 +113,18 @@ pub fn pair_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt>( } } +pub fn pair_2_pair_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U>( + x_name: &'a str, + y_name: &'a str, +) -> Bucketer<'a, (U, (Float, T))> { + Bucketer { + bucketing_function: &|(_, (x, z))| { + usize::exact_from(max!(x.complexity(), z.significant_bits())) + }, + bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits)"), + } +} + pub fn triple_float_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, @@ -128,6 +140,21 @@ pub fn triple_float_float_primitive_int_max_complexity_bucketer<'a, T: Primitive } } +pub fn pair_2_triple_float_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U>( + x_name: &'a str, + y_name: &'a str, + z_name: &'a str, +) -> Bucketer<'a, (U, (Float, Float, T))> { + Bucketer { + bucketing_function: &|(_, (x, y, z))| { + usize::exact_from(max!(x.complexity(), y.complexity(), z.significant_bits())) + }, + bucketing_label: format!( + "max({x_name}.complexity(), {y_name}.complexity(), {z_name}.significant_bits)" + ), + } +} + pub fn triple_1_2_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, @@ -140,6 +167,18 @@ pub fn triple_1_2_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveIn } } +pub fn pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U, V>( + x_name: &'a str, + y_name: &'a str, +) -> Bucketer<'a, (V, (Float, T, U))> { + Bucketer { + bucketing_function: &|(_, (x, y, _))| { + usize::exact_from(max!(x.complexity(), y.significant_bits())) + }, + bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), + } +} + pub fn quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, @@ -155,6 +194,26 @@ pub fn quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer<'a, T: } } +pub fn pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer< + 'a, + T: PrimitiveInt, + U, + V, +>( + x_name: &'a str, + y_name: &'a str, + z_name: &'a str, +) -> Bucketer<'a, (V, (Float, Float, T, U))> { + Bucketer { + bucketing_function: &|(_, (x, y, z, _))| { + usize::exact_from(max!(x.complexity(), y.complexity(), z.significant_bits())) + }, + bucketing_label: format!( + "max({x_name}.complexity(), {y_name}.complexity(), {z_name}.significant_bits())" + ), + } +} + pub fn quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer< 'a, T: PrimitiveInt, @@ -178,6 +237,30 @@ pub fn quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer< } } +pub fn pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer< + 'a, + T: PrimitiveInt, + U, + V, +>( + x_name: &'a str, + y_name: &'a str, + z_name: &'a str, +) -> Bucketer<'a, (V, (Float, Rational, T, U))> { + Bucketer { + bucketing_function: &|(_, (x, y, z, _))| { + usize::exact_from(max!( + x.complexity(), + y.significant_bits(), + z.significant_bits() + )) + }, + bucketing_label: format!( + "max({x_name}.complexity(), {y_name}.significant_bits(), {z_name}.significant_bits())" + ), + } +} + pub fn triple_float_rational_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, @@ -197,6 +280,29 @@ pub fn triple_float_rational_primitive_int_max_complexity_bucketer<'a, T: Primit } } +pub fn pair_2_triple_float_rational_primitive_int_max_complexity_bucketer< + 'a, + T: PrimitiveInt, + U, +>( + x_name: &'a str, + y_name: &'a str, + z_name: &'a str, +) -> Bucketer<'a, (U, (Float, Rational, T))> { + Bucketer { + bucketing_function: &|(_, (x, y, z))| { + usize::exact_from(max!( + x.complexity(), + y.significant_bits(), + z.significant_bits() + )) + }, + bucketing_label: format!( + "max({x_name}.complexity(), {y_name}.significant_bits(), {z_name}.significant_bits)" + ), + } +} + pub fn pair_2_pair_float_max_complexity_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, @@ -321,6 +427,16 @@ pub fn pair_float_primitive_float_max_complexity_bucketer<'a, T: PrimitiveFloat> } } +pub fn max_triple_1_float_complexity_triple_2_bucketer<'a, T>( + x_name: &'a str, + p_name: &'a str, +) -> Bucketer<'a, (Float, u64, T)> { + Bucketer { + bucketing_function: &|(x, p, _)| usize::exact_from(max(x.complexity(), *p)), + bucketing_label: format!("max({x_name}.complexity(), {p_name})"), + } +} + pub fn pair_2_max_triple_1_float_complexity_triple_2_bucketer<'a, T, U>( x_name: &'a str, p_name: &'a str, @@ -331,6 +447,16 @@ pub fn pair_2_max_triple_1_float_complexity_triple_2_bucketer<'a, T, U>( } } +pub fn max_pair_1_complexity_pair_2_bucketer<'a>( + x_name: &'a str, + y_name: &'a str, +) -> Bucketer<'a, (Float, u64)> { + Bucketer { + bucketing_function: &|(x, y)| usize::exact_from(max(x.complexity(), *y)), + bucketing_label: format!("max({x_name}.complexity(), {y_name})"), + } +} + pub fn pair_2_max_pair_1_complexity_pair_2_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, diff --git a/malachite-float/src/test_util/constants/mod.rs b/malachite-float/src/test_util/constants/mod.rs new file mode 100644 index 000000000..5a98bd76d --- /dev/null +++ b/malachite-float/src/test_util/constants/mod.rs @@ -0,0 +1,10 @@ +// 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 . + +pub mod prime_constant; +pub mod thue_morse_constant; diff --git a/malachite-float/src/test_util/constants/prime_constant.rs b/malachite-float/src/test_util/constants/prime_constant.rs new file mode 100644 index 000000000..a910af087 --- /dev/null +++ b/malachite-float/src/test_util/constants/prime_constant.rs @@ -0,0 +1,16 @@ +// 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 crate::Float; +use malachite_base::num::factorization::primes::prime_indicator_sequence; +use malachite_base::rounding_modes::RoundingMode; +use std::cmp::Ordering; + +pub fn prime_constant_prec_round_naive(prec: u64, rm: RoundingMode) -> (Float, Ordering) { + Float::non_dyadic_from_bits_prec_round(prime_indicator_sequence(), prec, rm) +} diff --git a/malachite-float/src/test_util/constants/thue_morse_constant.rs b/malachite-float/src/test_util/constants/thue_morse_constant.rs new file mode 100644 index 000000000..3a3051f63 --- /dev/null +++ b/malachite-float/src/test_util/constants/thue_morse_constant.rs @@ -0,0 +1,16 @@ +// 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 crate::Float; +use malachite_base::iterators::thue_morse_sequence; +use malachite_base::rounding_modes::RoundingMode; +use std::cmp::Ordering; + +pub fn thue_morse_constant_prec_round_naive(prec: u64, rm: RoundingMode) -> (Float, Ordering) { + Float::non_dyadic_from_bits_prec_round(thue_morse_sequence(), prec, rm) +} diff --git a/malachite-float/src/test_util/generators/common.rs b/malachite-float/src/test_util/generators/common.rs index e0c13a9ef..3f4946b04 100644 --- a/malachite-float/src/test_util/generators/common.rs +++ b/malachite-float/src/test_util/generators/common.rs @@ -123,6 +123,36 @@ pub fn float_float_rounding_mode_triple_rm( })) } +pub fn float_float_anything_triple_rm( + xs: It<(Float, Float, T)>, +) -> It<((rug::Float, rug::Float, T), (Float, Float, T))> { + Box::new(xs.map(|(x, y, z)| { + ( + ( + rug::Float::exact_from(&x), + rug::Float::exact_from(&y), + z.clone(), + ), + (x, y, z), + ) + })) +} + +pub fn float_rational_anything_triple_rm( + xs: It<(Float, Rational, T)>, +) -> It<((rug::Float, rug::Rational, T), (Float, Rational, T))> { + Box::new(xs.map(|(x, y, z)| { + ( + ( + rug::Float::exact_from(&x), + rug::Rational::exact_from(&y), + z.clone(), + ), + (x, y, z), + ) + })) +} + pub fn float_rational_rounding_mode_triple_rm( xs: It<(Float, Rational, RoundingMode)>, ) -> It<( @@ -140,3 +170,41 @@ pub fn float_rational_rounding_mode_triple_rm( ) })) } + +pub fn float_float_anything_rounding_mode_quadruple_rm( + xs: It<(Float, Float, T, RoundingMode)>, +) -> It<( + (rug::Float, rug::Float, T, rug::float::Round), + (Float, Float, T, RoundingMode), +)> { + Box::new(xs.map(|(x, y, z, rm)| { + ( + ( + rug::Float::exact_from(&x), + rug::Float::exact_from(&y), + z.clone(), + rug_round_exact_from_rounding_mode(rm), + ), + (x, y, z, rm), + ) + })) +} + +pub fn float_rational_anything_rounding_mode_quadruple_rm( + xs: It<(Float, Rational, T, RoundingMode)>, +) -> It<( + (rug::Float, rug::Rational, T, rug::float::Round), + (Float, Rational, T, RoundingMode), +)> { + Box::new(xs.map(|(x, y, z, rm)| { + ( + ( + rug::Float::exact_from(&x), + rug::Rational::exact_from(&y), + z.clone(), + rug_round_exact_from_rounding_mode(rm), + ), + (x, y, z, rm), + ) + })) +} diff --git a/malachite-float/src/test_util/generators/exhaustive.rs b/malachite-float/src/test_util/generators/exhaustive.rs index 6eb16a763..5aadd26a2 100644 --- a/malachite-float/src/test_util/generators/exhaustive.rs +++ b/malachite-float/src/test_util/generators/exhaustive.rs @@ -12,12 +12,11 @@ use crate::exhaustive::{ exhaustive_positive_floats_with_precision, exhaustive_positive_floats_with_sci_exponent, }; use crate::test_util::extra_variadic::{ - exhaustive_quadruples_xxyz_custom_output, exhaustive_triples_from_single, - exhaustive_triples_xxy, exhaustive_triples_xxy_custom_output, + exhaustive_triples_from_single, exhaustive_triples_xxy, exhaustive_triples_xxy_custom_output, }; use crate::{significand_bits, Float}; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; -use malachite_base::num::arithmetic::traits::{IsPowerOf2, Square}; +use malachite_base::num::arithmetic::traits::{IsPowerOf2, Reciprocal, Square}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; @@ -32,14 +31,14 @@ use malachite_base::num::iterators::ruler_sequence; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::rounding_modes::RoundingMode::{self, *}; -use malachite_base::test_util::generators::common::{reshape_2_1_to_3, It}; +use malachite_base::test_util::generators::common::{reshape_2_1_to_3, reshape_3_1_to_4, It}; use malachite_base::test_util::generators::exhaustive_pairs_big_tiny; use malachite_base::tuples::exhaustive::{ exhaustive_dependent_pairs, ExhaustiveDependentPairsYsGenerator, }; use malachite_base::tuples::exhaustive::{ - exhaustive_pairs, exhaustive_pairs_from_single, exhaustive_quadruples_custom_output, - exhaustive_triples, exhaustive_triples_custom_output, exhaustive_triples_xyy, lex_pairs, + exhaustive_pairs, exhaustive_pairs_from_single, exhaustive_triples, + exhaustive_triples_custom_output, exhaustive_triples_xyy, lex_pairs, }; use malachite_nz::integer::exhaustive::exhaustive_integers; use malachite_nz::integer::Integer; @@ -105,6 +104,13 @@ pub fn exhaustive_float_gen_var_10() -> It { )) } +pub fn exhaustive_float_gen_var_11() -> It { + Box::new(exhaustive_floats_with_precision_inclusive_range( + (Limb::WIDTH << 1) + 1, + u64::MAX, + )) +} + struct FloatWithPrecisionRangeGenerator; impl ExhaustiveDependentPairsYsGenerator>> @@ -158,6 +164,35 @@ fn exhaustive_float_pairs_with_precision_inclusive_range( ) } +struct FloatPairWithPrecisionRangesGenerator; + +impl + ExhaustiveDependentPairsYsGenerator< + (u64, u64), + (Float, Float), + Box>, + > for FloatPairWithPrecisionRangesGenerator +{ + #[inline] + fn get_ys(&self, &precs: &(u64, u64)) -> Box> { + Box::new(exhaustive_pairs( + exhaustive_positive_floats_with_precision(precs.0), + exhaustive_positive_floats_with_precision(precs.1), + )) + } +} + +fn exhaustive_float_pairs_with_precisions(precisions: It<(u64, u64)>) -> It<(Float, Float)> { + Box::new( + exhaustive_dependent_pairs( + ruler_sequence(), + precisions, + FloatPairWithPrecisionRangesGenerator, + ) + .map(|p| p.1), + ) +} + // -- (Float, Float) -- pub fn exhaustive_float_pair_gen() -> It<(Float, Float)> { @@ -199,6 +234,26 @@ pub fn exhaustive_float_pair_gen_var_7() -> It<(Float, Float)> { exhaustive_float_pairs_with_precision_inclusive_range(Limb::WIDTH * 3, u64::MAX) } +pub fn exhaustive_float_pair_gen_var_8() -> It<(Float, Float)> { + exhaustive_float_pairs_with_precisions(Box::new( + exhaustive_pairs( + exhaustive_positive_primitive_ints(), + primitive_int_increasing_inclusive_range(1, Limb::WIDTH), + ) + .filter(|&(x, y)| x != y), + )) +} + +pub fn exhaustive_float_pair_gen_var_9() -> It<(Float, Float)> { + exhaustive_float_pairs_with_precisions(Box::new( + exhaustive_pairs( + exhaustive_positive_primitive_ints(), + primitive_int_increasing_inclusive_range(Limb::WIDTH + 1, u64::MAX), + ) + .filter(|&(x, y)| x != y), + )) +} + // -- (Float, Float, Float) -- pub fn exhaustive_float_triple_gen() -> It<(Float, Float, Float)> { @@ -283,15 +338,16 @@ pub(crate) fn add_prec_round_valid(x: &Float, y: &Float, prec: u64, rm: Rounding pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_1( ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( - exhaustive_quadruples_xxyz_custom_output( - exhaustive_floats(), - exhaustive_positive_primitive_ints::(), + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_xxy_custom_output( + exhaustive_floats(), + exhaustive_positive_primitive_ints::(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), exhaustive_rounding_modes(), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::tiny(), - BitDistributorOutputType::tiny(), - ) + ))) .filter(|(x, y, prec, rm)| add_prec_round_valid(x, y, *prec, *rm)), ) } @@ -315,15 +371,16 @@ pub(crate) fn sub_prec_round_valid(x: &Float, y: &Float, prec: u64, rm: Rounding pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_2( ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( - exhaustive_quadruples_xxyz_custom_output( - exhaustive_floats(), - exhaustive_positive_primitive_ints::(), + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_xxy_custom_output( + exhaustive_floats(), + exhaustive_positive_primitive_ints::(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), exhaustive_rounding_modes(), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::tiny(), - BitDistributorOutputType::tiny(), - ) + ))) .filter(|(x, y, prec, rm)| sub_prec_round_valid(x, y, *prec, *rm)), ) } @@ -347,19 +404,56 @@ pub(crate) fn mul_prec_round_valid(x: &Float, y: &Float, prec: u64, rm: Rounding pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_3( ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( - exhaustive_quadruples_xxyz_custom_output( - exhaustive_floats(), - exhaustive_positive_primitive_ints::(), + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_xxy_custom_output( + exhaustive_floats(), + exhaustive_positive_primitive_ints::(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), exhaustive_rounding_modes(), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::tiny(), - BitDistributorOutputType::tiny(), - ) + ))) .filter(|(x, y, prec, rm)| mul_prec_round_valid(x, y, *prec, *rm)), ) } +pub(crate) fn div_prec_round_valid(x: &Float, y: &Float, prec: u64, rm: RoundingMode) -> bool { + if rm != Exact || *y == 0u32 { + return true; + } + if let (Ok(rx), Ok(ry)) = (Rational::try_from(x), Rational::try_from(y)) { + if let Ok(quotient) = Float::try_from(rx / ry) { + if let Some(min_prec) = quotient.get_min_prec() { + prec >= min_prec + } else { + true + } + } else { + false + } + } else { + true + } +} + +pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_4( +) -> It<(Float, Float, u64, RoundingMode)> { + Box::new( + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_xxy_custom_output( + exhaustive_floats(), + exhaustive_positive_primitive_ints::(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm)), + ) +} + // -- (Float, Float, Rational) -- pub fn exhaustive_float_float_rational_triple_gen() -> It<(Float, Float, Rational)> { @@ -389,8 +483,11 @@ pub(crate) fn add_round_valid(x: &Float, y: &Float, rm: RoundingMode) -> bool { pub fn exhaustive_float_float_rounding_mode_triple_gen_var_1() -> It<(Float, Float, RoundingMode)> { Box::new( - exhaustive_triples_xxy(exhaustive_floats(), exhaustive_rounding_modes()) - .filter(|(x, y, rm)| add_round_valid(x, y, *rm)), + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_pairs_from_single(exhaustive_floats()), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| add_round_valid(x, y, *rm)), ) } @@ -412,8 +509,11 @@ pub(crate) fn sub_round_valid(x: &Float, y: &Float, rm: RoundingMode) -> bool { pub fn exhaustive_float_float_rounding_mode_triple_gen_var_2() -> It<(Float, Float, RoundingMode)> { Box::new( - exhaustive_triples_xxy(exhaustive_floats(), exhaustive_rounding_modes()) - .filter(|(x, y, rm)| sub_round_valid(x, y, *rm)), + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_float_pair_gen_var_2(), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| sub_round_valid(x, y, *rm)), ) } @@ -569,8 +669,11 @@ pub(crate) fn mul_round_valid(x: &Float, y: &Float, rm: RoundingMode) -> bool { pub fn exhaustive_float_float_rounding_mode_triple_gen_var_16() -> It<(Float, Float, RoundingMode)> { Box::new( - exhaustive_triples_xxy(exhaustive_floats(), exhaustive_rounding_modes()) - .filter(|(x, y, rm)| mul_round_valid(x, y, *rm)), + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_float_pair_gen_var_2(), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| mul_round_valid(x, y, *rm)), ) } @@ -640,6 +743,91 @@ pub fn exhaustive_float_float_rounding_mode_triple_gen_var_22() -> It<(Float, Fl ) } +pub(crate) fn div_round_valid(x: &Float, y: &Float, rm: RoundingMode) -> bool { + if rm != Exact || *y == 0u32 { + return true; + } + if let (Some(x_prec), Some(y_prec)) = (x.get_prec(), y.get_prec()) { + if let Ok(quotient) = Float::try_from(Rational::exact_from(x) / Rational::exact_from(y)) { + if let Some(min_prec) = quotient.get_min_prec() { + max(x_prec, y_prec) >= min_prec + } else { + true + } + } else { + false + } + } else { + true + } +} + +pub fn exhaustive_float_float_rounding_mode_triple_gen_var_23() -> It<(Float, Float, RoundingMode)> +{ + Box::new( + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_float_pair_gen_var_2(), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| div_round_valid(x, y, *rm)), + ) +} + +pub fn exhaustive_float_float_rounding_mode_triple_gen_var_24() -> It<(Float, Float, RoundingMode)> +{ + Box::new( + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_float_pair_gen_var_2(), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| div_round_valid(x, y, *rm)), + ) +} + +pub fn exhaustive_float_float_rounding_mode_triple_gen_var_25() -> It<(Float, Float, RoundingMode)> +{ + Box::new( + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_float_pair_gen_var_3(), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| div_round_valid(x, y, *rm)), + ) +} + +pub fn exhaustive_float_float_rounding_mode_triple_gen_var_26() -> It<(Float, Float, RoundingMode)> +{ + Box::new( + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_float_pair_gen_var_4(), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| div_round_valid(x, y, *rm)), + ) +} + +pub fn exhaustive_float_float_rounding_mode_triple_gen_var_27() -> It<(Float, Float, RoundingMode)> +{ + Box::new( + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_float_pair_gen_var_8(), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| div_round_valid(x, y, *rm)), + ) +} + +pub fn exhaustive_float_float_rounding_mode_triple_gen_var_28() -> It<(Float, Float, RoundingMode)> +{ + Box::new( + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_float_pair_gen_var_9(), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| div_round_valid(x, y, *rm)), + ) +} + // -- (Float, Integer) -- pub fn exhaustive_float_integer_pair_gen() -> It<(Float, Integer)> { @@ -811,6 +999,36 @@ pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_2() -> It<(Float, )) } +pub fn reciprocal_prec_round_valid(x: &Float, prec: u64, rm: RoundingMode) -> bool { + if rm != Exact || *x == 0 { + return true; + } + if let Ok(rx) = Rational::try_from(x) { + if let Ok(reciprocal) = Float::try_from(rx.reciprocal()) { + if let Some(min_prec) = reciprocal.get_min_prec() { + prec >= min_prec + } else { + true + } + } else { + false + } + } else { + true + } +} + +pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_3() -> It<(Float, u64, RoundingMode)> +{ + reshape_2_1_to_3(Box::new( + lex_pairs( + exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_positive_primitive_ints()), + exhaustive_rounding_modes(), + ) + .filter(|&((ref x, p), rm)| reciprocal_prec_round_valid(x, p, rm)), + )) +} + // -- (Float, Rational) -- pub fn exhaustive_float_rational_pair_gen() -> It<(Float, Rational)> { @@ -843,7 +1061,7 @@ pub fn exhaustive_float_rational_unsigned_triple_gen_var_1 // -- (Float, Rational, PrimitiveUnsigned, RoundingMode) -- -pub(crate) fn add_prec_round_rational_valid( +pub(crate) fn add_rational_prec_round_valid( x: &Float, y: &Rational, prec: u64, @@ -870,21 +1088,22 @@ pub(crate) fn add_prec_round_rational_valid( pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_1( ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( - exhaustive_quadruples_custom_output( - exhaustive_floats(), - exhaustive_rationals(), - exhaustive_positive_primitive_ints(), + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_custom_output( + exhaustive_floats(), + exhaustive_rationals(), + exhaustive_positive_primitive_ints(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), exhaustive_rounding_modes(), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::tiny(), - BitDistributorOutputType::normal(1), - ) - .filter(|(x, y, prec, rm)| add_prec_round_rational_valid(x, y, *prec, *rm)), + ))) + .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } -pub(crate) fn sub_prec_round_rational_valid( +pub(crate) fn sub_rational_prec_round_valid( x: &Float, y: &Rational, prec: u64, @@ -911,21 +1130,22 @@ pub(crate) fn sub_prec_round_rational_valid( pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_2( ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( - exhaustive_quadruples_custom_output( - exhaustive_floats(), - exhaustive_rationals(), - exhaustive_positive_primitive_ints(), + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_custom_output( + exhaustive_floats(), + exhaustive_rationals(), + exhaustive_positive_primitive_ints(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), exhaustive_rounding_modes(), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::tiny(), - BitDistributorOutputType::normal(1), - ) - .filter(|(x, y, prec, rm)| sub_prec_round_rational_valid(x, y, *prec, *rm)), + ))) + .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } -pub(crate) fn mul_prec_round_rational_valid( +pub(crate) fn mul_rational_prec_round_valid( x: &Float, y: &Rational, prec: u64, @@ -952,17 +1172,102 @@ pub(crate) fn mul_prec_round_rational_valid( pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_3( ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( - exhaustive_quadruples_custom_output( - exhaustive_floats(), - exhaustive_rationals(), - exhaustive_positive_primitive_ints(), + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_custom_output( + exhaustive_floats(), + exhaustive_rationals(), + exhaustive_positive_primitive_ints(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), exhaustive_rounding_modes(), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::normal(1), - BitDistributorOutputType::tiny(), - BitDistributorOutputType::normal(1), - ) - .filter(|(x, y, prec, rm)| mul_prec_round_rational_valid(x, y, *prec, *rm)), + ))) + .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), + ) +} + +pub(crate) fn div_rational_prec_round_valid( + x: &Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> bool { + if rm != Exact || *y == 0u32 { + return true; + } + if let Ok(rx) = Rational::try_from(x) { + if let Ok(quotient) = Float::try_from(rx / y) { + if let Some(min_prec) = quotient.get_min_prec() { + prec >= min_prec + } else { + true + } + } else { + false + } + } else { + true + } +} + +pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_4( +) -> It<(Float, Rational, u64, RoundingMode)> { + Box::new( + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_custom_output( + exhaustive_floats(), + exhaustive_rationals(), + exhaustive_positive_primitive_ints(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), + ) +} + +pub(crate) fn rational_div_float_prec_round_valid( + x: &Float, + y: &Rational, + prec: u64, + rm: RoundingMode, +) -> bool { + if rm != Exact || *x == 0u32 { + return true; + } + if let Ok(rx) = Rational::try_from(x) { + if let Ok(quotient) = Float::try_from(y / rx) { + if let Some(min_prec) = quotient.get_min_prec() { + prec >= min_prec + } else { + true + } + } else { + false + } + } else { + true + } +} + +pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_5( +) -> It<(Float, Rational, u64, RoundingMode)> { + Box::new( + reshape_3_1_to_4(Box::new(lex_pairs( + exhaustive_triples_custom_output( + exhaustive_floats(), + exhaustive_rationals(), + exhaustive_positive_primitive_ints(), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::normal(1), + BitDistributorOutputType::tiny(), + ), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } @@ -977,7 +1282,7 @@ pub fn exhaustive_float_rational_rational_triple_gen() -> It<(Float, Rational, R // -- (Float, Rational, RoundingMode) -- -pub(crate) fn add_round_rational_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { +pub(crate) fn add_rational_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { if rm != Exact { return true; } @@ -1000,16 +1305,15 @@ pub(crate) fn add_round_rational_valid(x: &Float, y: &Rational, rm: RoundingMode pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_1( ) -> It<(Float, Rational, RoundingMode)> { Box::new( - exhaustive_triples( - exhaustive_floats(), - exhaustive_rationals(), + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), - ) - .filter(|(x, y, rm)| add_round_rational_valid(x, y, *rm)), + ))) + .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } -pub(crate) fn sub_round_rational_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { +pub(crate) fn sub_rational_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { if rm != Exact { return true; } @@ -1032,12 +1336,11 @@ pub(crate) fn sub_round_rational_valid(x: &Float, y: &Rational, rm: RoundingMode pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_2( ) -> It<(Float, Rational, RoundingMode)> { Box::new( - exhaustive_triples( - exhaustive_floats(), - exhaustive_rationals(), + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), - ) - .filter(|(x, y, rm)| sub_round_rational_valid(x, y, *rm)), + ))) + .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } @@ -1050,13 +1353,13 @@ pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_3( )) } -pub(crate) fn mul_round_rational_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { +pub(crate) fn mul_rational_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { if rm != Exact { return true; } if let Some(x_prec) = x.get_prec() { - if let Ok(sum) = Float::try_from(Rational::exact_from(x) * y) { - if let Some(min_prec) = sum.get_min_prec() { + if let Ok(product) = Float::try_from(Rational::exact_from(x) * y) { + if let Some(min_prec) = product.get_min_prec() { x_prec >= min_prec } else { true @@ -1073,12 +1376,72 @@ pub(crate) fn mul_round_rational_valid(x: &Float, y: &Rational, rm: RoundingMode pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_4( ) -> It<(Float, Rational, RoundingMode)> { Box::new( - exhaustive_triples( - exhaustive_floats(), - exhaustive_rationals(), + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), - ) - .filter(|(x, y, rm)| mul_round_rational_valid(x, y, *rm)), + ))) + .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), + ) +} + +pub(crate) fn div_rational_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { + if rm != Exact || *y == 0 { + return true; + } + if let Some(x_prec) = x.get_prec() { + if let Ok(quotient) = Float::try_from(Rational::exact_from(x) / y) { + if let Some(min_prec) = quotient.get_min_prec() { + x_prec >= min_prec + } else { + true + } + } else { + false + } + } else { + // y must be representable by precision-1 float + y.is_power_of_2() + } +} + +pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_5( +) -> It<(Float, Rational, RoundingMode)> { + Box::new( + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), + ) +} + +pub(crate) fn rational_div_float_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { + if rm != Exact || *x == 0u32 { + return true; + } + if let Some(prec) = x.get_prec() { + if let Ok(quotient) = Float::try_from(y / Rational::exact_from(x)) { + if let Some(min_prec) = quotient.get_min_prec() { + prec >= min_prec + } else { + true + } + } else { + false + } + } else { + true + } +} + +pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_6( +) -> It<(Float, Rational, RoundingMode)> { + Box::new( + reshape_2_1_to_3(Box::new(lex_pairs( + exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), + exhaustive_rounding_modes(), + ))) + .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } @@ -1278,6 +1641,75 @@ pub fn exhaustive_float_rounding_mode_pair_gen_var_12() -> It<(Float, RoundingMo ) } +pub(crate) fn reciprocal_round_valid(x: &Float, rm: RoundingMode) -> bool { + if rm != Exact || *x == 0 { + return true; + } + if let Some(x_prec) = x.get_prec() { + if let Ok(reciprocal) = Float::try_from(Rational::exact_from(x).reciprocal()) { + if let Some(min_prec) = reciprocal.get_min_prec() { + x_prec >= min_prec + } else { + true + } + } else { + false + } + } else { + true + } +} + +pub fn exhaustive_float_rounding_mode_pair_gen_var_13() -> It<(Float, RoundingMode)> { + Box::new( + lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn exhaustive_float_rounding_mode_pair_gen_var_14() -> It<(Float, RoundingMode)> { + Box::new( + lex_pairs( + exhaustive_floats_with_precision_inclusive_range(1, Limb::WIDTH - 1), + exhaustive_rounding_modes(), + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn exhaustive_float_rounding_mode_pair_gen_var_15() -> It<(Float, RoundingMode)> { + Box::new( + lex_pairs( + exhaustive_positive_floats_with_precision(Limb::WIDTH), + exhaustive_rounding_modes(), + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn exhaustive_float_rounding_mode_pair_gen_var_16() -> It<(Float, RoundingMode)> { + Box::new( + lex_pairs( + exhaustive_floats_with_precision_inclusive_range( + Limb::WIDTH + 1, + (Limb::WIDTH << 1) - 1, + ), + exhaustive_rounding_modes(), + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn exhaustive_float_rounding_mode_pair_gen_var_17() -> It<(Float, RoundingMode)> { + Box::new( + lex_pairs( + exhaustive_floats_with_precision_inclusive_range(Limb::WIDTH + 1, u64::MAX), + exhaustive_rounding_modes(), + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-nz. diff --git a/malachite-float/src/test_util/generators/mod.rs b/malachite-float/src/test_util/generators/mod.rs index efb8b01e9..ac27af84d 100644 --- a/malachite-float/src/test_util/generators/mod.rs +++ b/malachite-float/src/test_util/generators/mod.rs @@ -7,8 +7,10 @@ // 3 of the License, or (at your option) any later version. See . use crate::test_util::generators::common::{ + float_float_anything_rounding_mode_quadruple_rm, float_float_anything_triple_rm, float_float_rounding_mode_triple_rm, float_integer_pair_rm, float_natural_pair_rm, float_pair_rm, float_primitive_float_pair_rm, float_primitive_int_pair_rm, + float_rational_anything_rounding_mode_quadruple_rm, float_rational_anything_triple_rm, float_rational_pair_rm, float_rational_rounding_mode_triple_rm, float_rm, float_rounding_mode_pair_rm, float_unsigned_rounding_mode_triple_rm, }; @@ -142,6 +144,15 @@ pub fn float_gen_var_10() -> Generator { ) } +// All floats with a precision greater than `Limb::WIDTH` * 2. +pub fn float_gen_var_11() -> Generator { + Generator::new( + &exhaustive_float_gen_var_11, + &random_float_gen_var_11, + &special_random_float_gen_var_11, + ) +} + // -- (Float, Float) -- pub fn float_pair_gen() -> Generator<(Float, Float)> { @@ -227,6 +238,26 @@ pub fn float_pair_gen_var_7() -> Generator<(Float, Float)> { ) } +// All pairs of positive floats with different precisions, such that the precision of the second +// float is less than or equal to `Limb::WIDTH`. +pub fn float_pair_gen_var_8() -> Generator<(Float, Float)> { + Generator::new( + &exhaustive_float_pair_gen_var_8, + &random_float_pair_gen_var_8, + &special_random_float_pair_gen_var_8, + ) +} + +// All pairs of positive floats with different precisions, such that the precision of the second +// float is greater than `Limb::WIDTH`. +pub fn float_pair_gen_var_9() -> Generator<(Float, Float)> { + Generator::new( + &exhaustive_float_pair_gen_var_9, + &random_float_pair_gen_var_9, + &special_random_float_pair_gen_var_9, + ) +} + // -- (Float, Float, Float) -- pub fn float_triple_gen() -> Generator<(Float, Float, Float)> { @@ -297,6 +328,21 @@ pub fn float_float_unsigned_triple_gen_var_1() -> Generato ) } +pub fn float_float_unsigned_triple_gen_var_1_rm( +) -> Generator<((rug::Float, rug::Float, T), (Float, Float, T))> { + Generator::new( + &|| float_float_anything_triple_rm(exhaustive_float_float_unsigned_triple_gen_var_1()), + &|config| { + float_float_anything_triple_rm(random_float_float_unsigned_triple_gen_var_1(config)) + }, + &|config| { + float_float_anything_triple_rm(special_random_float_float_unsigned_triple_gen_var_1( + config, + )) + }, + ) +} + // -- (Float, Float, PrimitiveUnsigned, RoundingMode) -- // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::add_prec_round`. @@ -309,6 +355,29 @@ pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_1( ) } +pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_1_rm() -> Generator<( + (rug::Float, rug::Float, u64, rug::float::Round), + (Float, Float, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_float_anything_rounding_mode_quadruple_rm( + exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_1(), + ) + }, + &|config| { + float_float_anything_rounding_mode_quadruple_rm( + random_float_float_unsigned_rounding_mode_quadruple_gen_var_1(config), + ) + }, + &|config| { + float_float_anything_rounding_mode_quadruple_rm( + special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_1(config), + ) + }, + ) +} + // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::sub_prec_round`. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_2( ) -> Generator<(Float, Float, u64, RoundingMode)> { @@ -319,6 +388,29 @@ pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_2( ) } +pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_2_rm() -> Generator<( + (rug::Float, rug::Float, u64, rug::float::Round), + (Float, Float, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_float_anything_rounding_mode_quadruple_rm( + exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_2(), + ) + }, + &|config| { + float_float_anything_rounding_mode_quadruple_rm( + random_float_float_unsigned_rounding_mode_quadruple_gen_var_2(config), + ) + }, + &|config| { + float_float_anything_rounding_mode_quadruple_rm( + special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_2(config), + ) + }, + ) +} + // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::mul_prec_round`. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_3( ) -> Generator<(Float, Float, u64, RoundingMode)> { @@ -329,6 +421,62 @@ pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_3( ) } +pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_3_rm() -> Generator<( + (rug::Float, rug::Float, u64, rug::float::Round), + (Float, Float, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_float_anything_rounding_mode_quadruple_rm( + exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_3(), + ) + }, + &|config| { + float_float_anything_rounding_mode_quadruple_rm( + random_float_float_unsigned_rounding_mode_quadruple_gen_var_3(config), + ) + }, + &|config| { + float_float_anything_rounding_mode_quadruple_rm( + special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_3(config), + ) + }, + ) +} + +// All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::div_prec_round`. +pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_4( +) -> Generator<(Float, Float, u64, RoundingMode)> { + Generator::new( + &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_4, + &random_float_float_unsigned_rounding_mode_quadruple_gen_var_4, + &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_4, + ) +} + +pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_4_rm() -> Generator<( + (rug::Float, rug::Float, u64, rug::float::Round), + (Float, Float, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_float_anything_rounding_mode_quadruple_rm( + exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_4(), + ) + }, + &|config| { + float_float_anything_rounding_mode_quadruple_rm( + random_float_float_unsigned_rounding_mode_quadruple_gen_var_4(config), + ) + }, + &|config| { + float_float_anything_rounding_mode_quadruple_rm( + special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_4(config), + ) + }, + ) +} + // -- (Float, Float, Rational) -- pub fn float_float_rational_triple_gen() -> Generator<(Float, Float, Rational)> { @@ -625,6 +773,91 @@ pub fn float_float_rounding_mode_triple_gen_var_22() -> Generator<(Float, Float, ) } +// All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`. +pub fn float_float_rounding_mode_triple_gen_var_23() -> Generator<(Float, Float, RoundingMode)> { + Generator::new( + &exhaustive_float_float_rounding_mode_triple_gen_var_23, + &random_float_float_rounding_mode_triple_gen_var_23, + &special_random_float_float_rounding_mode_triple_gen_var_23, + ) +} + +pub fn float_float_rounding_mode_triple_gen_var_23_rm() -> Generator<( + (rug::Float, rug::Float, rug::float::Round), + (Float, Float, RoundingMode), +)> { + Generator::new( + &|| { + float_float_rounding_mode_triple_rm( + exhaustive_float_float_rounding_mode_triple_gen_var_23(), + ) + }, + &|config| { + float_float_rounding_mode_triple_rm(random_float_float_rounding_mode_triple_gen_var_23( + config, + )) + }, + &|config| { + float_float_rounding_mode_triple_rm( + special_random_float_float_rounding_mode_triple_gen_var_23(config), + ) + }, + ) +} + +// All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the +// `Float`s have the same precision, which is greater than zero and less than `Limb::WIDTH`. +pub fn float_float_rounding_mode_triple_gen_var_24() -> Generator<(Float, Float, RoundingMode)> { + Generator::new( + &exhaustive_float_float_rounding_mode_triple_gen_var_24, + &random_float_float_rounding_mode_triple_gen_var_24, + &special_random_float_float_rounding_mode_triple_gen_var_24, + ) +} + +// All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the +// `Float`s have the same precision, which is `Limb::WIDTH`. +pub fn float_float_rounding_mode_triple_gen_var_25() -> Generator<(Float, Float, RoundingMode)> { + Generator::new( + &exhaustive_float_float_rounding_mode_triple_gen_var_25, + &random_float_float_rounding_mode_triple_gen_var_25, + &special_random_float_float_rounding_mode_triple_gen_var_25, + ) +} + +// All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the +// `Float`s have the same precision, which is greater than `Limb::WIDTH` and less than twice +// `Limb::WIDTH`. +pub fn float_float_rounding_mode_triple_gen_var_26() -> Generator<(Float, Float, RoundingMode)> { + Generator::new( + &exhaustive_float_float_rounding_mode_triple_gen_var_26, + &random_float_float_rounding_mode_triple_gen_var_26, + &special_random_float_float_rounding_mode_triple_gen_var_26, + ) +} + +// All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the +// `Float`s have different precisions and that the precision of the second float is less than or +// equal to `Limb::WIDTH`. +pub fn float_float_rounding_mode_triple_gen_var_27() -> Generator<(Float, Float, RoundingMode)> { + Generator::new( + &exhaustive_float_float_rounding_mode_triple_gen_var_27, + &random_float_float_rounding_mode_triple_gen_var_27, + &special_random_float_float_rounding_mode_triple_gen_var_27, + ) +} + +// All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the +// `Float`s have different precisions and that the precision of the second float is greater than +// `Limb::WIDTH`. +pub fn float_float_rounding_mode_triple_gen_var_28() -> Generator<(Float, Float, RoundingMode)> { + Generator::new( + &exhaustive_float_float_rounding_mode_triple_gen_var_28, + &random_float_float_rounding_mode_triple_gen_var_28, + &special_random_float_float_rounding_mode_triple_gen_var_28, + ) +} + // -- (Float, Integer) -- pub fn float_integer_pair_gen() -> Generator<(Float, Integer)> { @@ -893,6 +1126,61 @@ pub fn float_unsigned_rounding_mode_triple_gen_var_2() -> Generator<(Float, u64, ) } +pub fn float_unsigned_rounding_mode_triple_gen_var_2_rm() -> Generator<( + (rug::Float, u64, rug::float::Round), + (Float, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_unsigned_rounding_mode_triple_rm( + exhaustive_float_unsigned_rounding_mode_triple_gen_var_2(), + ) + }, + &|config| { + float_unsigned_rounding_mode_triple_rm( + random_float_unsigned_rounding_mode_triple_gen_var_2(config), + ) + }, + &|config| { + float_unsigned_rounding_mode_triple_rm( + special_random_float_unsigned_rounding_mode_triple_gen_var_2(config), + ) + }, + ) +} + +// All `(Float, u64, RoundingMode)` that are valid inputs to `Float.reciprocal_prec_round`. +pub fn float_unsigned_rounding_mode_triple_gen_var_3() -> Generator<(Float, u64, RoundingMode)> { + Generator::new( + &exhaustive_float_unsigned_rounding_mode_triple_gen_var_3, + &random_float_unsigned_rounding_mode_triple_gen_var_3, + &special_random_float_unsigned_rounding_mode_triple_gen_var_3, + ) +} + +pub fn float_unsigned_rounding_mode_triple_gen_var_3_rm() -> Generator<( + (rug::Float, u64, rug::float::Round), + (Float, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_unsigned_rounding_mode_triple_rm( + exhaustive_float_unsigned_rounding_mode_triple_gen_var_3(), + ) + }, + &|config| { + float_unsigned_rounding_mode_triple_rm( + random_float_unsigned_rounding_mode_triple_gen_var_3(config), + ) + }, + &|config| { + float_unsigned_rounding_mode_triple_rm( + special_random_float_unsigned_rounding_mode_triple_gen_var_3(config), + ) + }, + ) +} + // -- (Float, Rational) -- pub fn float_rational_pair_gen() -> Generator<(Float, Rational)> { @@ -932,10 +1220,30 @@ pub fn float_rational_unsigned_triple_gen_var_1( ) } +pub fn float_rational_unsigned_triple_gen_var_1_rm( +) -> Generator<((rug::Float, rug::Rational, T), (Float, Rational, T))> { + Generator::new( + &|| { + let ef = exhaustive_float_rational_unsigned_triple_gen_var_1(); + float_rational_anything_triple_rm(ef) + }, + &|config| { + float_rational_anything_triple_rm(random_float_rational_unsigned_triple_gen_var_1( + config, + )) + }, + &|config| { + float_rational_anything_triple_rm( + special_random_float_rational_unsigned_triple_gen_var_1(config), + ) + }, + ) +} + // -- (Float, Rational, PrimitiveUnsigned, RoundingMode) -- // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to -// `Float::add_prec_round_rational`. +// `Float::add_rational_prec_round`. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_1( ) -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( @@ -945,8 +1253,31 @@ pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_1( ) } +pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_1_rm() -> Generator<( + (rug::Float, rug::Rational, u64, rug::float::Round), + (Float, Rational, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_rational_anything_rounding_mode_quadruple_rm( + exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_1(), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1(config), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1(config), + ) + }, + ) +} + // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to -// `Float::sub_prec_round_rational`. +// `Float::sub_rational_prec_round`. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_2( ) -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( @@ -956,8 +1287,31 @@ pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_2( ) } +pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_2_rm() -> Generator<( + (rug::Float, rug::Rational, u64, rug::float::Round), + (Float, Rational, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_rational_anything_rounding_mode_quadruple_rm( + exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_2(), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2(config), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2(config), + ) + }, + ) +} + // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to -// `Float::mul_prec_round_rational`. +// `Float::mul_rational_prec_round`. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_3( ) -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( @@ -967,6 +1321,97 @@ pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_3( ) } +pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_3_rm() -> Generator<( + (rug::Float, rug::Rational, u64, rug::float::Round), + (Float, Rational, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_rational_anything_rounding_mode_quadruple_rm( + exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_3(), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3(config), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3(config), + ) + }, + ) +} + +// All `(Float, Rational, u64, RoundingMode)` that are valid inputs to +// `Float::div_prec_round_rational`. +pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_4( +) -> Generator<(Float, Rational, u64, RoundingMode)> { + Generator::new( + &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_4, + &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4, + &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4, + ) +} + +pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_4_rm() -> Generator<( + (rug::Float, rug::Rational, u64, rug::float::Round), + (Float, Rational, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_rational_anything_rounding_mode_quadruple_rm( + exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_4(), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4(config), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4(config), + ) + }, + ) +} + +// All `(Float, Rational, u64, RoundingMode)` that are valid inputs to +// `Float::rational_div_float_prec_round` (with the first two arguments reversed). +pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_5( +) -> Generator<(Float, Rational, u64, RoundingMode)> { + Generator::new( + &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_5, + &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5, + &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5, + ) +} + +pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_5_rm() -> Generator<( + (rug::Float, rug::Rational, u64, rug::float::Round), + (Float, Rational, u64, RoundingMode), +)> { + Generator::new( + &|| { + float_rational_anything_rounding_mode_quadruple_rm( + exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_5(), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5(config), + ) + }, + &|config| { + float_rational_anything_rounding_mode_quadruple_rm( + special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5(config), + ) + }, + ) +} + // -- (Float, Rational, Rational) -- pub fn float_rational_rational_triple_gen() -> Generator<(Float, Rational, Rational)> { @@ -999,8 +1444,7 @@ pub fn float_rational_rounding_mode_triple_gen_var_2() -> Generator<(Float, Rati ) } -// All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::add_round_rational` or -// `Float::sub_round_rational`, excluding those with `Exact`. +// All `(Float, Rational, RoundingMode)`, excluding those with `Exact`. pub fn float_rational_rounding_mode_triple_gen_var_3_rm() -> Generator<( (rug::Float, rug::Rational, rug::float::Round), (Float, Rational, RoundingMode), @@ -1034,6 +1478,50 @@ pub fn float_rational_rounding_mode_triple_gen_var_4() -> Generator<(Float, Rati ) } +// All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::div_round_rational`. +pub fn float_rational_rounding_mode_triple_gen_var_5() -> Generator<(Float, Rational, RoundingMode)> +{ + Generator::new( + &exhaustive_float_rational_rounding_mode_triple_gen_var_5, + &random_float_rational_rounding_mode_triple_gen_var_5, + &special_random_float_rational_rounding_mode_triple_gen_var_5, + ) +} + +// All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::rational_div_float_round` +// (with the first two arguments reversed). +pub fn float_rational_rounding_mode_triple_gen_var_6() -> Generator<(Float, Rational, RoundingMode)> +{ + Generator::new( + &exhaustive_float_rational_rounding_mode_triple_gen_var_6, + &random_float_rational_rounding_mode_triple_gen_var_6, + &special_random_float_rational_rounding_mode_triple_gen_var_6, + ) +} + +pub fn float_rational_rounding_mode_triple_gen_var_6_rm() -> Generator<( + (rug::Float, rug::Rational, rug::float::Round), + (Float, Rational, RoundingMode), +)> { + Generator::new( + &|| { + float_rational_rounding_mode_triple_rm( + exhaustive_float_rational_rounding_mode_triple_gen_var_6(), + ) + }, + &|config| { + float_rational_rounding_mode_triple_rm( + random_float_rational_rounding_mode_triple_gen_var_6(config), + ) + }, + &|config| { + float_rational_rounding_mode_triple_rm( + special_random_float_rational_rounding_mode_triple_gen_var_6(config), + ) + }, + ) +} + // -- (Float, RoundingMode) -- pub fn float_rounding_mode_pair_gen() -> Generator<(Float, RoundingMode)> { @@ -1184,6 +1672,66 @@ pub fn float_rounding_mode_pair_gen_var_12() -> Generator<(Float, RoundingMode)> ) } +// All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`. +pub fn float_rounding_mode_pair_gen_var_13() -> Generator<(Float, RoundingMode)> { + Generator::new( + &exhaustive_float_rounding_mode_pair_gen_var_13, + &random_float_rounding_mode_pair_gen_var_13, + &special_random_float_rounding_mode_pair_gen_var_13, + ) +} + +pub fn float_rounding_mode_pair_gen_var_13_rm( +) -> Generator<((rug::Float, rug::float::Round), (Float, RoundingMode))> { + Generator::new( + &|| float_rounding_mode_pair_rm(exhaustive_float_rounding_mode_pair_gen_var_13()), + &|config| float_rounding_mode_pair_rm(random_float_rounding_mode_pair_gen_var_13(config)), + &|config| { + float_rounding_mode_pair_rm(special_random_float_rounding_mode_pair_gen_var_13(config)) + }, + ) +} + +// All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` has a +// precision less than `Limb::WIDTH`. +pub fn float_rounding_mode_pair_gen_var_14() -> Generator<(Float, RoundingMode)> { + Generator::new( + &exhaustive_float_rounding_mode_pair_gen_var_14, + &random_float_rounding_mode_pair_gen_var_14, + &special_random_float_rounding_mode_pair_gen_var_14, + ) +} + +// All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` has +// precision `Limb::WIDTH`. +pub fn float_rounding_mode_pair_gen_var_15() -> Generator<(Float, RoundingMode)> { + Generator::new( + &exhaustive_float_rounding_mode_pair_gen_var_15, + &random_float_rounding_mode_pair_gen_var_15, + &special_random_float_rounding_mode_pair_gen_var_15, + ) +} + +// All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` has a +// precision greater than `Limb::WIDTH` and less than `Limb::WIDTH` * 2. +pub fn float_rounding_mode_pair_gen_var_16() -> Generator<(Float, RoundingMode)> { + Generator::new( + &exhaustive_float_rounding_mode_pair_gen_var_16, + &random_float_rounding_mode_pair_gen_var_16, + &special_random_float_rounding_mode_pair_gen_var_16, + ) +} + +// All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` has a +// precision greater than `Limb::WIDTH` * 2. +pub fn float_rounding_mode_pair_gen_var_17() -> Generator<(Float, RoundingMode)> { + Generator::new( + &exhaustive_float_rounding_mode_pair_gen_var_17, + &random_float_rounding_mode_pair_gen_var_17, + &special_random_float_rounding_mode_pair_gen_var_17, + ) +} + // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-nz. diff --git a/malachite-float/src/test_util/generators/random.rs b/malachite-float/src/test_util/generators/random.rs index ad45d81fd..f5ba11247 100644 --- a/malachite-float/src/test_util/generators/random.rs +++ b/malachite-float/src/test_util/generators/random.rs @@ -16,15 +16,17 @@ use crate::test_util::extra_variadic::{ random_triples_xxy, random_triples_xyy, }; use crate::test_util::generators::{ - add_prec_round_rational_valid, add_prec_round_valid, add_round_rational_valid, add_round_valid, - mul_prec_round_rational_valid, mul_prec_round_valid, mul_round_rational_valid, mul_round_valid, - square_prec_round_valid, square_round_valid, sub_prec_round_rational_valid, - sub_prec_round_valid, sub_round_rational_valid, sub_round_valid, + add_prec_round_valid, add_rational_prec_round_valid, add_rational_round_valid, add_round_valid, + div_prec_round_valid, div_rational_prec_round_valid, div_rational_round_valid, div_round_valid, + mul_prec_round_valid, mul_rational_prec_round_valid, mul_rational_round_valid, mul_round_valid, + rational_div_float_prec_round_valid, rational_div_float_round_valid, square_prec_round_valid, + square_round_valid, sub_prec_round_valid, sub_rational_prec_round_valid, + sub_rational_round_valid, sub_round_valid, }; use crate::test_util::generators::{ from_primitive_float_prec_round_valid, integer_rounding_from_float_valid, - natural_rounding_from_float_valid, set_prec_round_valid, signed_rounding_from_float_valid, - unsigned_rounding_from_float_valid, + natural_rounding_from_float_valid, reciprocal_prec_round_valid, reciprocal_round_valid, + set_prec_round_valid, signed_rounding_from_float_valid, unsigned_rounding_from_float_valid, }; use crate::Float; use crate::InnerFloat::Finite; @@ -169,6 +171,14 @@ pub fn random_float_gen_var_10(config: &GenConfig) -> It { ) } +pub fn random_float_gen_var_11(config: &GenConfig) -> It { + random_floats_with_precision_inclusive_range_to_infinity( + EXAMPLE_SEED, + config, + (Limb::WIDTH << 1) + 1, + ) +} + struct RandomFloatsWithPrecisionUniformInclusiveRange { seed: Seed, mean_exponent_n: u64, @@ -214,6 +224,31 @@ fn random_floats_with_precision_inclusive_range( }) } +fn random_floats_with_precision_inclusive_range_to_infinity( + seed: Seed, + config: &GenConfig, + prec_lo: u64, +) -> It { + let mean_precision = Rational::from_unsigneds( + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 64), + ) + Rational::from(prec_lo); + let (n, d) = mean_precision.into_numerator_and_denominator(); + Box::new(RandomFloatsWithPrecisionUniformInclusiveRange { + seed: seed.fork("floats"), + mean_exponent_n: config.get_or("mean_exponent_n", 64), + mean_exponent_d: config.get_or("mean_exponent_d", 1), + precisions: Box::new(geometric_random_unsigned_inclusive_range( + seed.fork("precisions"), + prec_lo, + u64::MAX, + u64::exact_from(&n), + u64::exact_from(&d), + )), + floats: HashMap::new(), + }) +} + struct RandomFloatPairsWithPrecisionUniformInclusiveRange { seed: Seed, mean_exponent_n: u64, @@ -240,6 +275,43 @@ impl Iterator for RandomFloatPairsWithPrecisionUniformInclusiveRange { } } +struct RandomFloatPairsWithPrecisions { + seed: Seed, + mean_exponent_n: u64, + mean_exponent_d: u64, + precisions: Box>, + floats: HashMap>, +} + +impl Iterator for RandomFloatPairsWithPrecisions { + type Item = (Float, Float); + + fn next(&mut self) -> Option<(Float, Float)> { + let precs = self.precisions.next().unwrap(); + let xs = self + .floats + .entry(precs.0) + .or_insert(random_positive_floats_with_precision( + self.seed.fork(&precs.0.to_string()), + self.mean_exponent_n, + self.mean_exponent_d, + precs.0, + )); + let x = xs.next().unwrap(); + let ys = self + .floats + .entry(precs.1) + .or_insert(random_positive_floats_with_precision( + self.seed.fork(&precs.1.to_string()), + self.mean_exponent_n, + self.mean_exponent_d, + precs.1, + )); + let y = ys.next().unwrap(); + Some((x, y)) + } +} + fn random_float_pairs_with_precision_inclusive_range( seed: Seed, config: &GenConfig, @@ -284,6 +356,20 @@ fn random_float_pairs_with_precision_inclusive_range_to_infinity( }) } +fn random_float_pairs_with_precisions( + seed: Seed, + config: &GenConfig, + precisions: It<(u64, u64)>, +) -> It<(Float, Float)> { + Box::new(RandomFloatPairsWithPrecisions { + seed: seed.fork("floats"), + mean_exponent_n: config.get_or("mean_exponent_n", 64), + mean_exponent_d: config.get_or("mean_exponent_d", 1), + precisions, + floats: HashMap::new(), + }) +} + // -- (Float, Float) -- pub fn random_float_pair_gen(config: &GenConfig) -> It<(Float, Float)> { @@ -362,6 +448,57 @@ pub fn random_float_pair_gen_var_7(config: &GenConfig) -> It<(Float, Float)> { ) } +pub fn random_float_pair_gen_var_8(config: &GenConfig) -> It<(Float, Float)> { + random_float_pairs_with_precisions( + EXAMPLE_SEED.fork("abc"), + config, + Box::new(random_pairs( + EXAMPLE_SEED.fork("precisions"), + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + &|seed| { + geometric_random_unsigned_inclusive_range( + seed, + 1, + Limb::WIDTH, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + )), + ) +} + +pub fn random_float_pair_gen_var_9(config: &GenConfig) -> It<(Float, Float)> { + random_float_pairs_with_precisions( + EXAMPLE_SEED.fork("abc"), + config, + Box::new(random_pairs( + EXAMPLE_SEED.fork("precisions"), + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + .map(|p: u64| p + Limb::WIDTH) + }, + )), + ) +} + // -- (Float, Float, Float) -- pub fn random_float_triple_gen(config: &GenConfig) -> It<(Float, Float, Float)> { @@ -602,6 +739,36 @@ pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_3( ) } +pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_4( + config: &GenConfig, +) -> It<(Float, Float, u64, RoundingMode)> { + Box::new( + random_quadruples_xxyz( + EXAMPLE_SEED, + &|seed| { + random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_small_n", 64), + config.get_or("mean_small_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm)), + ) +} + // -- (Float, Float, Rational) -- pub fn random_float_float_rational_triple_gen(config: &GenConfig) -> It<(Float, Float, Rational)> { @@ -1061,6 +1228,157 @@ pub fn random_float_float_rounding_mode_triple_gen_var_22( )) } +pub fn random_float_float_rounding_mode_triple_gen_var_23( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + Box::new( + random_triples_xxy( + EXAMPLE_SEED, + &|seed| { + random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, rm)| div_round_valid(x, y, *rm)), + ) +} + +pub fn random_float_float_rounding_mode_triple_gen_var_24( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_float_pairs_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + +pub fn random_float_float_rounding_mode_triple_gen_var_25( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_pairs_from_single(random_positive_floats_with_precision( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + Limb::WIDTH, + )) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + +pub fn random_float_float_rounding_mode_triple_gen_var_26( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_float_pairs_with_precision_inclusive_range( + seed, + config, + Limb::WIDTH + 1, + (Limb::WIDTH << 1) - 1, + ) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + +pub fn random_float_float_rounding_mode_triple_gen_var_27( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_float_pairs_with_precisions( + seed.fork("abc"), + config, + Box::new(random_pairs( + seed.fork("precisions"), + &|seed_2| { + geometric_random_positive_unsigneds( + seed_2, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + &|seed_2| { + geometric_random_unsigned_inclusive_range( + seed_2, + 1, + Limb::WIDTH, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + )), + ) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + +pub fn random_float_float_rounding_mode_triple_gen_var_28( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_float_pairs_with_precisions( + seed.fork("abc"), + config, + Box::new(random_pairs( + seed.fork("precisions"), + &|seed_2| { + geometric_random_positive_unsigneds( + seed_2, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + &|seed_2| { + geometric_random_positive_unsigneds( + seed_2, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + .map(|p: u64| p + Limb::WIDTH) + }, + )), + ) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + // -- (Float, Integer) -- pub fn random_float_integer_pair_gen(config: &GenConfig) -> It<(Float, Integer)> { @@ -1514,6 +1832,36 @@ pub fn random_float_unsigned_rounding_mode_triple_gen_var_2( ) } +pub fn random_float_unsigned_rounding_mode_triple_gen_var_3( + config: &GenConfig, +) -> It<(Float, u64, RoundingMode)> { + Box::new( + random_triples( + EXAMPLE_SEED, + &|seed| { + random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_small_n", 64), + config.get_or("mean_small_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|&(ref x, p, rm)| reciprocal_prec_round_valid(x, p, rm)), + ) +} + // -- (Float, Rational) -- pub fn random_float_rational_pair_gen(config: &GenConfig) -> It<(Float, Rational)> { @@ -1634,7 +1982,7 @@ pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1( }, &random_rounding_modes, ) - .filter(|(x, y, prec, rm)| add_prec_round_rational_valid(x, y, *prec, *rm)), + .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } @@ -1671,7 +2019,7 @@ pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2( }, &random_rounding_modes, ) - .filter(|(x, y, prec, rm)| sub_prec_round_rational_valid(x, y, *prec, *rm)), + .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } @@ -1708,7 +2056,81 @@ pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3( }, &random_rounding_modes, ) - .filter(|(x, y, prec, rm)| mul_prec_round_rational_valid(x, y, *prec, *rm)), + .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), + ) +} + +pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4( + config: &GenConfig, +) -> It<(Float, Rational, u64, RoundingMode)> { + Box::new( + random_quadruples( + EXAMPLE_SEED, + &|seed| { + random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + random_rationals( + seed, + config.get_or("mean_bits_n", 64), + config.get_or("mean_bits_d", 1), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_small_n", 64), + config.get_or("mean_small_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), + ) +} + +pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5( + config: &GenConfig, +) -> It<(Float, Rational, u64, RoundingMode)> { + Box::new( + random_quadruples( + EXAMPLE_SEED, + &|seed| { + random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + random_rationals( + seed, + config.get_or("mean_bits_n", 64), + config.get_or("mean_bits_d", 1), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_small_n", 64), + config.get_or("mean_small_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } @@ -1768,7 +2190,7 @@ pub fn random_float_rational_rounding_mode_triple_gen_var_1( }, &random_rounding_modes, ) - .filter(|(x, y, rm)| add_round_rational_valid(x, y, *rm)), + .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } @@ -1798,7 +2220,7 @@ pub fn random_float_rational_rounding_mode_triple_gen_var_2( }, &random_rounding_modes, ) - .filter(|(x, y, rm)| sub_round_rational_valid(x, y, *rm)), + .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } @@ -1855,7 +2277,67 @@ pub fn random_float_rational_rounding_mode_triple_gen_var_4( }, &random_rounding_modes, ) - .filter(|(x, y, rm)| mul_round_rational_valid(x, y, *rm)), + .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), + ) +} + +pub fn random_float_rational_rounding_mode_triple_gen_var_5( + config: &GenConfig, +) -> It<(Float, Rational, RoundingMode)> { + Box::new( + random_triples( + EXAMPLE_SEED, + &|seed| { + random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + random_rationals( + seed, + config.get_or("mean_bits_n", 64), + config.get_or("mean_bits_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), + ) +} + +pub fn random_float_rational_rounding_mode_triple_gen_var_6( + config: &GenConfig, +) -> It<(Float, Rational, RoundingMode)> { + Box::new( + random_triples( + EXAMPLE_SEED, + &|seed| { + random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + random_rationals( + seed, + config.get_or("mean_bits_n", 64), + config.get_or("mean_bits_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } @@ -2124,6 +2606,91 @@ pub fn random_float_rounding_mode_pair_gen_var_12(config: &GenConfig) -> It<(Flo ) } +pub fn random_float_rounding_mode_pair_gen_var_13(config: &GenConfig) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn random_float_rounding_mode_pair_gen_var_14(config: &GenConfig) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| random_floats_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1), + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn random_float_rounding_mode_pair_gen_var_15(config: &GenConfig) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_positive_floats_with_precision( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + Limb::WIDTH, + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn random_float_rounding_mode_pair_gen_var_16(config: &GenConfig) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_floats_with_precision_inclusive_range( + seed, + config, + Limb::WIDTH + 1, + (Limb::WIDTH << 1) - 1, + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn random_float_rounding_mode_pair_gen_var_17(config: &GenConfig) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_floats_with_precision_inclusive_range_to_infinity( + seed, + config, + Limb::WIDTH + 1, + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-nz. diff --git a/malachite-float/src/test_util/generators/special_random.rs b/malachite-float/src/test_util/generators/special_random.rs index 9e1c830e1..a6b886aff 100644 --- a/malachite-float/src/test_util/generators/special_random.rs +++ b/malachite-float/src/test_util/generators/special_random.rs @@ -16,15 +16,17 @@ use crate::test_util::extra_variadic::{ random_triples_xxy, random_triples_xyy, }; use crate::test_util::generators::{ - add_prec_round_rational_valid, add_prec_round_valid, add_round_rational_valid, add_round_valid, - mul_prec_round_rational_valid, mul_prec_round_valid, mul_round_rational_valid, mul_round_valid, - square_prec_round_valid, square_round_valid, sub_prec_round_rational_valid, - sub_prec_round_valid, sub_round_rational_valid, sub_round_valid, + add_prec_round_valid, add_rational_prec_round_valid, add_rational_round_valid, add_round_valid, + div_prec_round_valid, div_rational_prec_round_valid, div_rational_round_valid, div_round_valid, + mul_prec_round_valid, mul_rational_prec_round_valid, mul_rational_round_valid, mul_round_valid, + rational_div_float_prec_round_valid, rational_div_float_round_valid, reciprocal_round_valid, + square_prec_round_valid, square_round_valid, sub_prec_round_valid, + sub_rational_prec_round_valid, sub_rational_round_valid, sub_round_valid, }; use crate::test_util::generators::{ from_primitive_float_prec_round_valid, integer_rounding_from_float_valid, - natural_rounding_from_float_valid, set_prec_round_valid, signed_rounding_from_float_valid, - unsigned_rounding_from_float_valid, + natural_rounding_from_float_valid, reciprocal_prec_round_valid, set_prec_round_valid, + signed_rounding_from_float_valid, unsigned_rounding_from_float_valid, }; use crate::Float; use crate::InnerFloat::Finite; @@ -184,6 +186,14 @@ pub fn special_random_float_gen_var_10(config: &GenConfig) -> It { ) } +pub fn special_random_float_gen_var_11(config: &GenConfig) -> It { + striped_random_floats_with_precision_inclusive_range_to_infinity( + EXAMPLE_SEED, + config, + (Limb::WIDTH << 1) + 1, + ) +} + struct StripedRandomFloatsWithPrecisionUniformInclusiveRange { seed: Seed, mean_exponent_n: u64, @@ -235,6 +245,33 @@ fn striped_random_floats_with_precision_inclusive_range( }) } +fn striped_random_floats_with_precision_inclusive_range_to_infinity( + seed: Seed, + config: &GenConfig, + prec_lo: u64, +) -> It { + let mean_precision = Rational::from_unsigneds( + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 64), + ) + Rational::from(prec_lo); + let (n, d) = mean_precision.into_numerator_and_denominator(); + Box::new(StripedRandomFloatsWithPrecisionUniformInclusiveRange { + seed: seed.fork("floats"), + mean_exponent_n: config.get_or("mean_exponent_n", 64), + mean_exponent_d: config.get_or("mean_exponent_d", 1), + mean_stripe_n: config.get_or("mean_stripe_n", 64), + mean_stripe_d: config.get_or("mean_stripe_d", 1), + precisions: Box::new(geometric_random_unsigned_inclusive_range( + seed.fork("precisions"), + prec_lo, + u64::MAX, + u64::exact_from(&n), + u64::exact_from(&d), + )), + floats: HashMap::new(), + }) +} + struct StripedRandomFloatPairsWithPrecisionUniformInclusiveRange { seed: Seed, mean_exponent_n: u64, @@ -265,6 +302,49 @@ impl Iterator for StripedRandomFloatPairsWithPrecisionUniformInclusiveRange { } } +struct StripedRandomFloatPairsWithPrecisions { + seed: Seed, + mean_exponent_n: u64, + mean_exponent_d: u64, + mean_stripe_n: u64, + mean_stripe_d: u64, + precisions: Box>, + floats: HashMap>, +} + +impl Iterator for StripedRandomFloatPairsWithPrecisions { + type Item = (Float, Float); + + fn next(&mut self) -> Option<(Float, Float)> { + let precs = self.precisions.next().unwrap(); + let xs = + self.floats + .entry(precs.0) + .or_insert(striped_random_positive_floats_with_precision( + self.seed.fork(&precs.0.to_string()), + self.mean_exponent_n, + self.mean_exponent_d, + self.mean_stripe_n, + self.mean_stripe_d, + precs.0, + )); + let x = xs.next().unwrap(); + let ys = + self.floats + .entry(precs.1) + .or_insert(striped_random_positive_floats_with_precision( + self.seed.fork(&precs.1.to_string()), + self.mean_exponent_n, + self.mean_exponent_d, + self.mean_stripe_n, + self.mean_stripe_d, + precs.1, + )); + let y = ys.next().unwrap(); + Some((x, y)) + } +} + fn striped_random_float_pairs_with_precision_inclusive_range( seed: Seed, config: &GenConfig, @@ -313,6 +393,22 @@ fn striped_random_float_pairs_with_precision_inclusive_range_to_infinity( }) } +fn striped_random_float_pairs_with_precisions( + seed: Seed, + config: &GenConfig, + precisions: It<(u64, u64)>, +) -> It<(Float, Float)> { + Box::new(StripedRandomFloatPairsWithPrecisions { + seed: seed.fork("floats"), + mean_exponent_n: config.get_or("mean_exponent_n", 64), + mean_exponent_d: config.get_or("mean_exponent_d", 1), + mean_stripe_n: config.get_or("mean_stripe_n", 64), + mean_stripe_d: config.get_or("mean_stripe_d", 1), + precisions, + floats: HashMap::new(), + }) +} + // -- (Float, Float) -- pub fn special_random_float_pair_gen(config: &GenConfig) -> It<(Float, Float)> { @@ -404,6 +500,57 @@ pub fn special_random_float_pair_gen_var_7(config: &GenConfig) -> It<(Float, Flo ) } +pub fn special_random_float_pair_gen_var_8(config: &GenConfig) -> It<(Float, Float)> { + striped_random_float_pairs_with_precisions( + EXAMPLE_SEED, + config, + Box::new(random_pairs( + EXAMPLE_SEED.fork("precisions"), + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + &|seed| { + geometric_random_unsigned_inclusive_range( + seed, + 1, + Limb::WIDTH, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + )), + ) +} + +pub fn special_random_float_pair_gen_var_9(config: &GenConfig) -> It<(Float, Float)> { + striped_random_float_pairs_with_precisions( + EXAMPLE_SEED, + config, + Box::new(random_pairs( + EXAMPLE_SEED.fork("precisions"), + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + .map(|p: u64| p + Limb::WIDTH) + }, + )), + ) +} + // -- (Float, Float, Float) -- pub fn special_random_float_triple_gen(config: &GenConfig) -> It<(Float, Float, Float)> { @@ -596,7 +743,7 @@ pub fn special_random_float_float_unsigned_triple_gen_var_1 It<(Float, Float, u64, RoundingMode)> { + Box::new( + random_quadruples_xxyz( + EXAMPLE_SEED, + &|seed| { + striped_random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_small_n", 64), + config.get_or("mean_small_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm)), + ) +} + // -- (Float, Float, Rational) -- pub fn special_random_float_float_rational_triple_gen( @@ -1194,6 +1373,166 @@ pub fn special_random_float_float_rounding_mode_triple_gen_var_22( )) } +pub fn special_random_float_float_rounding_mode_triple_gen_var_23( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + Box::new( + random_triples_xxy( + EXAMPLE_SEED, + &|seed| { + striped_random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, rm)| div_round_valid(x, y, *rm)), + ) +} + +pub fn special_random_float_float_rounding_mode_triple_gen_var_24( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_float_pairs_with_precision_inclusive_range( + seed, + config, + 1, + Limb::WIDTH - 1, + ) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + +pub fn special_random_float_float_rounding_mode_triple_gen_var_25( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + random_pairs_from_single(striped_random_positive_floats_with_precision( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + Limb::WIDTH, + )) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + +pub fn special_random_float_float_rounding_mode_triple_gen_var_26( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_float_pairs_with_precision_inclusive_range( + seed, + config, + Limb::WIDTH + 1, + (Limb::WIDTH << 1) - 1, + ) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + +pub fn special_random_float_float_rounding_mode_triple_gen_var_27( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_float_pairs_with_precisions( + seed, + config, + Box::new(random_pairs( + seed.fork("precisions"), + &|seed_2| { + geometric_random_positive_unsigneds( + seed_2, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + &|seed_2| { + geometric_random_unsigned_inclusive_range( + seed_2, + 1, + Limb::WIDTH, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + )), + ) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + +pub fn special_random_float_float_rounding_mode_triple_gen_var_28( + config: &GenConfig, +) -> It<(Float, Float, RoundingMode)> { + reshape_2_1_to_3(Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_float_pairs_with_precisions( + seed, + config, + Box::new(random_pairs( + seed.fork("precisions"), + &|seed_2| { + geometric_random_positive_unsigneds( + seed_2, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + }, + &|seed_2| { + geometric_random_positive_unsigneds( + seed_2, + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + ) + .map(|p: u64| p + Limb::WIDTH) + }, + )), + ) + }, + &random_rounding_modes, + ) + .filter(|((x, y), rm)| div_round_valid(x, y, *rm)), + )) +} + // -- (Float, Integer) -- pub fn special_random_float_integer_pair_gen(config: &GenConfig) -> It<(Float, Integer)> { @@ -1725,6 +2064,38 @@ pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_2( ) } +pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_3( + config: &GenConfig, +) -> It<(Float, u64, RoundingMode)> { + Box::new( + random_triples( + EXAMPLE_SEED, + &|seed| { + striped_random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_small_n", 64), + config.get_or("mean_small_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|&(ref x, p, rm)| reciprocal_prec_round_valid(x, p, rm)), + ) +} + // -- (Float, Rational) -- pub fn special_random_float_rational_pair_gen(config: &GenConfig) -> It<(Float, Rational)> { @@ -1861,7 +2232,7 @@ pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1( }, &random_rounding_modes, ) - .filter(|(x, y, prec, rm)| add_prec_round_rational_valid(x, y, *prec, *rm)), + .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } @@ -1902,7 +2273,7 @@ pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2( }, &random_rounding_modes, ) - .filter(|(x, y, prec, rm)| sub_prec_round_rational_valid(x, y, *prec, *rm)), + .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } @@ -1943,7 +2314,89 @@ pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3( }, &random_rounding_modes, ) - .filter(|(x, y, prec, rm)| mul_prec_round_rational_valid(x, y, *prec, *rm)), + .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), + ) +} + +pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4( + config: &GenConfig, +) -> It<(Float, Rational, u64, RoundingMode)> { + Box::new( + random_quadruples( + EXAMPLE_SEED, + &|seed| { + striped_random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + striped_random_rationals( + seed, + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_bits_n", 64), + config.get_or("mean_bits_d", 1), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_small_n", 64), + config.get_or("mean_small_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), + ) +} + +pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5( + config: &GenConfig, +) -> It<(Float, Rational, u64, RoundingMode)> { + Box::new( + random_quadruples( + EXAMPLE_SEED, + &|seed| { + striped_random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + striped_random_rationals( + seed, + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_bits_n", 64), + config.get_or("mean_bits_d", 1), + ) + }, + &|seed| { + geometric_random_positive_unsigneds( + seed, + config.get_or("mean_small_n", 64), + config.get_or("mean_small_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } @@ -2011,7 +2464,7 @@ pub fn special_random_float_rational_rounding_mode_triple_gen_var_1( }, &random_rounding_modes, ) - .filter(|(x, y, rm)| add_round_rational_valid(x, y, *rm)), + .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } @@ -2045,7 +2498,7 @@ pub fn special_random_float_rational_rounding_mode_triple_gen_var_2( }, &random_rounding_modes, ) - .filter(|(x, y, rm)| sub_round_rational_valid(x, y, *rm)), + .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } @@ -2110,7 +2563,75 @@ pub fn special_random_float_rational_rounding_mode_triple_gen_var_4( }, &random_rounding_modes, ) - .filter(|(x, y, rm)| mul_round_rational_valid(x, y, *rm)), + .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), + ) +} + +pub fn special_random_float_rational_rounding_mode_triple_gen_var_5( + config: &GenConfig, +) -> It<(Float, Rational, RoundingMode)> { + Box::new( + random_triples( + EXAMPLE_SEED, + &|seed| { + striped_random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + striped_random_rationals( + seed, + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_bits_n", 64), + config.get_or("mean_bits_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), + ) +} + +pub fn special_random_float_rational_rounding_mode_triple_gen_var_6( + config: &GenConfig, +) -> It<(Float, Rational, RoundingMode)> { + Box::new( + random_triples( + EXAMPLE_SEED, + &|seed| { + striped_random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &|seed| { + striped_random_rationals( + seed, + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_bits_n", 64), + config.get_or("mean_bits_d", 1), + ) + }, + &random_rounding_modes, + ) + .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } @@ -2426,6 +2947,112 @@ pub fn special_random_float_rounding_mode_pair_gen_var_12( ) } +pub fn special_random_float_rounding_mode_pair_gen_var_13( + config: &GenConfig, +) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_floats( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + config.get_or("mean_precision_n", 64), + config.get_or("mean_precision_d", 1), + config.get_or("mean_zero_p_n", 1), + config.get_or("mean_zero_p_d", 64), + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn special_random_float_rounding_mode_pair_gen_var_14( + config: &GenConfig, +) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_floats_with_precision_inclusive_range( + seed, + config, + 1, + Limb::WIDTH - 1, + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn special_random_float_rounding_mode_pair_gen_var_15( + config: &GenConfig, +) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_positive_floats_with_precision( + seed, + config.get_or("mean_exponent_n", 64), + config.get_or("mean_exponent_d", 1), + config.get_or("mean_stripe_n", 32), + config.get_or("mean_stripe_d", 1), + Limb::WIDTH, + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn special_random_float_rounding_mode_pair_gen_var_16( + config: &GenConfig, +) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_floats_with_precision_inclusive_range( + seed, + config, + Limb::WIDTH + 1, + (Limb::WIDTH << 1) - 1, + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + +pub fn special_random_float_rounding_mode_pair_gen_var_17( + config: &GenConfig, +) -> It<(Float, RoundingMode)> { + Box::new( + random_pairs( + EXAMPLE_SEED, + &|seed| { + striped_random_floats_with_precision_inclusive_range_to_infinity( + seed, + config, + Limb::WIDTH + 1, + ) + }, + &random_rounding_modes, + ) + .filter(|(f, rm)| reciprocal_round_valid(f, *rm)), + ) +} + // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-nz. diff --git a/malachite-float/src/test_util/mod.rs b/malachite-float/src/test_util/mod.rs index 7b69125a3..5f0398c42 100644 --- a/malachite-float/src/test_util/mod.rs +++ b/malachite-float/src/test_util/mod.rs @@ -9,6 +9,7 @@ pub mod arithmetic; pub mod bench; pub mod common; +pub mod constants; pub mod exhaustive; pub mod extra_variadic; pub mod generators; diff --git a/malachite-float/tests/arithmetic/add.rs b/malachite-float/tests/arithmetic/add.rs index de53623c2..29ba66fd0 100644 --- a/malachite-float/tests/arithmetic/add.rs +++ b/malachite-float/tests/arithmetic/add.rs @@ -16,8 +16,9 @@ use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::test_util::arithmetic::add::{ - add_prec_round_naive, add_rational_prec_round_naive, rug_add, rug_add_rational, - rug_add_rational_round, rug_add_round, + add_prec_round_naive, add_rational_prec_round_naive, rug_add, rug_add_prec, rug_add_prec_round, + rug_add_rational, rug_add_rational_prec, rug_add_rational_prec_round, rug_add_rational_round, + rug_add_round, }; use malachite_float::test_util::common::{ emulate_primitive_float_fn_2, parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, @@ -81,8 +82,8 @@ fn test_add() { assert_eq!( ComparableFloatRef(&Float::from(&rug_add( - rug::Float::exact_from(&x), - rug::Float::exact_from(&y) + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y) ))), ComparableFloatRef(&sum) ); @@ -1150,6 +1151,17 @@ fn test_add_prec() { let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + + let (rug_sum, rug_o) = rug_add_prec( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_sum)), + ComparableFloatRef(&sum) + ); + assert_eq!(rug_o, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); @@ -2009,7 +2021,7 @@ fn test_add_round() { assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = - rug_add_round(rug::Float::exact_from(&x), rug::Float::exact_from(&y), rm); + rug_add_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), @@ -5082,6 +5094,20 @@ fn test_add_prec_round() { let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_sum, rug_o) = rug_add_prec_round( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_sum)), + ComparableFloatRef(&sum) + ); + assert_eq!(rug_o, o); + } }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); @@ -7324,8 +7350,8 @@ fn test_add_rational() { assert_eq!( ComparableFloatRef(&Float::from(&rug_add_rational( - rug::Float::exact_from(&x), - rug::Rational::from(&y) + &rug::Float::exact_from(&x), + &rug::Rational::from(&y) ))), ComparableFloatRef(&sum) ); @@ -7538,6 +7564,17 @@ fn test_add_rational_prec() { let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + + let (rug_sum, rug_o) = rug_add_rational_prec( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_sum)), + ComparableFloatRef(&sum) + ); + assert_eq!(rug_o, o); }; test("NaN", "NaN", "123", 1, "NaN", "NaN", Equal); test( @@ -7686,8 +7723,8 @@ fn test_add_rational_round() { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_round( - rug::Float::exact_from(&x), - rug::Rational::exact_from(&y), + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), rm, ); assert_eq!( @@ -8411,6 +8448,20 @@ fn test_add_rational_prec_round() { let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_sum, rug_o) = rug_add_rational_prec_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_sum)), + ComparableFloatRef(&sum) + ); + assert_eq!(rug_o, o); + } }; test("NaN", "NaN", "123", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Ceiling, "NaN", "NaN", Equal); @@ -9046,6 +9097,39 @@ fn add_prec_round_properties() { assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_sum, rug_o) = rug_add_prec_round( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_sum)), + ComparableFloatRef(&sum) + ); + assert_eq!(rug_o, o); + } + + if o == Equal && sum.is_finite() { + assert_eq!( + ComparableFloat( + sum.sub_prec_round_ref_ref(&x, y.significant_bits(), Exact) + .0 + .abs_negative_zero() + ), + ComparableFloat(y.abs_negative_zero_ref()) + ); + assert_eq!( + ComparableFloat( + sum.sub_prec_round_ref_ref(&y, x.significant_bits(), Exact) + .0 + .abs_negative_zero() + ), + ComparableFloat(x.abs_negative_zero_ref()) + ); + } + let r_sum = if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); @@ -9212,10 +9296,40 @@ fn add_prec_properties() { assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + let (rug_sum, rug_o) = rug_add_prec( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_sum)), + ComparableFloatRef(&sum) + ); + assert_eq!(rug_o, o); + let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + if o == Equal && sum.is_finite() { + assert_eq!( + ComparableFloat( + sum.sub_prec_ref_ref(&x, y.significant_bits()) + .0 + .abs_negative_zero() + ), + ComparableFloat(y.abs_negative_zero_ref()) + ); + assert_eq!( + ComparableFloat( + sum.sub_prec_ref_ref(&y, x.significant_bits()) + .0 + .abs_negative_zero() + ), + ComparableFloat(x.abs_negative_zero_ref()) + ); + } + if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); @@ -9360,6 +9474,11 @@ fn add_round_properties_helper(x: Float, y: Float, rm: RoundingMode) { assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + if o == Equal && sum.is_finite() { + assert_eq!(sum.sub_round_ref_ref(&x, Exact).0, y); + assert_eq!(sum.sub_round_ref_ref(&y, Exact).0, x); + } + let r_sum = if sum.is_finite() { if x.is_normal() && y.is_normal() && sum.is_normal() { assert_eq!( @@ -9397,7 +9516,7 @@ fn add_round_properties_helper(x: Float, y: Float, rm: RoundingMode) { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = - rug_add_round(rug::Float::exact_from(&x), rug::Float::exact_from(&y), rm); + rug_add_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), @@ -9578,9 +9697,14 @@ fn add_properties_helper_2(x: Float, y: Float) { .add_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); - let sum_alt = x.add_round_ref_ref(&y, Nearest).0; + let (sum_alt, o) = x.add_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); + if o == Equal && sum.is_finite() { + assert_eq!(&sum - &x, y); + assert_eq!(&sum - &y, x); + } + if sum.is_finite() && x.is_normal() && y.is_normal() && sum.is_normal() { assert_eq!( sum.get_prec(), @@ -9598,7 +9722,7 @@ fn add_properties_helper_2(x: Float, y: Float) { } } - let rug_sum = rug_add(rug::Float::exact_from(&x), rug::Float::exact_from(&y)); + let rug_sum = rug_add(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), @@ -9723,6 +9847,32 @@ fn add_rational_prec_round_properties() { assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_sum, rug_o) = rug_add_rational_prec_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_sum)), + ComparableFloatRef(&sum) + ); + assert_eq!(rug_o, o); + } + + if o == Equal && sum.is_finite() { + assert_eq!( + ComparableFloat( + sum.sub_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) + .0 + .abs_negative_zero() + ), + ComparableFloat(x.abs_negative_zero_ref()) + ); + // TODO additional test + } + let r_sum = if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); @@ -9787,7 +9937,7 @@ fn add_rational_prec_round_properties() { assert_eq!(oo, Equal); } } else { - assert_panic!(x.add_rational_prec_round_ref_ref(&y, prec, Exact)); + // QQQ assert_panic!(x.add_rational_prec_round_ref_ref(&y, prec, Exact)); } }, ); @@ -9865,6 +10015,29 @@ fn add_rational_prec_properties() { assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + let (rug_sum, rug_o) = rug_add_rational_prec( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_sum)), + ComparableFloatRef(&sum) + ); + assert_eq!(rug_o, o); + + if o == Equal && sum.is_finite() { + assert_eq!( + ComparableFloat( + sum.sub_rational_prec_ref_ref(&y, x.significant_bits()) + .0 + .abs_negative_zero() + ), + ComparableFloat(x.abs_negative_zero_ref()) + ); + // TODO additional test + } + let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); @@ -9985,6 +10158,11 @@ fn add_rational_round_properties() { assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); + if o == Equal && sum.is_finite() && sum != 0 { + assert_eq!(sum.sub_rational_round_ref_ref(&y, Exact).0, x); + // TODO additional test + } + let r_sum = if sum.is_finite() { if x.is_normal() && sum.is_normal() { assert_eq!(sum.get_prec(), Some(x.get_prec().unwrap())); @@ -10019,8 +10197,8 @@ fn add_rational_round_properties() { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_round( - rug::Float::exact_from(&x), - rug::Rational::exact_from(&y), + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), rm, ); assert_eq!( @@ -10149,9 +10327,14 @@ fn add_rational_properties() { assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = x.add_rational_prec_ref_ref(&y, x.significant_bits()).0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); - let sum_alt = x.add_rational_round_ref_ref(&y, Nearest).0; + let (sum_alt, o) = x.add_rational_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); + if o == Equal && sum.is_finite() && sum != 0 { + assert_eq!(&sum - &y, x); + // TODO additional test + } + if sum.is_finite() && x.is_normal() && sum.is_normal() { assert_eq!(sum.get_prec(), Some(x.get_prec().unwrap())); let r_sum = Rational::exact_from(&x) + &y; @@ -10166,7 +10349,7 @@ fn add_rational_properties() { } } - let rug_sum = rug_add_rational(rug::Float::exact_from(&x), rug::Rational::from(&y)); + let rug_sum = rug_add_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), diff --git a/malachite-float/tests/arithmetic/div.rs b/malachite-float/tests/arithmetic/div.rs new file mode 100644 index 000000000..83d4922e3 --- /dev/null +++ b/malachite-float/tests/arithmetic/div.rs @@ -0,0 +1,16263 @@ +// 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 core::cmp::max; +use core::cmp::Ordering::{self, *}; +use malachite_base::num::arithmetic::traits::NegAssign; +use malachite_base::num::basic::floats::PrimitiveFloat; +use malachite_base::num::basic::integers::PrimitiveInt; +use malachite_base::num::basic::traits::{ + Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero, +}; +use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; +use malachite_base::num::float::NiceFloat; +use malachite_base::num::logic::traits::SignificantBits; +use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_base::test_util::generators::common::GenConfig; +use malachite_base::test_util::generators::primitive_float_pair_gen; +use malachite_float::arithmetic::div::{ + div_rational_prec_round_direct, div_rational_prec_round_direct_ref_ref, + div_rational_prec_round_direct_ref_val, div_rational_prec_round_direct_val_ref, + div_rational_prec_round_naive, div_rational_prec_round_naive_ref_ref, + div_rational_prec_round_naive_ref_val, div_rational_prec_round_naive_val_ref, + rational_div_float_prec_round_direct, rational_div_float_prec_round_direct_ref_ref, + rational_div_float_prec_round_direct_ref_val, rational_div_float_prec_round_direct_val_ref, + rational_div_float_prec_round_naive, rational_div_float_prec_round_naive_ref_ref, + rational_div_float_prec_round_naive_ref_val, rational_div_float_prec_round_naive_val_ref, +}; +use malachite_float::test_util::arithmetic::div::{ + div_prec_round_naive, rug_div, rug_div_prec, rug_div_prec_round, rug_div_rational, + rug_div_rational_prec, rug_div_rational_prec_round, rug_div_rational_round, rug_div_round, + rug_rational_div_float, rug_rational_div_float_prec, rug_rational_div_float_prec_round, + rug_rational_div_float_round, +}; +use malachite_float::test_util::common::{ + emulate_primitive_float_fn_2, parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, +}; +use malachite_float::test_util::generators::{ + float_float_rounding_mode_triple_gen_var_23, float_float_rounding_mode_triple_gen_var_24, + float_float_rounding_mode_triple_gen_var_25, float_float_rounding_mode_triple_gen_var_26, + float_float_rounding_mode_triple_gen_var_27, float_float_rounding_mode_triple_gen_var_28, + float_float_unsigned_rounding_mode_quadruple_gen_var_4, float_float_unsigned_triple_gen_var_1, + float_gen, float_pair_gen, float_pair_gen_var_2, float_pair_gen_var_3, float_pair_gen_var_4, + float_pair_gen_var_8, float_pair_gen_var_9, float_rational_pair_gen, + float_rational_rounding_mode_triple_gen_var_5, float_rational_rounding_mode_triple_gen_var_6, + float_rational_unsigned_rounding_mode_quadruple_gen_var_4, + float_rational_unsigned_rounding_mode_quadruple_gen_var_5, + float_rational_unsigned_triple_gen_var_1, float_rounding_mode_pair_gen, + float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1, + rational_rounding_mode_pair_gen_var_6, rational_unsigned_rounding_mode_triple_gen_var_1, +}; +use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; +use malachite_nz::platform::Limb; +use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; +use malachite_q::Rational; +use std::panic::catch_unwind; +use std::str::FromStr; + +#[test] +fn test_div() { + let test = |s, s_hex, t, t_hex, out: &str, out_hex: &str| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + let y = parse_hex_string(t_hex); + assert_eq!(y.to_string(), t); + + let quotient = x.clone() / y.clone(); + assert!(quotient.is_valid()); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let quotient_alt = x.clone() / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + let quotient_alt = &x / y.clone(); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + let quotient_alt = &x / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + + let mut quotient_alt = x.clone(); + quotient_alt /= y.clone(); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + let mut quotient_alt = x.clone(); + quotient_alt /= &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + + assert_eq!( + ComparableFloatRef(&Float::from(&rug_div( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y) + ))), + ComparableFloatRef("ient), + ); + + let quotient_alt = div_prec_round_naive( + x.clone(), + y.clone(), + max(x.significant_bits(), y.significant_bits()), + Nearest, + ) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + }; + test("NaN", "NaN", "NaN", "NaN", "NaN", "NaN"); + test("NaN", "NaN", "Infinity", "Infinity", "NaN", "NaN"); + test("NaN", "NaN", "-Infinity", "-Infinity", "NaN", "NaN"); + test("NaN", "NaN", "0.0", "0x0.0", "NaN", "NaN"); + test("NaN", "NaN", "-0.0", "-0x0.0", "NaN", "NaN"); + test("NaN", "NaN", "1.0", "0x1.0#1", "NaN", "NaN"); + test("NaN", "NaN", "-1.0", "-0x1.0#1", "NaN", "NaN"); + + test("Infinity", "Infinity", "NaN", "NaN", "NaN", "NaN"); + test("Infinity", "Infinity", "Infinity", "Infinity", "NaN", "NaN"); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + "NaN", + "NaN", + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", "Infinity", "Infinity", + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", "Infinity", "Infinity", + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + "-Infinity", + "-Infinity", + ); + + test("-Infinity", "-Infinity", "NaN", "NaN", "NaN", "NaN"); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + "NaN", + "NaN", + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + "NaN", + "NaN", + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + "Infinity", + "Infinity", + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + "-Infinity", + "-Infinity", + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + "Infinity", + "Infinity", + ); + + test("0.0", "0x0.0", "NaN", "NaN", "NaN", "NaN"); + test("0.0", "0x0.0", "Infinity", "Infinity", "0.0", "0x0.0"); + test("0.0", "0x0.0", "-Infinity", "-Infinity", "-0.0", "-0x0.0"); + test("0.0", "0x0.0", "0.0", "0x0.0", "NaN", "NaN"); + test("0.0", "0x0.0", "-0.0", "-0x0.0", "NaN", "NaN"); + test("0.0", "0x0.0", "1.0", "0x1.0#1", "0.0", "0x0.0"); + test("0.0", "0x0.0", "-1.0", "-0x1.0#1", "-0.0", "-0x0.0"); + + test("-0.0", "-0x0.0", "NaN", "NaN", "NaN", "NaN"); + test("-0.0", "-0x0.0", "Infinity", "Infinity", "-0.0", "-0x0.0"); + test("-0.0", "-0x0.0", "-Infinity", "-Infinity", "0.0", "0x0.0"); + test("-0.0", "-0x0.0", "0.0", "0x0.0", "NaN", "NaN"); + test("-0.0", "-0x0.0", "-0.0", "-0x0.0", "NaN", "NaN"); + test("-0.0", "-0x0.0", "1.0", "0x1.0#1", "-0.0", "-0x0.0"); + test("-0.0", "-0x0.0", "-1.0", "-0x1.0#1", "0.0", "0x0.0"); + + test("123.0", "0x7b.0#7", "NaN", "NaN", "NaN", "NaN"); + test("123.0", "0x7b.0#7", "Infinity", "Infinity", "0.0", "0x0.0"); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + ); + test("123.0", "0x7b.0#7", "0.0", "0x0.0", "Infinity", "Infinity"); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + ); + test("123.0", "0x7b.0#7", "1.0", "0x1.0#1", "123.0", "0x7b.0#7"); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + "-123.0", + "-0x7b.0#7", + ); + + test("NaN", "NaN", "123.0", "0x7b.0#7", "NaN", "NaN"); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", "Infinity", "Infinity", + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + ); + test("0.0", "0x0.0", "123.0", "0x7b.0#7", "0.0", "0x0.0"); + test("-0.0", "-0x0.0", "123.0", "0x7b.0#7", "-0.0", "-0x0.0"); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + "0.0082", + "0x0.0218#7", + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + "-0.0082", + "-0x0.0218#7", + ); + + test("1.0", "0x1.0#1", "2.0", "0x2.0#1", "0.5", "0x0.8#1"); + test("1.0", "0x1.0#1", "2.0", "0x2.0#2", "0.5", "0x0.8#2"); + test("1.0", "0x1.0#2", "2.0", "0x2.0#1", "0.5", "0x0.8#2"); + test("1.0", "0x1.0#2", "2.0", "0x2.0#2", "0.5", "0x0.8#2"); + test("1.0", "0x1.000#10", "2.0", "0x2.00#10", "0.5", "0x0.800#10"); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "0.45015815807855308", + "0x0.733d90a6f99888#53", + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-0.45015815807855308", + "-0x0.733d90a6f99888#53", + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-0.45015815807855308", + "-0x0.733d90a6f99888#53", + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "0.45015815807855308", + "0x0.733d90a6f99888#53", + ); + + // - in div_float_significands_same_prec_lt_w + // - increment_exp in div_float_significands_same_prec_lt_w + // - (q0 + 2) & (mask >> 1) <= 2 in div_float_significands_same_prec_lt_w + // - h == 0 && l < y in div_float_significands_same_prec_lt_w + // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_lt_w + test("1.0", "0x1.0#1", "1.0", "0x1.0#1", "1.0", "0x1.0#1"); + // - !increment_exp in div_float_significands_same_prec_lt_w + // - (q0 + 2) & (mask >> 1) > 2 in div_float_significands_same_prec_lt_w + // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_lt_w + // - rm == Nearest in div_float_significands_same_prec_lt_w + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (quotient & shift_bit) != 0) in + // div_float_significands_same_prec_lt_w + test("1.0", "0x1.0#2", "1.5", "0x1.8#2", "0.8", "0x0.c#2"); + // - h != 0 || l >= y in div_float_significands_same_prec_lt_w + test("1.5", "0x1.8#2", "1.0", "0x1.0#2", "1.5", "0x1.8#2"); + // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (quotient & shift_bit) == 0)) in + // div_float_significands_same_prec_lt_w + test("1.0", "0x1.0#3", "1.2", "0x1.4#3", "0.8", "0x0.c#3"); + + // - in div_float_significands_same_prec_w + // - increment_exp in div_float_significands_same_prec_w + // - hi == 0 && lo < y in div_float_significands_same_prec_w + // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_w + test( + "1.0", + "0x1.0000000000000000#64", + "1.0", + "0x1.0000000000000000#64", + "1.0", + "0x1.0000000000000000#64", + ); + // - !increment_exp in div_float_significands_same_prec_w + // - round_bit == 0 in div_float_significands_same_prec_w + // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_w + // - rm == Nearest in div_float_significands_same_prec_w + // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (quotient & 1) == 0)) in + // div_float_significands_same_prec_w + test( + "1.0", + "0x1.0000000000000000#64", + "1.0000000000000000001", + "0x1.0000000000000002#64", + "0.99999999999999999989", + "0x0.fffffffffffffffe#64", + ); + // - hi != 0 || lo >= y in div_float_significands_same_prec_w + test( + "1.0000000000000000001", + "0x1.0000000000000002#64", + "1.0", + "0x1.0000000000000000#64", + "1.0000000000000000001", + "0x1.0000000000000002#64", + ); + // - rm == Nearest || round_bit != 0 && (sticky_bit != 0 || (quotient & 1) != 0) in + // div_float_significands_same_prec_w + test( + "1.0000000000000000002", + "0x1.0000000000000004#64", + "1.0000000000000000001", + "0x1.0000000000000002#64", + "1.0000000000000000001", + "0x1.0000000000000002#64", + ); + // - round_bit != 0 in div_float_significands_same_prec_w + test( + "3.1790543009742223972e-11", + "0x2.2f43e0add6ebd01cE-9#64", + "7770090901.6225594673", + "0x1cf222d95.9f600ea8#64", + "4.0913991113158902183e-21", + "0x1.35232b1b3b9aeabeE-17#64", + ); + + // - in div_float_significands_same_prec_gt_w_lt_2w + // - increment_exp in div_float_significands_same_prec_gt_w_lt_2w + // - in div_float_2_approx + // - y_1 != Limb::MAX in div_float_2_approx + // - r_1 == 0 in div_float_2_approx + // - (q_0.wrapping_add(21)) & (mask >> 1) <= 21 in div_float_significands_same_prec_gt_w_lt_2w + // - s_2 == 0 && s_1 <= y_1 && (s_1 != y_1 || s_0 < y_0) in + // div_float_significands_same_prec_gt_w_lt_2w + // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_gt_w_lt_2w + test( + "1.0", + "0x1.0000000000000000#65", + "1.0", + "0x1.0000000000000000#65", + "1.0", + "0x1.0000000000000000#65", + ); + // - !increment_exp in div_float_significands_same_prec_gt_w_lt_2w + // - s_2 > 0 || s_1 > y_1 || (s_1 == y_1 && s_0 >= y_0) in + // div_float_significands_same_prec_gt_w_lt_2w + // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_gt_w_lt_2w + // - rm == Nearest in div_float_significands_same_prec_gt_w_lt_2w + // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0)) in + // div_float_significands_same_prec_gt_w_lt_2w + test( + "1.0", + "0x1.0000000000000000#65", + "1.00000000000000000005", + "0x1.0000000000000001#65", + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + ); + // - r_1 != 0 in div_float_2_approx + test( + "1.0", + "0x1.0000000000000000#65", + "1.00000000000000000011", + "0x1.0000000000000002#65", + "0.99999999999999999989", + "0x0.fffffffffffffffe0#65", + ); + // - (q_0.wrapping_add(21)) & (mask >> 1) > 21 in div_float_significands_same_prec_gt_w_lt_2w + test( + "1.0", + "0x1.0000000000000000#65", + "1.00000000000000000016", + "0x1.0000000000000003#65", + "0.99999999999999999984", + "0x0.fffffffffffffffd0#65", + ); + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow + // in div_float_significands_same_prec_gt_w_lt_2w + test( + "1.00000000000000000011", + "0x1.0000000000000002#65", + "1.00000000000000000005", + "0x1.0000000000000001#65", + "1.00000000000000000005", + "0x1.0000000000000001#65", + ); + // - y_1 == Limb::MAX in div_float_2_approx + test( + "5.29395592276605355108231857701752e-23", + "0x4.00000007e000fffffff0000000E-19#107", + "255.999999999999999999999947060441", + "0xff.ffffffffffffffffffc000000#107", + "2.06795153233048966839153112178982e-25", + "0x4.00000007e000fffffff1000000E-21#107", + ); + + // - in div_float_significands_long_by_short + // - diff >= 0 in div_float_significands_long_by_short + // - in limbs_div_limb_to_out_mod_with_fraction + // - d.get_highest_bit() in limbs_div_limb_to_out_mod_with_fraction + // - sticky_bit != 0 || diff >= 0 || i >= abs_diff in div_float_significands_long_by_short + // - tmp[ys_len] == 0 in div_float_significands_long_by_short + // - tmp[ys_len] == 0 && shift != 0 in div_float_significands_long_by_short + // - round_bit != 0 || sticky_bit != 0 in div_float_significands_long_by_short + // - rm == Nearest in div_float_significands_long_by_short + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (ys[0] & shift_bit) != 0) in + // div_float_significands_long_by_short + // - rm == Nearest && !overflow in div_float_significands_long_by_short + test("1.0", "0x1.0#1", "1.5", "0x1.8#2", "0.8", "0x0.c#2"); + // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (ys[0] & shift_bit) == 0)) in + // div_float_significands_long_by_short + test("1.0", "0x1.0#1", "1.2", "0x1.4#3", "0.8", "0x0.c#3"); + // - tmp[ys_len] != 0 in div_float_significands_long_by_short + // - tmp[ys_len] != 0 && shift != 0 in div_float_significands_long_by_short + test("1.5", "0x1.8#2", "1.2", "0x1.4#3", "1.2", "0x1.4#3"); + // - round_bit == 0 && sticky_bit == 0 in div_float_significands_long_by_short + test("1.5", "0x1.8#2", "1.5", "0x1.8#3", "1.0", "0x1.0#3"); + // - tmp[ys_len] == 0 && shift == 0 in div_float_significands_long_by_short + // - c >= u - c in div_float_significands_long_by_short + test( + "1539239.2465826685826", + "0x177ca7.3f200ab152a#64", + "0.00009", + "0x0.0006#3", + "16812597210.673628039", + "0x3ea1bdfda.ac72e31c#64", + ); + // - c < u - c in div_float_significands_long_by_short + // - round_bit == 0 in div_float_significands_long_by_short + test( + "1.7088961703394199635e-73", + "0x4.d4baa70e83509ad8E-61#64", + "1.7359472818744e-34", + "0xe.6bf39991dcE-29#42", + "9.844170892645193631e-40", + "0x5.5c13c13c6d059800E-33#64", + ); + // - tmp[ys_len] != 0 && shift == 0 in div_float_significands_long_by_short + test( + "4.874956728709606165589080471392071684004548689044982493122e-71", + "0x5.6220e3ededa8be921ace72bbb95a16164a2f0abd57c49f18E-59#192", + "1.5092483e-10", + "0xa.5f190E-9#22", + "3.230056172437141772802006354545046772521759341614858124236e-61", + "0x8.4e07636cdfc96e412c1de0a522f40a5f092091c1a3aa159E-51#192", + ); + + test( + "6.88621557179233820703925296804982406452e-28", + "0x3.68ee78c4dbb67961d201a40495749728E-23#127", + "0.1418399214207466117788070203268", + "0x0.244f9effc4f1edfd85dfab3008#99", + "4.85492060543760755133907256608679730501e-27", + "0x1.80a57d020f8b7083401eec627a6787ccE-22#127", + ); + + // - in div_float_significands_general + // - up[u_size - 1] == vp[vsize - 1] in div_float_significands_general + // - k == 0 || l == 0 in div_float_significands_general + // - up[k] == vp[l] && l != 0 in div_float_significands_general + // - q0size < MPFR_DIV_THRESHOLD || vsize < MPFR_DIV_THRESHOLD in div_float_significands_general + // - rm != Nearest || shift != 0 second time in div_float_significands_general + // - qqsize > u_size in div_float_significands_general + // - qqsize > u_size && !extra_bit in div_float_significands_general + // - vsize >= qsize in div_float_significands_general + // - in limbs_div_helper + // - ds_len == 2 in limbs_div_helper + // - qsize == q0size in div_float_significands_general + // - vsize <= qsize in div_float_significands_general + // - rm == Nearest second time in div_float_significands_general + // - !goto_truncate_check_qh && !goto_sub_1_ulp && !goto_sub_1_ulp && !goto_sub_2_ulp in + // div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) in div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit == 0 in + // div_float_significands_general + test( + "1.0", + "0x1.0#1", + "1.00000000000000000005", + "0x1.0000000000000001#65", + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + ); + // - up[u_size - 1] != vp[vsize - 1] in div_float_significands_general + test( + "1.0", + "0x1.0#1", + "1.00000000000000000011", + "0x1.0000000000000002#65", + "0.99999999999999999989", + "0x0.fffffffffffffffe0#65", + ); + // - qqsize > u_size && extra_bit in div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 in + // div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 && !carry + // first time in div_float_significands_general + test( + "1.5", + "0x1.8#2", + "1.00000000000000000005", + "0x1.0000000000000001#65", + "1.49999999999999999995", + "0x1.7fffffffffffffff#65", + ); + // - ds_len > 1 in limbs_div_helper + test( + "12077.327578390390934514", + "0x2f2d.53dc2d699afa78b8#75", + "4.90332775049862782951473377323022738896770775e-11", + "0x3.5e9a4013acb1890afeca956568e5bffe30edE-9#146", + "246308796656764.923124719743308898445103382544", + "0xe0043c546c7c.ec51e6d16d3ab81c76ba65494#146", + ); + // - vsize < qsize in div_float_significands_general + test( + "1917511442.613985761391508315964935868035476119276770671", + "0x724ae712.9d2e2bbd62dd31f140b2b9b664635f251b18c0#180", + "3.352896739388742667241376e25", + "0x1.bbc08f6e851e14a094c4E+21#79", + "5.718969570663133425280005234972069245666491961744252885e-17", + "0x4.1ef6b3c1725013efb2a8179983b542a97b0131f39a938E-14#180", + ); + // - rm == Nearest && shift == 0 second time in div_float_significands_general + // - qsize != q0size in div_float_significands_general + test( + "1.490328e-27", + "0x7.61370E-23#20", + "2.89262335038499315783322011549431655756e-75", + "0x1.4ef161f7b7fc2c6cb4464f827b58b972E-62#128", + "5.15216656741446303242577558053691246166e47", + "0x5.a3f1d299f6f20544fbba161403f075f8E+39#128", + ); + // - rm == Floor || rm == Down || (round_bit == 0 && sticky == 0) in + // div_float_significands_general + test( + "2.38418579101562499999949513e-7", + "0x3.fffffffffffffffffc0000E-6#87", + "2113929216.0", + "0x7e000000.000000000#66", + "1.12784561231761934265233937e-16", + "0x8.208208208208208200000E-14#87", + ); + // - k != 0 && l != 0 in div_float_significands_general + // - up[k] != vp[l] first time in div_float_significands_general + // - up[k] != vp[l] second time in div_float_significands_general + test( + "65535.99999999999999994", + "0xffff.fffffffffffffc#70", + "22835963083295358096932575511189670382427701248.00000000000000022202", + "0x3fffffffffffffffffffffffff8000007000000.0000000000000fff8#219", + "2.869859254937225361249367321235116718339077564583058127288930659162e-42", + "0x3.fffffffffffffffff000000007fffff8ffffffffffe000001c00008E-35#219", + ); + // - up[k] == vp[l] first time in div_float_significands_general + test( + "1.91561942608236107295e53", + "0x2.0000000000000000E+44#66", + "43556142965880123323311949751266331066368.000061035156249999998", + "0x8000000000000000000000000000000000.0003fffffffffffff8#205", + "4398046511103.99999999999999999999999999999999383702417796084544", + "0x3ffffffffff.ffffffffffffffffffffffffffe00000000000004#205", + ); + // - up[k] == vp[l] && l == 0 second time in div_float_significands_general + test( + "255.99999999813735485076904", + "0xff.fffffff800000000000#82", + "1.35525271559701978119405335351978053e-20", + "0x3.ffffffffe0000000000000000000E-17#114", + "18889465931478580854784.0", + "0x4000000000000000000.0000000000#114", + ); + // - q0size >= MPFR_DIV_THRESHOLD && vsize >= MPFR_DIV_THRESHOLD in + // div_float_significands_general + // - u_size < n << 1 in div_float_significands_general + // - vsize < n in div_float_significands_general + // - in limbs_float_div_high + // - len >= MPFR_DIVHIGH_TAB.len() in limbs_float_div_high + // - k != 0 in limbs_float_div_high + // - q_high != 0 in limbs_float_div_high + // - carry == 0 in limbs_float_div_high + // - carry != 0 in limbs_float_div_high + // - len < MPFR_DIVHIGH_TAB.len() in limbs_float_div_high + // - k == 0 in limbs_float_div_high + // - len > 2 in limbs_float_div_high + // - qh == 1 in div_float_significands_general + // - in round_helper_2 + // - err0 > 0 in round_helper_2 + // - err0 > prec && prec < err in round_helper_2 + // - s != Limb::WIDTH in round_helper_2 + // - n != 0 && tmp != 0 && tmp != mask in round_helper_2 + // - round_helper_2 in div_float_significands_general + // - rm == Nearest first time in div_float_significands_general + // - rm == Nearest && shift != 0 first time in div_float_significands_general + // - rm == Nearest && round_bit == 0 in div_float_significands_general + test( + "914122363545.7300954288539961362078521335512160921125366724096502748846903936195389924148\ + 154757063704910629280973433563521737016298541257057972452261335506117124831272191707877190\ + 2119190824963185068512647039440777212199983388696", + "0xd4d5f05299.bae788b5e312f78f55ac79e4ca82e12494296afdb40ba21e0c21a4b3915ba2e217c389f8c9fd\ + 22042f5ed70da20cfb9f1ee797b1433e077a2d34b1ae5781f975eebbcb21a32ee0c5afa5e59f8f382fe0c754a4\ + a3fb57fa4d668#754", + "99775868891207693182758620905617766484977359141657322302733467080906379945858675686059451\ + 2527853476231275058799551652072546.7114971760702609364731573674336745185834760605451122614\ + 680178551142556046183482705875960001033145321970465204907865385015751310573750415565593472\ + 515573584122133946534420508845514863685042630834456885627933663697385547769664847990486584\ + 336882273751721721644989648370590667737234950547668737865047573751482757356022197920174371\ + 088074314780588737501583713833755004374512024407585163195094394292034507503368814534990168\ + 9912721166210129145585", + "0x1826427338bc8ee8c907c3ce5e6a2a793f6ba67df6e738f22dc8aee7eb1838ddc4290e49186e61bdbedb847\ + d19c5d8c4bf88c62.b624adce6b0a3564827e04608c1aec0c8b10390491e15df75402c1788241935e791ebd5f4\ + 25d73042c03e3bad5f0d11257d8bcdab6c8bae677785865be19fa4f42690ddb02174b09bb2c1c9ce6cf3dc2d80\ + 9f0b0b79c42ae70f14ec682ac3850e91ee3b6ef02555e18758417024bf2e8801a759e710b3ac91f28b15277ff4\ + f6380b7ba380aa56c032ce8db2107bfd99a9c789098467f2b27a7b3e1bb6a9e7804ef8a26a3baea51e9a8da4d5\ + 02af09995fd6ced97b00#1859", + "9.161757985214429764992710266551647359057325985892606639113002591596898046569993924851132\ + 469009506849046579846739625666450546615840413944516736833310444241924771226669449467280905\ + 847180462085951493210441487438964221396785151298524525494386941673630175499486324164244756\ + 513337189186243674611400515366863669226025015162200893355049656715514081022497216123358900\ + 204159965608607573130556648229035236124949246847315199932950877590362471534070708393335471\ + 028355306786566135185894674384218244976402468322690432705335567965983855642753641740432604\ + 3437409476409135277542e-112", + "0x8.d032a1c09c5a822250facc4d03dcbdde26d4f5fe102c1e08a4f87e413b615d798e202484a718a7e4ee277\ + 3677de7769fc7d817e371393d771d3460b42f92e9ba23196df3ebdff7cdda4294aecfb6c43776a893a979bdc8c\ + cac166e11d435edd52a1481ecb355a6595fcd794f14478ca886b31b8422e8bc9fdcdbc2261e6c6dfdfea3875fd\ + d48e82b6f89b37437a8064efc36e3671100bf00cb530951d17bbaefe545249991b357ff0fbc5a593a69916e391\ + e844f20336e8635a395cbda774a8ed440b65ccac5a4a48827068b6780bdeecccb424ecbcea085547d055a670dd\ + a2ce7fd1bc8ccfff3fcE-93#1859", + ); + // - q_high == 0 in limbs_float_div_high + test( + "3.667390117738159207950705349477719105571949429980976394812181671883945054829509256768693\ + 428777428660656941387302685172371854480204626447190818847235223777196475037450938977825246\ + 002439873468885558547110470430228085143851019175355894923610792842932340338852051239754427\ + 095026930245556704615627992643819617817074019244527799280182728405175259498139200084973400\ + 185025632529817381341736837108765891093445296142846875524815723636775475593320258020981988\ + 641285509338653295726597545939874976233498010217572353942629414771256828458910867296816672\ + 522543163090158525097032013393556880192772591230747507060825723928635133507431423165786715\ + 278150157159772706487785219042905040143153742214007713387626849311191420055238664770362170\ + 343983987545766271318010394410223132309343859005046365250499465556871672911799580499791909\ + 295656508202340485571517780009270726548788594036564495463224892161734462687808109262481368\ + 096969794376769660230615691331025217443348007977074560288273633401967130359649250852147512\ + 141074330343117535301250887203664127461249846867757356639750473042390297739319749311431157\ + 14372183907772936544329974943881256368038028229439176970805917055179180439477409e-9", + "0xf.c0568c485e0b826908a56a1e9eed605a795d47bbb3b22b86ff364a5aa967860d79fa907ffa4b598c74ca2\ + 768fd610cc65e72d1328231f74c2896a372707f3fffd4713cd781c36ddc8c429a53c9de0a260ab39221aa6723f\ + 639d4f0a18f42a39ce148ec18caa8292a2404e421cb5af96a525988ace64d3b66492e8b29b9f1982af075eac7f\ + a4c4f560684706f9c92a1babe3a7cedd233045842df3c534b90481e818908a787ba694e61d3bd3d93a45651240\ + a1926f3b818e8c51165d9c7c186dd99b0afededda17332acec6e4419ca2c498ecac62e9670b8cc359ac4ce5abb\ + e6a858a9ad732af4717655c73ab36f06357d16912bd759fba2c774b33607e2ee49fbf3328842b34b1649846034\ + e601a686e91c2040c578ab8676f4c413bc62718b75fe591900b6f10a6ee20a73c59ab3be30fb9a154c1a50b4b5\ + d60d7a76de24b93f804302eb4d625df61cf824be4c93189bd500d72fe88443b2e506a11e3b57403b447b8602ef\ + 45e256c2e9cbfbc69697901d340ae418d96a38e3f87b38c8ee8b168c15df448ce29060725fff6438c91fd406bf\ + 6cf95e07431942e379a50250441c4ed69a634f4e155cb67d47b7b4b285388f957b3809dcfb73606173ca9a64c8\ + 9b5ee06f42fc1ee8c752cf947957f346aac01a1e21759f8267f58d36b22e7bd14E-8#3843", + "3187923845432148642442057154569059.126715487792372839803386914179538752693826970283207166\ + 811288798839227319311871148502823407877176659352907588186871022894787193533982873662011253\ + 290757573915501169313819926148549862448642272469031186766746849160076154409190019980289710\ + 170792165652792217117270925812431819493193080694795589891807146039351866024622601910524654\ + 975993653145125921373829181052606711648254654081125875153947355721451359688668050452670532\ + 460418624462017975144128989503732730892234660879379487543472739334395798501406522301770530\ + 084261662015482020833397653047706275744771695945820139179975325296925632712346348118093097\ + 953095934511815810581175318735500116787412839224213098543182657584610954902591533740060963\ + 289805212670558460977431314581393471573332429725647583364688986461335610003995668212280028\ + 807977055980202986273442266172236653427698776974320204115552560417196660880213932819325142\ + 548937684752935846670101028764484218237392844524558383599287530029421881169570993841163993\ + 843829902198804691520255195056203676272889080365643704609455722537324606271987166289767672\ + 190663805227886932691226996255254535007618551610966568052639325048438160780381909128343538\ + 211967934803057176881479842550254050201767779261994751352264395465646274141983125281497566\ + 020553366225193569060382295548356106219949376044134821789228041804290511458952966410365196\ + 222090758059421770693182158103609003570428820956594490269060711518240230638460085565864341\ + 256289190220580928350048868798606128912317218138793827337661513849296003850300428079774414\ + 62431384255329048179650372924700507846477189871631671161154559755984562472291", + "0x9d2d417f3ca9f32fea99c6482363.20706d1bf7058f4c6275f668a177cd076adccb2fda12b6ed78a3b56bb5\ + 9dfb518b8b3c05c40c48fd5544dac5cf4c4b5097a348e21623af642ca54df95b1dc69591e2bdc1e3f296461a0e\ + 73545f0b1a728f095b34af1c14dc3ff040878852b81a047198ec51c9f7dcfffac0ad33017fdb2f0c43edcff12d\ + ef18336029b6f47a305e278cb4eda766445530f250be179818a2d241b5afebc21b194dbd62400042f887100725\ + 62fb877debcff302fcc5b1162c1450e14478eb4e96906a31d6843172390e3cd69b3c0f474a72a62036579c22fe\ + 1d1ad35fc2be49e475a1be85f30bec6d387e595070d17b17f5b5a6f400fde641d92abee13055777fe7f6b647fc\ + 7850f8002fadb99332ceffb5439a87b2ac7f223b73750c6b42112fffe8b992da6c3fbc5274503b1bba48602753\ + 174ba7260f73f3fa02c00fc495aad0f85c84c966f0a98fa7d85cca68b07d58e6292617f3b67fd0aafc0dc0c457\ + 806b811f2698bea27de70e9ea3de0e898978b9670aa90750e88ac855daaf830c9dedb5d22968f2b01302edc889\ + ce03e2af4ec2e339258ace8efa81eeb76b273039929d7289eadfb0bae898fd0257e0f1db349eba610dfb56e3d3\ + 1520f08012e02d96edfbf9a1a05ad01f682c49e1cf1e0f2b1131943ffe95afd8c6454deffe4bfdbf15fe656e18\ + 13690a6dbdca197ec4c2b29ac61a6ca074a2866ff9f55184ed344bb45b2e44eca9945a21cd78ccdd427dff1dab\ + 1d449dccc0aa07e37c89bb61c7fc94ce0edd5fb60b7e2d8034decb7a0e2bba4c1159236fd7f800450c1516e64c\ + bb2206f385ee11aba1c6993b2d50b2437bc23cc47f6b85d72fdd7348a5e321b5c960e8e23830fc93c4393938b8\ + 98c2f16e8452c9e81ce5aa01460fb108dca1e371c53a1e72ad6ad0cb80bd5bf0ace476ab08fe8#5329", + "1.150400792350488243006374252439239370084430198894097883408930056885079539097149903334801\ + 351771948494649335504249165228317854781872084884358035626531528587565616792440130659246789\ + 547068913471358728267587391921067763401960740658485999234360708658257354709138940743401019\ + 478517400580149085993404074744575447821383623813098520973947955049547026992303475579228215\ + 436224676800479021561310494945776720018368502752527214637080415175177143606297950367602304\ + 149567232708944245857383841379350871799797376084773487408407355299732079377175164962925047\ + 553551234005632068337070468847266947004802579875459884664958168707856865409967591741263680\ + 896819771668163339399940221050773763868745744855354003266260565352234279551485173590767169\ + 460117377689246074482291141675360319952860733464727767370984256722737643645180588444886771\ + 648355387388454942423178644791668457452750839522592156007162798991977390140623536578544490\ + 057707937271642210929120388296125663413585185722459999909564986042307052548228205977082023\ + 238981495642981332360042089388607651948288196055583153394379775735995327224157713864077477\ + 321557707540034099204193983589868016082915953745995091314702115380175700364741814725184464\ + 602065018950641261052531311066491931955988616475785792821351515116629573461861957542243077\ + 532642867446492701937719979200426618485741197144774966492676324343483017759514367363624027\ + 675809506514516688590348320872084123672477458766804242125009602995249222201904595636534318\ + 096670348004414769559053243712710972449074750435098780379781902955436286126620063025099547\ + 80435463720060716005725004637793753168276780047800093479230422676842555945701e-42", + "0x1.9a7a0a4405b5655db3032989d155cf7a58151a06aacabc4789fac720edfb0e835fe88bc9af3cc179149fe\ + 616753cd76b4c7d9c17f2f47389f4e0007572679dad2a5316ede08c14af0283577f171d41d795d4ff13631def2\ + 630089c6f215d7b5b8948c52ff97a4a1d9f1eb6d67b60e55478c40ffd2a7cd9684f43637e46ce3ce3e33085654\ + 9165c4a377c6ab1dbb9c9b40ece8c47d94ddd1318dd2e5e57388b2e8ef80705d97c3db61d805c43cf7ff7a9a1e\ + 41ded3ff033e68dc751b34ffd9cf2eae50cb7e7875b9d8f24116927cd9f609a65c71e840166cf535bbf110404d\ + bc493350b17705c0e23a9091d61f544117f70c6c6387dfb9a1dcc2f513cfbebc4cdd4b7d94c9fc57ceebebe3a2\ + e7d85b9b488b5571ef7b7c8621b770d99c67f9a19252ec5f9be4b129c7755b4a8585b97ea68e60e390c0b5c2b2\ + 7b5fc3a47825c136e3b2517a6a7490ae84cf61659a9b819bfe59d45f7254dd48e028c7b694a9b9b427e60358fd\ + 52afbeed855580a61e351d523d4ffaabfc7ca00e9a5b40128e9fd8b2998c189e95abc1857ff9ddf1dac904a2de\ + dfce45cbc4f1ffac50c26ec7e1135aa9ca96f6d3ac8cb3a6620a3aecb003d246eade4cf0e6394df920dfba899f\ + 44ed41072e121f0402f19fc4c43c348467a07566df372a7b1af45354f2b4c7f94d52f355813e84c1a95202029c\ + 0056a974e856e7c42fd6463561d1b5e02ed6a7e0ea0ca50887bd1047f4abd068ea61e2095abdad6a0cbaf91846\ + a340717aa624d6c6ba02f5d3e835ff06c742f1343479ec9a9b184eaca8e7c8be7eaf4fa322afc13f046a4a2e5f\ + 4e84c723c68079991a080ac6939780e172640d568c2bc3452c14317358ee8d27a18af7c9bf2de8bea3e5b8b113\ + d8e61b810d6103e805c2a8f85b9b88f8c9129b924ba95521aa83a066991bea980c8be16f1df53E-35#5329", + ); + // - qh != 1 in div_float_significands_general + test( + "5.001744775175450910666028825162941035057223155811961434576858983758571141018459147239961\ + 203150588371507863692097065128597336587126035820647361489875366021800666979434518756504925\ + 080057234368614339602900137940067888065298554658519361482160014564328827389146902718969285\ + 655774560873251528749737416878097111467317878479458938947793439179987668446365650646689222\ + 368834166803110702160567896615568919058064520266761717855703906871630752776256537972706691\ + 492064397304429453321564568279795029252524047182880248127317544801138445700458013706547493\ + 607273723210196209139384085476634511414334117395068648152693457778920460359930382343697178\ + 078573995749595631668772420417704996567074590195305455833132484492282116574194971013126880\ + 3791636230633361526548302742414616516594455084620537903358416e-16", + "0x2.40a97302ee75111e17146bc65c8925811ce517da511093e155a5f8d319eaddbeb4108f1636a175bfa8c49\ + 995045d6820b2f007a269091d024c939d8b02f4910a81e4eb38a836a327a5c12207dbd4d7a81228e55fec96493\ + eb7d51704a03ee77c5caca6616fdc0b6cbe90c676923de6ef8bf3f132b9e5e0dcbae8db3a41502b6d35629f01c\ + 0834af3506639efdaa9dba6adf35a24b53b04e032ba7f9821a7155eb04aa7d235436bb878e13e2f265b7a183bd\ + 7830bf484c2c6b19e1df88120105ab6ceb5f940ee7e82d4a6da4e67b7532f20750db350a532138117c02fd3f63\ + 1e917747a8217c0e647adfae38491beacae6be9197fecb6a639604eba9f3e2a0e1250124f9d994d6ae0f8077c0\ + ad1f961f00f0513cb1b3b92f03fd2e19ce799415d8c26352d23ab730bff342c3d10823b5d476e3a74e5e3a1265\ + 3a2e81ad38c5d7f45687a8E-13#2587", + "1.142392802815468388118014752111991104436260746248041498551240097570984474280784266879307\ + 592064853042631818930172030116326290909317377878988867978348974337550025356060840134215623\ + 183687852648862683292152461337367387727519703906836027722282460995072637442171724001503892\ + 471336699233392710738717656085295397789876649817787754823752786376233371866685422498954888\ + 388883747226256845650864591251580129661172288008506642506027201072159168710566406994425528\ + 61698637621752755004821872e-17", + "0xd.2bbf98dfde60cfd72ff373085dca4697e7a8a2b1b6d379d3c49be918a519d5508c59f210662104e5d0b4b\ + bb4e9f09afcccb3c1655f91f2a86657e3f1315aa4e7c857d68f4d7b989d2a2f5d56a205e85ef7d6d2e9325e0fe\ + eded2158374d99d513a6d203143a26cfd251731f49e63a0e342dec62e52287bd673124d763a94038f4529cffd3\ + 3599c97c0e19c589ce5603d9c26a084d360b9e7decaa7dda44ce1c27bb7c21adcb23b90d069b0a9b53b9d66094\ + d817f0420227841d34052ed2bd52e148923f8E-15#1571", + "43.78305573046740119713641861874642911154821650761595780287653003720809501996262685108891\ + 851641972710141298162279987632328545443442081070773994511258975201978303856309243168868354\ + 195798884971190979692045031917290903217918542303368118161338247041052975773351929884789101\ + 115569142934332750399827875003719838494787907290778719530315375971295186399328856671813524\ + 401338950750393532748258170809380674066918530153006391759208813425198252649570832466781508\ + 205219467712658427254330831981130973959961174357861904110964877950640959685965415405374479\ + 749995867814629083616329619361738872731212580413192190669870683344353586783786957328312637\ + 080558281918488071596583884466679323108552730394571978915258990045025562636051246193761815\ + 9037942507064891051161378037771712070204599081778501997567779", + "0x2b.c87657214d897953f5e5edbb169c290285fbd11622c9cf401ba99ad9f03da7ffc778df1db0d888d67c18\ + 379efc8b4b36ed8cbb67da04b5b4cfdabc5f751b0a6fc68b1e3a2a16a62c4160ce4d10e00ae47020ca5d3867a7\ + 2213145fe6456480971ef0cb9716c6136384fe41721979e86d1ea1bdc104f2967865add528a1367b01cc449a48\ + 5786a74209d8e4c5e216fa7ae2dc897fd4926b55eacde3321f7c41bf2875c24933c8eecc7a8a26f738fd6d666b\ + 678ec93b48bab7b34c5392d3ca76949dab6958fa5caaf70927d3e8b40d050bb607bc1b4fe656506e1b3e468e87\ + 8b257c21e926286697a97538d3230475cd54415b8154351e72363b4b7509061108fc6ac5db47219368f3ca4011\ + 5309edd7318a116c2b62a34277bfdc8a1faf656b14b6a046087cfc5dd238cd94fe91967fb6dfc52f8afa5699df\ + e2970ca40fb03c71d7d668#2587", + ); + // - n != 0 && tmp == 0 in round_helper_2 + // - s != Limb::WIDTH first time in round_helper_2 + test( + "0.029226865494398284939675773661541675546326681033634876986774906885711036844605915426240\ + 340310096249605517533494947862661721742262334681480455706389428160732541825851560446846541\ + 984468705310228771603694136853587701004882713625816107989162498255925332620064155091399923\ + 221735997586925448254801064429910518067322424203818026901404115120552071966804127784634236\ + 948421057038304255272147630765439482924461011451862112889343084859504616664030668233890526\ + 750016895266382189553251377266295422223247821668554701473442441938933867323625955488726630\ + 366895993417469747854898337776376811834753617592182604418498468334055402941851068346511528\ + 636460609896950078921029074658151972716364203699936241491820871671807186599907001653993018\ + 871354678119954470481273332266267481346670395677171242596948926022697465301700258863974068\ + 74909984356479995046141060221761701111762543380195142151878885588292130260647185", + "0x0.077b696f76893b930df354ab0e34b0df1508ee4503f673e22fa3b41867c5e4ffbc43b589d4cb4a00c472e\ + 4046ccc9dd4a2b88b59dde14b46da030dc5a0f825fc1d9ff0213e8b046b1cd79785dd554b78e98759eae454c23\ + 4fddf6ee7ae174bfc7c1ed096e905b41ce6b18511a9bfc9cfbc43c536393410fe83a634f402b0f18a446a3af90\ + 9a4079394959da6918bd9094c5b587839c67f902f1f107259257f4ae96549552e41dbe7dbaddda5b9d8fa2b2bd\ + d01ba920c27d6ff6e44bd8f0ef230d60508f693680e1d769f920949bd35768a7ff10fa62210e3caf84f93cdccb\ + a5238b5e4be804a1422da22abe509c758d0cf44f202896613342ffd0fa93939f0c9bcd4de899fb72b286773da8\ + fe9cbfbd51894ec97176996bf2b6a61ac27a5f524cd408e8bca09d7cefc329a98f17616d4b48652d0a3f14cc49\ + a9bbe75a69ae9167aaa9d1951d446e95bb89c1760a549ff81f7b1d8ee454047a7d3c3e244dc499d97b256eca33\ + 3d43933df1e0a046136e10#2940", + "13755175900776476.03444104347769161034491994978466673515315430911280875941467408228432201\ + 072744723926732268661761372710838010056791678637659254162102142124198282086034764229922487\ + 783612307113854432839997318024745178344073274492535681224805316900558167281372795857375154\ + 556654904332875058382920111153919687941523340022403648029377155100560618075774147398400587\ + 446623619383420263487024723715538921428293815054071349051549046244877203394687286110159347\ + 188168590858399073350484327515115795260226962105536078430163098017753828590552884767518140\ + 1985404905771271934", + "0x30de427563881c.08d120d36075efcee88657ce81cdcaedf45cd89aeca352b6e32212d20771ea31a54387b4\ + 8b1eb8738ae1d31c6213ddc44bdc809d5f5b278e3449ebd13c9ab8d89ec9f0a2d87e7233cbd5128caca14e0c42\ + 61e5c9ed6444b50d0cce082673e3c80b1a7102c8fc7520036bc3c6900dbcff7cecdf27ac4022bd4095736dba93\ + f47ec8ed66154c32a8eb07e14079a264e1e3370aebbfeacf3a1bbfe7aa657d9911acc70d626a35a29d86c84029\ + f97428f7cd8a3965838abf5dba9a9943b07c0ad2541156ef8e2aca1afd50c7dc55f986c835b95647701f744563\ + d15716174f2ac444#1845", + "2.124790384741531086324618396766014790807036315098759090708607153306148130187657728807205\ + 824808003798574987452867827342282934278081982848900135498971286785256137258700150407383617\ + 040883394430575593960834148265479663570529896251340120502267014474793716347382140126837773\ + 997589830815187190064041312015350810806968062929485379465521677249527992330225473850965169\ + 559943150658138282772411679190301632849325467452565481282203194749783450341076382685241552\ + 308193411477432500590221491760317417660435511777399629140824293491122934845121250984106958\ + 267596015361360781611025519421253206751640221273565905944385402975185311734694681019948131\ + 664198303801199498616289444621169851399879692298796098215712787193626312888177618196672010\ + 550069281366814417353104090880010484400040465312380510548737422916103805415326232623198929\ + 338433641210905412883566788706510371353536321443505713555119784985687877546815e-18", + "0x2.73209f5170c5b9aaeb5a7e9e79e1dba6ba9eb57b8701701f4d2be387a03993b7e53f907a48a9029ff962b\ + 4eb20e6ade6771889642b19b1985ec76b2b24fb517b27eb86681dab6bc7d5a5a203545d850396986ce5c6f9542\ + 50b478a0dd27222c6c45900f2d06dad9d7f78a79b9978e3ce203479c5dce6dde3affc40e370565c038007c8bc1\ + ef1fdf0f6398b88721063c52e5eb2c4b5ba1f10d93710d5abe8aab35f5bc5cdf7031f7765dd4f9d4065b1b5b86\ + 4ccd6665b73715bdfe783fae157cdc8a78e9d053cae011d4dddf28499ac3809e290ca0a221e38d2a6dd8d01980\ + c64da2f6836e0815e2ae3feb8a0d765808afcbdf6df10cf661eaf6c064ec8023cad01912101fb7e8b732b555b4\ + a053a203ab5ec17c24af5694ed7db4f67c3c76a7f360512bc9a2018d2860111211238048d21af3d79aa0904474\ + 22c0d9c9883b2f3769a5fe3faeaf8bab1409329c376b70c7b54fe1393115359c5a7ff43560bc0e2548a02ffb68\ + 184585e5023a6fb507d0E-15#2940", + ); + // - rm == Nearest && round_bit != 0 in div_float_significands_general + // - rm == Nearest && round_bit != 0 && !carry in div_float_significands_general + test( + "767950667289861979450190915916317600206727962344150969868.8721759327117422801652737665276\ + 756590281054535919141164571740727630029753345081284383462360338144272865435150624843971065\ + 632159910277471560574746205336214689461444841220676837587640834824669960199738043592424986\ + 826697488691269778053087892841924823231361961899657984958299046295741089107389167540777341\ + 1137893901502419455", + "0x1f51c7714fd0115fee394111538cd8cc2697edb4db72ae0c.df46ec035af05536a25a7e2694997099b2577e\ + a12f12bb82f781cda7cd6a148cc07ab56a0bac9e90b8590cb04b95fcb27209c3c8704cb6940c7fb857c1688d50\ + 6042d2fb6c58e0600ed4d86a5af398f029ebf3521880629fcd23f2bfd5f9447e8dee8310647fde5e5f5e2a0a18\ + 7cdc4e8c046be95417ea73f5d4a1962ebecd092b613af810#1250", + "51.02908107282950125513822733633990251324880237789609831750259919822628384179764854139813\ + 664310170076349095466129599769105832710389521373306698912599298264052853550294941822816681\ + 854313580668986120583821047373123379751687690065811623363578923931243167028825931454472450\ + 957582633858214796963862561877157489833071159740156527107422181977546544800568916528954101\ + 973657910504690951238460938847030239913388867386095316629182004723248011669496406544341717\ + 280330814897033602543594303927085904297027340275835376721330553519116838042737905906942433\ + 571685773257005175176741271374980135164819404821829229591371965448368260666618720681201228\ + 891015077648242337901859343084853665103006650868094946302847691177013349096688713595881758\ + 621480481903927608236275982505035171940737146501502983532266096788435188627685343250723400\ + 305856753098249087347464717300786991295322157886984156263306019163631926110778355478267431\ + 730519001037411438399866507817311259465545754442998333101310788661554118860610086857525556\ + 649462275011688416941329847092728287810185063940836755796270353054485056127471728114260616\ + 408519706805571508639638485588089026599284155688404740772260862102363921554760355678529807\ + 545078380365647104062842403550988330511500383389703046031841433893387481098301402534069795\ + 658730174573583314000979689827444189825731612831252242895060479770394162281620141901978731\ + 360879005964038152579829187416621515149774573766217606037565254139422563209723838864340747\ + 448492223949482531030183865551640816462517599780266133382572731428229045787209942986614817\ + 192016158247860998226332096129248802519217902568127470669978186812858044800325333178140023\ + 387809105983555698845635663825858578549915679237164757880235025950739307212793316009945989\ + 415835829851915334677834156538103555704104713171341701847682567317855121655570126973890951\ + 3929068030854124664713500553256", + "0x33.0771db70bc3cc1bbfd03fee9ecfaaa1f99d76266a08107a7c922f5787496298c9bd6b5bfa13889bc0bb1\ + 0f2e280f2673b20cb2191b3f747978b1483ed5890a8f1e9b4ef8665dff89aeff7e04820fcb58e76837b70b36b4\ + 946ecf9ebe8fba5e510503f922f8e39500946e3ba0fd0a28c3a881101047c77426f1160e2835ecd5cdfc3c85d7\ + 78adf772e0b5f5d5913cda27866ff4a68981bb0b247705d4a7a13e0cf5df9064561c207ad89d6bd10ed4faf445\ + ceca3d7f86bbdcd652aaf5c547a0071a203dca41ee8ec829aff439308e3dd8d470556949fb583c7ed1bd6c7854\ + bb629c27db1c0caa83e77e13d983d022e1865331aa5f67de9bca45976769e471933efa23a7d5fe8e03b8eed13a\ + 3920db5d0f4052f811bcd1955c217ad35a8b75478eb3f2e077ecc810af955e23d57d0b957bf2104261c9f16ba6\ + a16f119f6d83e2b35b1a28b6fc7a029bcec426c495328cba2082e252a65c7267a9a83365475cc6b4672f77d481\ + 40ec81e987a366445896d2ae795891105da2f608b56dca4a3e4166c6a0338423e51de87dcbfe3717817893141c\ + 8b61f1377d82379374f5ad121cb9e04cf51776a20bc8b0ccaa51862efa4f51d52333818ee4877c039261bcd8dc\ + 152db0a6119f3724603b4aaf9994eaf197d5adbcb723d1dc6ebdd8d2cfd37952c4128f3b79556ea134b7193dcf\ + afdc170fa41bf528ba4deac3f3d79d4407db9fd076aaca428efe74dbbc1bc7fad8b57ab1a693330f49aab1ddcc\ + f26bdc853360568f201c8fea22c816ae67afff2668debe399f951e72144cfa93dea4f18d1ee734ed2bf350fed9\ + d126c9b660f6b27ba5e13f15a8be20837e071c52d7588c0a856a969903419e91d47e7011235886759942c1c0e1\ + 896e1621b2d23df869694531248722482999c8600632a5ab2279907e29cb3c38994bfbe299cb368a72ef45ecaa\ + b9646b4f1e2f37f24aa954535b1ba220c8e91dfb8f81e56dc45ec4cb3181511fa5b1854096fb3f03f2aa052eb1\ + 5111548f398b2a0ffeecd95498fef2bd7f25126507f63bd3803c3a9d1aff24563f7f0baf024307e9c75#6074", + "15049274867282653916783425765897232338286237097021544510.63055696334657926692700975852105\ + 429908991325181901560777184807721684871576977542689434849596891044659963521044055457283641\ + 367304991334226236960366994118987961185804836414630696056584495778598754606288486597978327\ + 332370268104018122071463105903604569912790301532188931593783003198530412792016208481406460\ + 177569545284296438034561831086095957417103960718034276692579871391678752019863068680376188\ + 441084892942908419595289335759422879108451807263984856494740183999962091220506257869533189\ + 151879060260534882539324732360323776701789524149049182180697710000483323367419829770508959\ + 886298233038628402259126153349007515813222501560286947664943532169644098519601985837510236\ + 220345218089637472842801890223279059211522040546360301667071765816467200381174390649332596\ + 068474921226001156721359127966627401319343668619013146928630922944213877247277873392955093\ + 504639915667110210542526572018725370251615388653789028473354868425502960351888594917293217\ + 742712292964655900915998259809033409553076012583762301750508167459913039705278696038307105\ + 198133823120123667996810391703122691279674638629684591634520584549627376733588876153831722\ + 199369165407756045645488517825617351416613370266999295351664343537186993481753740631996768\ + 537474147168714208012012313452364629821090786481898210882140832386720226088895885830143936\ + 713915428453413001094302216345205004980013281182978168058085052927135299009881922560519790\ + 174395754146412113876346433499785448301225654969985504964945207336686282652994022882395571\ + 250336046288750244045997533647713495015654011612857222465008362940468446125031495141758501\ + 398188163302138089732641998828146315905675208381266922364102647252983963785718802006725178\ + 667871858412814374481149992996719213942377608145948042933317201168269095689729130915320304\ + 63030844892155532105060912300876", + "0x9d1f2bb817353ba61ad13135f94f65b1b52180f58a183e.a16c2e5fd6b05e4155475ec873e35d0f193a9765\ + ef45957a4681138fd789135172e7be4efd1b67c60d22430a10832c82a4dc4a53156de6d8638ce6ffe089ebf880\ + f2e1c68c90b576b5dc0b99085865ed663bd642b7743ff5500d4c6d3e2cf4977af36122c98fc49e81ee87b80d89\ + 3fe81fa07bdc5986b40bdb0bf7e6bfde432dcedd2063308cf685bfee2b964ff62d434434a9518683156e532f30\ + 11f2ac8f98a75178cd412e00f2261a83f952b6a94bb97c280cb51f16f85891ddd7fe6ad8030e20422da11497e5\ + efe8d88db4f96479fd0b16f3703dca8946d944979a3454bb8155d8dbdd3a765584148771967d02f798d157b6a1\ + 59e10461bc83d8ec9e55b557614c35d75b391c0c9d04aefe96cab5078bd3a13d5618ca219640c68919f1fefea9\ + a3d1e47a3fcbc8c19de2210708fd96fed608648d183fd4c1177d803a49f7d276f940aeef6feaffded75f8e03ce\ + 33df996eeb67ac6c0bec62d821bfce22d9a30baa6f7f4963eb4eaa91707ba1b12fd6f3e04f75cfea4dc39c6488\ + d72e86c36ba981115f42300b97a7caa427023f16c4f66213cf0c18f04cb6aa66e4830cc7040b3103e27c2e800a\ + 0bce21b653566628a5bb8b0becb80b441801f31aa100fb4539cf7e4d6d68815a666c11c6cf4ac97878c551c043\ + 3750e9ab6fdeb65765ae3ece107302baf12b3086988bf4d0b37206bde4041cc7c4fa79d38170719e92c052187e\ + e810ed1b2b425c081512c7ee6ea722c413215229ebaecc207fb1126644e66dea7e0139682e90f91c71b579cd86\ + b91211305fe40770c3176e35b783732c2d74c8aa1a09da66c4f34dfa1f9fd35662c5c3d1f82eeb37498b121357\ + e73ed7eea79adeab91001b3c63b1f75aa82793cd1a2b39e1bb09ecf5c6522ccc46652d831abe3ad1f9bc301df5\ + 2c646068fd97c0402a29caa4ea3f4de8e5fb8a4d537d45d685f87d05d95f7ba40fbb6a919e93b44fb78b9c80ea\ + 6c0a75b4dff2f73844bf4f7172907d8165f606a47821da925eda50af0ce44be22fa2b36d56e1d1698a8#6074", + ); + // - s == Limb::WIDTH in round_helper_2 + // - n == 0 first time in round_helper_2 + test( + "2.169542166817986625468879014599175406350620737442480370882139687492174119453066131804433\ + 632496405940270655469169364935548092764516132338564210201385531365409396738163453793191332\ + 174443470862749001312126324808896288354477512722829484994475343567852816045883088813362218\ + 109536965926916816038009290804934132950340684582117875938116310656669280480683072639988319\ + 858148103369026349100099758130382359401952836454392007054797540845974323496094771400665868\ + 125503436816661354237720713751777833086011158065863046075212704099660843597053397398549954\ + 8348685976904925033580113969653312280822082757679509546197165e-14", + "0x6.1b51e41e16de577dd7b5a3a6222357b305d4e7313b1d47721ebe3d4275ef95b0d98ad997627ec7acc76f5\ + d426b7c5a9333cbc0dec080499093952901e541880379e2fdf874d1d931d1243e2b2ab072c0772ce94734ae65d\ + ff7afda628d44635b3fba75efa9bd2c10d8bdcb3a61a8b6a7697f598758d80bd808f17f8351b1761850fd75cc1\ + 9f86409ac25dd27dd0ce7c26478dae9d50aff0210dc4fa18674fd87aa017255dabd141e1289a7e734e21577610\ + bf92b6ce4fe21881cc5209081e0536f0aeb1dcf6e288feeed183095b510c09e50c432ef280e742528c0c4dd6d2\ + 5e65c8b6d19c28914472a930aae1ad7fac96f6442134ee95f3bd8E-12#1993", + "301180.0045246172416425721655892719573457356766058630317841133942315022590404351104810586\ + 213517139802439747677458029756555586634849124296886483237621871644459126081050822492233083\ + 707945595254133438910359944302659214080172068073620764660184379004827633051943726032292014\ + 225559234820452819113849827971319776547835482966443724022128469656550054145203573809984759\ + 336239968661049955088445384576034864711412948863817402256055440443111246220943775270251981\ + 245519547063921282094595332683031347213016637666849460902039610984880445147686118036204784\ + 051476863264255027838976527798504452504598268980029728768388473210371246534136227460265249\ + 86471927", + "0x4987c.0128867b146bf9c05b0bb90d2c480c2b610c9c19a0a03f58f0d0aefa84d41a94dbc0c1206d80eab12\ + 18d0f5e72e0b72a6f063fe0f604b1eedcc3760c7f60b2aa6e35735292ea939fa59fc7da94b3e86d7bbba5f8ef6\ + 8136a9a4c5d98df58e4ad215fee20274cd18a324d8b66b0119d3cf93efacf51659a9814222c8f9b53fe6356392\ + e2b27f1ee07621f888214936f129248d805ae614b37cae5b83f51b2be167dc62ef96c1322204921369dc6c7475\ + c195aa735676f467be6a45d895b6b08fba56a7919ac216a6dc76cf9f5c3184a2ffa7b1bc3d8760c250d651afca\ + 18aa90ff70ee4532482978816617fb02f0de87b2abd54886d1c7c16d62550d5fd8a4abb55b0c4ebb8c#2111", + "7.203473451839519375659920800256968930150281137907207966420457324091308743561158996788387\ + 290694159461823269997598092194316979651412090098764718003237064733792291895103263169730962\ + 123418174759909091404064508319172962888992299461557410206033700688023479037478761668781891\ + 761303156472454780198812373188616203221872171676002219543916314587725944225532571475160352\ + 707938049990541748698746656039607206067984173221685967465441429896808706646646536972493098\ + 282122681082474772608417991249668805473092287771115239878542545454824251859441724816281902\ + 754574769925885897122660854445163455617440019293712118274988718965330199709067927675503187\ + 81705947e-20", + "0x1.542ca6851865ac89e311ac1608cac34c9fe637305345b739b624981a50028d6f60e7fd803167413e1285b\ + 796e7a5ed37e1cb19125606ca9d15a697c9c497b14455aae6477ad96ffa4f216a14878a9802e8350d104f0b9d8\ + cd86ff511d7efbd74d40104b107a9d7f33d0e8894d3b157e46b7fd4e6386f823e75ae0efa9be33aac3e252d7d2\ + 411f8e2afd3773f3914778d26a6b76f5569fd822db5a66db515e3cdd6699301b71cbdb73f07c24fb20d0c66059\ + fe1f236a4656c3f508e25958bdef5ca863d7950c5740d7849b46bde7e1a38b797265dedd7d4dfdaee7bcb69dce\ + 887bddd7a7bbd45a6561cfad8cd840e7d95599a81bb274cc02a161439f7280459a15c9865ad5b658ed8E-16\ + #2111", + ); + // - n != 0 && tmp != 0 && tmp == mask in round_helper_2 + // - s != Limb::WIDTH second time in round_helper_2 + test( + "7.967842945782984973942186035477141750978306951371418866981413625233901049016799636923049\ + 043510064598367854094347269064974737243308027061881036076018766384961823690368428913274793\ + 537e-19", + "0xe.b2b51b3ba9b3fa4c3c91f60bbe2f30efe9403d1c1ed1fa2688711592167dc11f579d747f20609a0e8704a\ + 660072ec620d514ab31d0845381f10e96f76ac41c97c2a7b53849757dc846fdeE-16#599", + "4.290314881292277334232122993869736164625712811477787127079554140127474408529492187148865\ + 860241941174878594521708166855716060386064937593774872957730026516247807479269506509835640\ + 014575725456051856772978910171974972671741113731811243859146099959299700690748160884209812\ + 639693266282036645473254451466381125403186024743001502094065938286200460441378264282871237\ + 445194601993083290951436490295842815606015494575193282638997440331311694865085507331318327\ + 437042408938144577985735854973264189023250983346696190654635795462654945584732891184659237\ + 746883228154089313101793763347136552004708447204474905674167880735273390965084667673056531\ + 378593414825374458582134295243495148718875340371312206621884585775967428131940924035968587\ + 526069447315202760539547246403295371510536211424729007907823710381420209210303664575050843\ + 559776729235120592670693730372232402604761499044741741752247404544150954858075273585139895\ + 643242778698674255451287458469387850297372316908957826221759549123594364155475346755476293\ + 552962991845182999537688763267208310118481794778770137863789646906639637779481228371710954\ + 980900001879766864929946144490423459237336070803276511200399191948305713293997532907864745\ + 24489311444825214442690999e-14", + "0xc.137f67f6b60895b6164f36c36d5b134858a21d493d7d49584a1811d76bd92f10b6d0aa0bea20843896e0f\ + d0d2e93957b024a1b5e7101d0f679c3dcc134107c20f0664acbfdf6bafac9013ae41ce018c62b6cf36043f13a8\ + 1c35291946c79569662de17adff4ec759b1ccbe440675ef95167b0d5a5481ea6e7a6b998233e094436c8eeaefb\ + e21fa0f9c24aad8d11f378034d73a5daec0111cef1b0b8426dd5df78555318d44c992e40ad5fa98171908c4019\ + 636becfe749a93747c965c11e84b68df48e887e933449d42c1ec5c2d6a7658e91f6d68333ddfde5719ca117d72\ + dadec43975eb0b6b6a076c4ada32d70b0e93250cf5e8836b11ad6a8b13a4a957de6221168782640f2313ca3716\ + 3e4da0decaee000e5824d53c71d0a36a55295f8ad1c7a86eb35eab709891d1a6ac96a10448e0e307c7d6742d8d\ + 0617a3e21978394d0393bc9be8e32ff2d87e85ae44c3a76ac79752bcca4927ca5dc6dcfc4db10793dc0cfc2161\ + 24fdf30070db19fd8a89982adf45a408e08499b77cf25011c54cf9270bf491a2186e1a5fad26087812cc3c2446\ + ca7e5457d75f66fe9e736ad07c6b1fe4b20eaf1f073d454f371f659f7402d24e6666c8e212ddccf50c22209ca5\ + 7651a266ecba0559cacf587691f7f7df3389d9968023d71b412cc20516c9b1d00f1392474c6683bd0fd6c6dc7a\ + 705d88E-12#3966", + "0.000018571697337476093645597974800042221391343383471511758884717235995391699590980821846\ + 925772010524277797520625056343676345716562878283777572676679678398279369283853673423775272\ + 117775978501001731220831012727542639628984101788862199591237806493805996059161201835253203\ + 204357442043212398495525692960904672132359565047969002327766123188917268873022220728326927\ + 266813579456518458545345939557868848624450974456390610446369728959726525392113471132021539\ + 038960803550352390128253151270734177749632737865390247648212171456318006032507634424453843\ + 795159031314496937836591202252458892414236797451738560115150573320872948069964155298984838\ + 456270978739037104719669912968807593222214861520588395175617611807975267322946381339673265\ + 479787948188151606275111200784895864164305724683464061829109671306661764726602634895903888\ + 287506327660181397735839535481997625450956961420572462126703944263526095290954835871182404\ + 868513321447417245068813964246287015709186652991049553947407472630595976266674750290084010\ + 397575525528176465754260767775733418629588880876176812207672741703984898153224615968196909\ + 775917982890995046346113085550279268258183711136206964350043642244181512435164664671221839\ + 6370838653686792137638621224928", + "0x0.00013794d52b8b1e96ced9de16a585696e655c080cbd5da8030eef302763f4138b28d7261786b8ff50bc6\ + 9d0a5f06f20dad7ee2a65fae9caeeaee187ea820eae6fd4c8a673a92def1c9a165c1aeec8807ddb464eac6f550\ + 6dbe6d6e3a21a035c4472d414f4887b05775ede2ad98b9b380b663c0929394c811648792ef20f0756b6bad50de\ + 099fda3dd792ae5616df8837945c3cb4cd833fb9bf0db07243887c0a8fedba7030c428024be8572bca9398f563\ + b2a661574fd7faf130ac3d404dbe94b7e0ca06f440962616e1879d4f15895a10229f04969c26dbb9a1b733f734\ + fd2be1c88c7b20af178cd1d3fa116fba33a435b040155b5f5f28f0668b798810c2acb1faf0581e46cc71e9b07f\ + c9e4ebcd8a96a7d7d318d649e4468baa2ce2cdf9b1adf74f6a6b8b95a3eed5991934327ddfeb243e80db0c230e\ + d593df31dce1201e64430a27d39e6760dcf2086c1cb86bfb4e9211f18940b72d1a492a5b9109c0fdf4f5fa9fce\ + 9e0ec199756ee5f8e69ba7ded6b7507facbc46df62adaa4546b3113a80e7ea40bab782194bfd006099f6a79bb8\ + 19aad950497cae351fdc370756b86b3188e5c2cf71ed56fdb3683c9cc38facff80b0f2076d0f3b3a8605ca24d2\ + c8b6301601e23b50ea0940f7ba05f92ddd4a644cca6e420d6bfcd06caab9c695ba67b857bc57e1000b5935d0a8\ + 79821217280#3966", + ); + // - rm == Nearest && shift == 0 first time in div_float_significands_general + test( + "3.494003589335061592114850452482839587826456952956376068177291318828682713177358264760784\ + 874304744009907216335963217912223351596098015455390432300579562836209635380394751634810606\ + 195414389573610568068623776330707730813932586805062287543490729241818555718410383777926489\ + 343323917900958772688451527795643412381235039158654803215405274640835172391547486080681691\ + 827169629800140882523056966137099117587677259077996268577162491409610597231997851472454718\ + 312803304389117924206548413988545367622912505139619073824279361037770537659001099972259551\ + 367613373821227769095845567435994753397767332318253172120529133505790353120177308303588487\ + 770407205738279213609665027613843515660027068482463985188375646552261141849026408186728824\ + 80307838589616979262426550353243006148083216398932181e-12", + "0x3.d7797e014d587584d7875beed50257a2555726437bf03fdebac1110cae2c4b64f09f9a338bf2ca8b1fcf5\ + e0128d7f387a40893706e25c04e65fdd316e3fc348d2478632d632bae209325b6c681dde52405cd7f8d9707d7f\ + 5d6de0abb73e130c41c21c4537ce41381fc43788187dab4fa280fa46503f1890d663ca441f49a6a7e2b712e710\ + 4c826535fdf1c8ae0282d162e3d128a982e44f67c6104624863e7f3c2c60833df521e5bab88feddd4843e4b50b\ + 81ba442bc612787ad38f640412f6cff81df9793590dfa6a0debdd7f2f6de7a089fc50d597d700dbeeecfc9d795\ + ceb9a69d05db5c520717ddd7e73fabaea4e2cb06b1e1874b8b541dfca2083cb277e4d1bbefa48c0a427afea0a5\ + 87cd5085c2ba28c1cad42a97be72844e851abf698ac844915e9f5ac4af406a2c354aa055f3c0994b7932d1bdb7\ + b4999768f776148E-10#2560", + "8.388557903692744678886673027706512178020882171440574341138664910770681048759242342335520\ + 689291884051853125391850946672822384185374426629671262437149651332606541726962233658521936\ + 440197380293004778812876511148916284206096731251130678261803308370362817534297504354768207\ + 175302739282372189357904919163400327254111204148827422042723518774290057028465296755126014\ + 371014512774422430414368313070504306047237723842986944935010614200247398223867859750512432\ + 528263508555538801970472032683504663202558316239308702078808690323956381650112536926354687\ + 819619269837340011822483859668579241157516055938780563664184620140501025776680716962470155\ + 2e-35", + "0x6.f80c88bef08546fc8a21f0f2152ee0612eebad2635acbe0d49ce7179b387d0719cd657923976ec2796026\ + 5e330a5e71c0cd8417c2cf919556130f9b353cdf2435349f846c895ede372648bccd9c217f1bb7c3e4197c1806\ + c4744c8a05ddf4f67946a4972f056d84028e7023d956a95b2ff067c093002267f7015fecb9ca5ed8f58dde48d7\ + 4510e965bfa6478370f4e71e5a240dabdd9a4d6e000d4af93eea8510c6c4e095290bce062925fd9a7245caff37\ + 8b7be01d3b94b56154cbeb98c26f78338a98e416fa9acc3bd12c4953b058efdcdbe56335f952208a15166babaa\ + 698da808f96df97655d3f5cdb4768e6370755a01515d4ad54f625432fc742e9121b7cce4fdb08E-29#2088", + "41652017300815899948547.94831484736938823572318695739742204735159366375620848030675947597\ + 937407214848121136435440017047965685656179645007771422864559798518659544278806178160023554\ + 020245599674536568425190916908552958650848910192845046055088066614557330847090320384899468\ + 575304634050066348271499359839369427201019441174516439045175255034723132436872248790761539\ + 506937527488424041602486298663492699846695028977559705152038731125314966620233281505474337\ + 677248672173837029868825260085661764008715204976773612281854954844288452423998027475082981\ + 779489389492756600188312999400831430516184077432877044587246391185262444911853744883006186\ + 684049728461939709785134255700251964580618924591175050653894151676243677123400686218961075\ + 24208104943935667403367286485079704207117845193523456", + "0x8d1f5db9d3f145a7603.f2c4c307c343da5b63ef331aa97f5e951921921a937336258bc4ab65fdf9d715d36\ + ef6755e61dd29859283e35c618271ec076a196c3ddb06ce536bafe52ad10a521ebfdcda2a3839fce6eadd33d87\ + eba1d25c5eacfa66f0af4f1ce568be4792717319611eb807fe7fc0d855f2cf1b099f908a269208b3ee36d33e71\ + 3912e0557515bf16566f8cc4c8c45fd6bb2ced1b3d3f27c9b272c6e5dfaacdd66335f658951d70cd7b3190aac8\ + b90d7e564b5c0ac68a04f4681a552c50de11c466e3ac1230d426fdc851e7d5705e73d7ad30a82c2febb82c46b4\ + 93762b8d7c80e514c1fe29a64d4189fc176b72bb816f1223676b93d38dc33a2fd578eaf5fa512468b21e723d6c\ + d5595dac5bfd84c94e4826fc5b9aff74dec22c3cb43d7970a1359eb2642295a920a70da20a166db400602f0f4f\ + 2aee9255f2251c#2560", + ); + // - !round_helper_2 in div_float_significands_general + test( + "3.999999999999999999999999999999999999999999999999999999999999999999999999999447285212473\ + 955543975273480780774427448575976676077991358482977909210124597604668289823519777773553500\ + 1249731874464215297923136674027554116062077582682832144200801849365234375", + "0x3.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000#2090", + "3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000038180485e-31", + "0x8.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000001ffffffeE-26#2567", + "10141204801825835211973625643007.99999999999999999999999999999999999999999999859870153567\ + 518292907627041671008386871973805812348422824293171611020891731413939851336181163787841796\ + 874999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 99999999999999999999999999999999999999999999999018341217", + "0x7fffffffffffffffffffffffff.fffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffe0000002#2567", + ); +} + +#[test] +fn test_div_prec() { + let test = |s, s_hex, t, t_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + let y = parse_hex_string(t_hex); + assert_eq!(y.to_string(), t); + + let (quotient, o) = x.clone().div_prec(y.clone(), prec); + assert!(quotient.is_valid()); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + assert_eq!(o, o_out); + + let (quotient_alt, o_alt) = x.clone().div_prec_val_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let (quotient_alt, o_alt) = x.div_prec_ref_val(y.clone(), prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let (quotient_alt, o_alt) = x.div_prec_ref_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_prec_assign(y.clone(), prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_prec_assign_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let (quotient_alt, o_alt) = div_prec_round_naive(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient), + ); + assert_eq!(o_alt, o); + + let (rug_quotient, rug_o) = rug_div_prec( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + }; + test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); + test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + 1, + "NaN", + "NaN", + Equal, + ); + test("NaN", "NaN", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); + test("NaN", "NaN", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); + test("NaN", "NaN", "1.0", "0x1.0#1", 1, "NaN", "NaN", Equal); + test("NaN", "NaN", "-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); + + test("Infinity", "Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal); + test( + "Infinity", "Infinity", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + 1, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", 1, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + 1, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + 1, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + 1, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + 1, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + 1, + "Infinity", + "Infinity", + Equal, + ); + + test("0.0", "0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); + test( + "0.0", "0x0.0", "Infinity", "Infinity", 1, "0.0", "0x0.0", Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + 1, + "-0.0", + "-0x0.0", + Equal, + ); + test("0.0", "0x0.0", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "1.0", "0x1.0#1", 1, "0.0", "0x0.0", Equal); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, "-0.0", "-0x0.0", Equal, + ); + + test("-0.0", "-0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", 1, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + 1, + "0.0", + "0x0.0", + Equal, + ); + test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, "0.0", "0x0.0", Equal, + ); + + test("123.0", "0x7b.0#7", "NaN", "NaN", 1, "NaN", "NaN", Equal); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, "0.0", "0x0.0", Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + 1, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 1, + "1.0e2", + "0x8.0E+1#1", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 1, + "-1.0e2", + "-0x8.0E+1#1", + Less, + ); + + test("NaN", "NaN", "123.0", "0x7b.0#7", 1, "NaN", "NaN", Equal); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, "Infinity", "Infinity", Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, "-0.0", "-0x0.0", Equal, + ); + test( + "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, "0.008", "0x0.02#1", Less, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + "0.00813", + "0x0.0215#10", + Greater, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 1, + "-0.008", + "-0x0.02#1", + Greater, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + "-0.00813", + "-0x0.0215#10", + Less, + ); + + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", + "0x1.0#1", + "2.0", + "0x2.0#1", + 10, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", + "0x1.0#1", + "2.0", + "0x2.0#2", + 10, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", + "0x1.0#2", + "2.0", + "0x2.0#1", + 10, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", + "0x1.000#10", + "2.0", + "0x2.00#10", + 1, + "0.5", + "0x0.8#1", + Equal, + ); + test( + "1.0", + "0x1.000#10", + "2.0", + "0x2.00#10", + 10, + "0.5", + "0x0.800#10", + Equal, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + "0.4502", + "0x0.734#10", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + "-0.4502", + "-0x0.734#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + "-0.4502", + "-0x0.734#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + "0.4502", + "0x0.734#10", + Greater, + ); + + // - rm == Nearest && overflow in div_float_significands_long_by_short + test( + "5.8208294e-27", + "0x1.cd2c72E-22#24", + "5.322295e17", + "0x7.62dbe8E+14#24", + 3, + "1.1e-44", + "0x4.0E-37#3", + Greater, + ); + // - diff < 0 in div_float_significands_long_by_short + // - sticky_bit == 0 && diff < 0 && i < abs_diff in div_float_significands_long_by_short + // - xs[i] != 0 first time in div_float_significands_long_by_short + test( + "2.4914040842493675536005152793625253098043524808533216867315977e-8", + "0x6.b014710df6d8d0fb1901206ed24e1e002b4411ac77d2348fd2E-7#202", + "0.38945825655685", + "0x0.63b3894b11a0#45", + 74, + "6.3971017234954763411416e-8", + "0x1.12c0e0961c12c850368E-6#74", + Less, + ); + // - xs[i] == 0 first time in div_float_significands_long_by_short + test( + "5.94670436124321717863912904768573447358", + "0x5.f25b378e852b0522e85279dd6e9b5e20#129", + "5.93e6", + "0x5.a8E+5#9", + 5, + "1.0e-6", + "0x0.000011#5", + Greater, + ); + + // - qqsize <= u_size in div_float_significands_general + // - qqsize <= u_size && !extra_bit in div_float_significands_general + // - ds_len == 1 in limbs_div_helper + // - vsize > qsize in div_float_significands_general + // - inex != 0 in div_float_significands_general + // - rm == Nearest third time in div_float_significands_general + // - sticky_3 <= 1 in div_float_significands_general + // - qh == 0 in div_float_significands_general first time + // - !qh2 first time in div_float_significands_general + // - cmp_s_r != Equal in div_float_significands_general + // - cmp_s_r <= Equal first time in div_float_significands_general + test( + "4.171457951045116318706366624151444947334895358793933e-7", + "0x6.ffa0a6f6450242ee750c35f12c7b17a438109694bfE-6#171", + "6.7041531299542248604361e-9", + "0x1.ccb4b589b3974d3c8a8E-7#75", + 63, + "62.2219968754442595", + "0x3e.38d4c987d8e7580#63", + Greater, + ); + // - cmp_s_r > Equal first time in div_float_significands_general + // - !qh2 second time in div_float_significands_general + // - low_u == 0 second time in div_float_significands_general + // - cmp_s_r != Equal || low_u == 0 in div_float_significands_general + // - cmp_s_r <= Equal second time in div_float_significands_general + // - sticky_3 != 1 && round_bit == 0 in div_float_significands_general + // - cmp_s_r != Equal || shift != 0 in div_float_significands_general + // - rm == Nearest || ((rm == Ceiling || rm == Up) && inex != 0) in + // div_float_significands_general + // - goto_truncate_check_qh || goto_sub_1_ulp || goto_sub_1_ulp || goto_sub_2_ulp in + // div_float_significands_general + // - !goto_sub_2_ulp in div_float_significands_general + // - !goto_sub_2_ulp && !goto_sub_1_ulp in div_float_significands_general + // - qh == 0 in div_float_significands_general second time + test( + "3.7563361266e88", + "0x4.b87f4dfa0E+73#36", + "6.769173652614128677797571270436826716e-13", + "0xb.e8909656207637d3379c02628519c4E-11#123", + 63, + "5.549179736559369991e100", + "0x6.57b76abe8193e56E+83#63", + Greater, + ); + // - sticky_3 > 1 in div_float_significands_general + test( + "6.4231308808e37", + "0x3.05280069E+31#34", + "737445296117739183341894639.41419934820825930816963962148939959402654898", + "0x262001d9b6493f3dffcfbef.6a08f7ee9438af0b7e2168670bbe153c76748#236", + 61, + "87099760682.70268959", + "0x14478ce02a.b3e377#61", + Greater, + ); + // - cmp_s_r > Equal second time in div_float_significands_general + // - rm == Nearest fourth time in div_float_significands_general + // - rm == Nearest fourth time && shift == 1 in div_float_significands_general + // - rm == Nearest fourth time && shift == 1 && round_bit == 0 in div_float_significands_general + // - goto_sub_2_ulp in div_float_significands_general + // - goto_sub_2_ulp || goto_sub_1_ulp in div_float_significands_general + test( + "6.4231308808e37", + "0x3.05280069E+31#34", + "737445296117739183341894639.41419934820825930816963962148939959402654898", + "0x262001d9b6493f3dffcfbef.6a08f7ee9438af0b7e2168670bbe153c76748#236", + 63, + "87099760682.70268956", + "0x14478ce02a.b3e3768#63", + Less, + ); + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 && carry + // first time in div_float_significands_general + test( + "0.00002882366272258", + "0x0.0001e394b0518e#40", + "4.407913996892399269446698943482826e-28", + "0x2.2ec4fccc4a5e21c3fa6da2c36120E-23#113", + 1, + "8.0e22", + "0x1.0E+19#1", + Greater, + ); + // - qqsize <= u_size && extra_bit in div_float_significands_general + test( + "13863336.632654341786855779405528442674244", + "0xd389a8.a1f5a28ba59ea1aca395f84bcc2#131", + "88.32972592752556369746097031876493672699524930031683012093294198918", + "0x58.5468eb1b5d957d68d5c161060f2abd3d11568e57fb44ace5b9530c#222", + 49, + "156949.8431822285", + "0x26515.d7daca60#49", + Greater, + ); + // - sticky_3 != 1 && round_bit != 0 in div_float_significands_general + test( + "2.60106", + "0x2.99df#18", + "1.12640651293023472114636230356467597616119208733434416176044102440877312604351521285e-35", + "0xe.f8f67659254f23c6296e8bd68107bb0d6543b0d65b1f5b85639b43d42fafe22d0850E-30#273", + 62, + "2.309165412400307267e35", + "0x2.c7910820f8e1a98E+29#62", + Less, + ); + // - sticky_3 == 1 in div_float_significands_general + test( + "5.3925833329420346441e-59", + "0x5.6a7cd168af6b5224E-49#65", + "7.055235440683529923035882801220195059780252442336634700998228376328e-29", + "0x5.96f8c4a5671f264deaaafa2151d5a576774640994697357cb67388aE-24#222", + 126, + "7.6433782802570609426763368452677453109e-31", + "0xf.80ab3d3f6f9720a3e3d6bc0dd473a20E-26#126", + Greater, + ); + // - low_u != 0 second time in div_float_significands_general + // - l >= k in div_float_significands_general + // - cy == 0 first time in div_float_significands_general + // - in sub_helper + // - len != 0 in sub_helper + // - !extra in sub_helper + test( + "7.326919700506453074257659445909468362437490080995085670582700901565e-8", + "0x1.3ab0558546a1bb0ffb3951411ea17cd193a72ecfb10c90503c09df8E-6#220", + "6.204773818244710788233721e40", + "0xb.65787b1d85852bbdaff0E+33#81", + 62, + "1.1808520205784374405e-48", + "0x1.b9cf274b9b9758d8E-40#62", + Greater, + ); + // - extra in sub_helper + test( + "8175446.9642736466252057884969624115178724187752436027351898906495229305213", + "0x7cbf56.f6daa340a6612207973c17246d0fbeab7366f17c873b36e8a7c5e130#244", + "2.2364028106870166695e31", + "0x1.1a461277f5c6a045E+26#65", + 62, + "3.655623631488002044e-25", + "0x7.122d595c6ad6278E-21#62", + Greater, + ); + // - rm == Nearest fourth time && shift != 1 in div_float_significands_general + test( + "1.274876025e31", + "0xa.0e9775E+25#28", + "7.104011072486714881105976022274735719942619445087760266603169705559e-82", + "0x5.6412fa517e8e5c9e2826903dbe9c6b4f020acbf4d07a5f83b6e4008E-68#222", + 126, + "1.79458620199896394199805694868744557485e112", + "0x1.dd946a676df629632baf4759d5af1090E+93#126", + Greater, + ); + // - l < k in div_float_significands_general + // - cy == 0 second time in div_float_significands_general + test( + "1312304952.868834018993672867833994901273914152677", + "0x4e382f38.de6be8013ae5b9256e2e3d80a6484417#159", + "805222139786632223922.788562923013680863", + "0x2ba6b3b5e2de25dcb2.c9df427d2e92a42#130", + 61, + "1.629742760446910473e-12", + "0x1.cabb579ba24a1c8E-10#61", + Greater, + ); + // - qh != 0 in div_float_significands_general first time + // - qh != 0 in div_float_significands_general second time + test( + "4.77e-7", + "0x8.00E-6#9", + "7.27595761418342590332031250000000280259692864963414184745916657983226252757951518e-12", + "0x8.000000000000000000000000000fffffffffffffffffffffffffffffffc00000000E-10#272", + 12, + "6.554e4", + "0x1.000E+4#12", + Greater, + ); + // - cmp_s_r == Equal in div_float_significands_general + // - u_size < qqsize in div_float_significands_general + // - !slice_test_zero in div_float_significands_general + test( + "7.37e19", + "0x3.ffE+16#10", + "5192296858534827628530496329220096.00001525877451", + "0x10000000000000000000000000000.0000fffff000#160", + 19, + "1.419698e-14", + "0x3.ff000E-12#19", + Greater, + ); + // - cy != 0 first time in div_float_significands_general + test( + "68094456598293603327533905548505297620013066911.08376291606058693773517767794501897994582\ + 258970805389024907002851553537297142201729190070813276436614829387252399053496817432401142\ + 072590738640749961499805778301047693438889653237932045230908598957544293121509337746443019\ + 818113697275492083034559948210251757918035033203320082922052180871824896122583688257790633\ + 347767288424884057738898369318200284711885269916578380577251435556820233836251778387280672\ + 557877138589743092466532437097578789439010809222705729003762084164876928991111619216295374\ + 407477624059748769343096515734766384609704158183422827373811211581562563854555563208285030\ + 789640954030131590715773225619459109078415421551825383051156907165239504581969296580217917\ + 201401107075438836986951972027346920300296173028752019760961905082742144822764332949493643\ + 236343403045805151576437841818592689216294090992083144539119316847195395330209116021520674\ + 687172083129681053947608634984318972146599189025048336884553676307718881472973047561666876\ + 170703037518590793048762200560314576630872589716790447601932356569152269838665699058277016\ + 66840662018065630567707390037462589298017636098402605937122", + "0xbed7606a24f1082b01518fdb3fb83b7bd6aaa9f.15717c89190a577b04eeec86844b1c5da7ec1d515c98354\ + 34d7eaf573076ade2dd2a181b60b144c489be5eadf10a8fa23688bb3d5dc411a80de60bf15d00f4e2bb3d1dd9a\ + 05d37673fc56cf152b3e89f3955fd67353655a855872202dd9bb5939503124c7c8c1c2e93073284ac47ffc59ea\ + a0e2d8533a243325fc33e1795ea157a7a42aac695237acf96951da79f695a7ba51387281685f9dafc3987d0cd5\ + f393a28b74f7077fac3ca1d127e47df74353b51a5191ef44d9d17d76e82b13992c6d3cb5330e49f88047554a32\ + 6085af468cf06e8d9d64da3bef6a9dcd50d9c3d50c03f20851ad827d200fd778bb6ffade66b04462f28dd87893\ + 32e49807a56a3d251a3123c64131caa8c495f18271f1511c3ebb467c8e07f5a65ce58538f1b5a0a5cffb750f2d\ + 2aadcba0995b2bc3d8ec2c295ded7fa6a05959ac7560ab0a8d43761ff672a2823d42f9a3274e5d9f621920a078\ + 13bf0f700cfd42309086f1a2a594e81d2cc56780a2d2146487d5c84e4a45ea287d5082ebbc00d963dfc85328fe\ + fe6406f3583a1d25b20043620066c12999c2438ae661a9ce3a7577bc39adbb7d9c6b2b95f70ab93d453deab5ba\ + 879c49217ce044fb8c99aafeab2a3c2d7b81d1420f50f3124#3778", + "5089003.986901636664002211687103226682676013278365930635943365557217778575140755071304051\ + 262677914765136974076241170290188547560394627827342683941547868265780205495768503547504471\ + 809839828485098007901365847412395780099805986364986150288103155890838726927248245864748917\ + 545776909957932766621125809519317578017645670025405880924769796697930801127403727804288556\ + 494641308619101409216398256844236435992132716137153671232504127486179270643290623882858426\ + 225419756589684747143027545016939069261808018044193898155688966291933573563069322732013621\ + 2807285459308838582521108293701", + "0x4da6eb.fca595edd73c4fe606a4af64c155ce5a5a06c66381dac0cd6a8b987a7c57162437fab8f807ce8aab\ + ccbcb3f448d402e4caa52f0641d93df28bfaf5e58a6f16f39adc87b5a1dd5398bb2bbcc7d994a0201b397c4a74\ + f97fca0b917ba0bd07b9ce9d25bb5feb2db2ede12841338d892fca759aafb7971202ee42d8f016c781218a37c3\ + bc2cd12d5917a00cf157abd9f8e9ca4f5b16b4359dfe287ef904d8db4c7df271a3b90126ef56586929a4a65813\ + f3467787c4829222d7fb9cf2e133be397a765f905e56ae783ac80f559db68cd58a90a22f1ab1af1d4dcd872ca6\ + 981a9ecca8670be84795798bfc4#1890", + 63, + "1.3380704116868237389e40", + "0x2.75285dfa208ffd00E+33#63", + Greater, + ); + // - cy != 0 second time in div_float_significands_general + test( + "5491.549122096322909336636529538856618128292880125595066488677776051102905046366315843918\ + 913993420423080685689765224843845532100106275652902608353545283642619588636389226823484210\ + 861629061239611056329749023362152227886065897973662117489519345928983306276603012226918628\ + 850786900692391091591113247385622873420889775685843449415444179626888676565806730164439066\ + 916153918074448979830160313236976037323911844599167437480714277238521850834771260598243342\ + 817521177189023", + "0x1573.8c93440537c5819a8b2239f718e330a799971b8d83971158cdd2e59617a3347f7b4fb69cbaf9e5ff87\ + 522a9c5cda06c869912d81fca8e9ef0dbe259efb7b9b0a54a58449a185302363331ad127c4e9256f242984dbc8\ + bcbea4216ff87b05bc4790144521cef5ba2b27261d31a7b650ec83e23fe89b1b2f569c96581f78da0e0d4554f3\ + 0f2ed4731ea3d9bfda8cb2254fa514c04681a9298a927fc2abb2b920ac830f6d5ceb4ccb7f627c3b8895ff1804\ + 8c7517748878fce7a0839b14beb12#1536", + "1.509673347429890062512836190652173917347254081193788057095565296339169922295435269039375\ + 472698941288863827397739888112708775552600102260052264376059462711206952889795049703596839\ + 232956098476826545419162632064629313103364676417718336633177039699753340705596727615974068\ + 628610723831801827765947524025118267152138672831243078933782856373566584766564765627600767\ + 096322262179300330204832084508935397859168676086969433875110241760537834330483926543135245\ + 217039771663537327658657093592229424143926522163858843150047672118222822507365351980019570\ + 622407757023485804508837072933740850465658604e-7", + "0x2.88665707e5f5634041c4267ef6487dd6141defd41a214073fe6520a7bdcf0c026eeac8a1a76a6f7c7e2c0\ + 73cf8d31cab2cfe226fc73bc3a686dc489877a18a6e4ecfc6970268300003802d27bf6e18d0623eb7b117d7342\ + 0a73839c03f41c3d09bb282d8dedfe2fb5675ee89cf010503f7f0b26eede0bb1c37b08c5a55d42499a3d9a9175\ + c05b5b8d873a476906f4a54340f4892951e2c8ef3a29f769e86cfab6965b4f110f218061a287f47ff1b3c217cc\ + df00c65594ce0048e5bac7ab91da9e0ecbd44b6c0440d575c7f294899ff21e307008ade7d2fba1c820083431d2\ + 3a0f94cf78f5937afde262a9f2aa86d36c391c0E-6#1935", + 189, + "36375744007.4390200041449619204768129898564194090547870908", + "0x87829ce07.70639d7017a741d4c383ed19081084c4464eff0#189", + Less, + ); + // - qh2 first time in div_float_significands_general + // - qh2 second time in div_float_significands_general + test( + "17592186044415.99999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999", + "0xfffffffffff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe#619", + "511.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999858969189385560189369588899908301051658131815921691396545986807150339147015462\ + 016914098983479659782731543057846003175884332840513803623318182318832820724717407320371823\ + 6294395745915856", + "0x1ff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000#1539", + 26, + "3.4359738e10", + "0x8.000000E+8#26", + Greater, + ); + // - u_size >= qqsize in div_float_significands_general + // - in cmp_helper + // - xs_len >= ys_len in cmp_helper + // - cmp == Equal && ys_len != 0 in cmp_helper + // - extra first time in cmp_helper + // - xs[k + ys_len] == bb in cmp_helper + // - xs[k + ys_len] < bb in cmp_helper + // - cmp != Equal || k == 0 in cmp_helper first time + // - cmp != Equal || bb == 0 in cmp_helper + test( + "5070602400912917605986812821504.000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000072282982868771681166004491412846722101397844122267684138688870467552820474559090102317\ + 447234871538375909335604136421707865093288809202542467085297095776399695369977155046440218\ + 72699461509694558652328992590065121835881232", + "0x40000000000000000000000000.000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffe#2230", + "0.031250000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000519145120156837503\ + 646385401176147001734918579024397648372858359187739423120395387040659114766108267370765089\ + 588804048262656404437892026790384389944710053355139410493357036837062723311890087295336535\ + 224886414974037589635945157614552911737025968561447428534517548726620712055254368601400677\ + 671297010734467257376219342434577391120913670811726006378408285341591896262197466018812208\ + 707818364202903001714252499366447760377357676976645014748597726032434627346717442135450023\ + 055574853304203092750885653943947474937587714924946440549453028916954237373614371956358356\ + 475429001114655812373726770920126725739237754419551706215855979284224297710219012046069209\ + 939692719820661068941772746188111229015697420074924121315943073728508778962547216389153434\ + 262911373438798885794691058258008791084816770299900324276184865853804713586768050489411191\ + 664317769877562965352444256815704956578248231483831995594631665817366125592817899193355951\ + 118530268969738737015352029171836561799730662727849622621896971327136981718066405555588128\ + 499837506069085441884105298697942808825809875065414280125486286978200226472477679074148608\ + 959361116404570999151605839083899731368423273690135641440237909114194036012915602847402345\ + 640200131464172673937558930023395763819989040966673763510370208058366269042896065620543694\ + 889060883071378600260819500918049255496885447711748266825241404608194240474286320016971013\ + 505365433166482975272851975538460641506474893740018353758689194264153921667729046743564069\ + 253579744", + "0x0.0800000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01fffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffffffc000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000#6892", + 36, + "1.62259276829e32", + "0x8.00000000E+26#36", + Less, + ); + // - xs_len < ys_len in cmp_helper + // - cmp == Equal && xs_len != 0 in cmp_helper + // - extra second time in cmp_helper + // - xs[xs_len] == bb in cmp_helper + // - xs[xs_len] < bb in cmp_helper + // - cmp != Equal || k == 0 in cmp_helper second time + // - cmp != Equal || !extra || ys[0] & 1 == 0 in cmp_helper + test( + "0.000488281249999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999963663982709420587425167733195\ + 304372898231735836009052811521034277852253692510619649191102380354831309742044158555819900\ + 182303288606739679841769892362177959648480394191365684359543454337339931688383011417980993\ + 719495486975941054744491093403718104080315380258293738327998799327152912644577698156976186\ + 55095367486514165923991079335821758615173478", + "0x0.001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000000000000000000000#2815", + "2.168404344971008868014905601739883422851562499999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 99999999999997e-19", + "0x3.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffcE-16#1232", + 36, + "2.2517998137e15", + "0x8.00000000E+12#36", + Less, + ); + // - !extra first time in cmp_helper + // - xs[k + ys_len] > bb in cmp_helper + test( + "187072209578355573530071658587684226515959365500928.0000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000001101803207893244326789943155\ + 018460305099242595345476423646015479873854823483513049621916060417380926502108264599637960\ + 009028188448912132272078404411433183433802785019851743390002334059444086579631362687278982\ + 092055516132867633211303823870165864587972287857634502648284831738260191440051776077031899\ + 598142362977237015956245760229588121897813474421614887403259665611637741356303541231148645\ + 802831472359942877820272387728004709359817918832294062785037876007514227493405888433177689\ + 680714430224698456312336396309714864041562196381794611694655680402546092635353483367808913\ + 752362293005799560093641139943406727218702402175348117018858577588516940143086501070121082\ + 790860175377027", + "0x800000000000000000000000000000000000000000.00000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000003ffffffff80000000000000000000000000000000000000000001fffffffffffffffffffffffffffff\ + 0000000000000000000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000\ + 000000000000000000000000000#3331", + "4.814824860968089632639944856462318296345254120538470488099846988916397094726562500000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000043039187809582461740\ + 237762479156173200033015160616639237674924575702164607097773158539128576763982320696088303\ + 832038609517565761168327844792993520257347193172468143718482303439757405926333196250133060\ + 288550223275967750822594171887174682861815132430042665799184768861200315909562005634908495\ + 040482237984846081838841677107482858326355102804446586581213177924458440804958481615550624\ + 777545362515887646344379566287174797564232997148384542907314841464505589746930096972150685\ + 525970118605412491959870803444763295822500525548365368442918966063445202883350639365511116\ + 639832781262353439062659724470167290957426899576854017375938862005470860735521697212635101\ + 685662094078329428036605435693999242602513069760981920534839908438815346198461935722540210\ + 326793005024577932413554325700374174982252819095920682430496242093539639719648496398673988\ + 294181130946788869550483877630340388986962249045975498873325109426508397715202174256327738\ + 115206226749346851411911082798138490772273613411588181424713572149102614119711767787285638\ + 524703608044386935250150211880470005994669065127142264588906081548898113686963839840837625\ + 878160925150811347647212869111896217042292003837889935947741223166647027572900535517651639\ + 207495691251723099461646574220946216274869671971300965751857652439720077434006455131311793\ + 590683604336422775710475248004038566299454724867611543407224462775327725726271022150051488\ + 962306463251821198471593641698105320214416610382784775624895123451428368367748899615073448\ + 540841180568439251922577807930504713787460146305777655304325240206357947725816143068424676\ + 946204398859120790721921646336338115096532038905903264996890888572731012019093458139272007\ + 836293712752099827742569952571629995231554586253215504385643489009213919397283063609836863\ + 267686636840153036916740518806971074030344720455273318700117606897827915624482324081001558\ + 580105852766963764590581776038099624170109326877344468594726954445140050830134037782433855\ + 587285682701452954803937838579540908490074176523981670683042482665018271091095010951223690\ + 5278182153271165591237853e-35", + "0x4.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000003fffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000007ffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000000\ + 0000000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00E-29#7548", + 94, + "3.8853377844514581418389238136e84", + "0x2.00000000000000000000000E+70#94", + Greater, + ); + // - cmp != Equal || ys_len == 0 in cmp_helper + // - cmp == Equal && k != 0 in cmp_helper first time + // - xs[k] > bb in cmp_helper + test( + "536870912.0", + "0x20000000.000000000000000000#100", + "618970019642690137449562112.000000000000000000000000413590306276513837413283570606", + "0x20000000000000000000000.000000000000000000007fffffffffffffff800000000#267", + 7, + "8.7e-19", + "0x1.00E-15#7", + Greater, + ); + // - xs[k] == bb in cmp_helper + test( + "5.82076609134674072265625e-11", + "0x4.0000000000000000000000000000000000000000000000000000000000E-9#234", + "8192.000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000073621518290228626754368\ + 661771449651176491350325096363488672030344706104289026372412636851722245811280577862962401\ + 765246827402220719444460351741455902885984901380506690583579618039994586998414375011572379\ + 779182346403549244684325279848137048396135313055840892271543868080199241336353523751067084\ + 487605126715192128136637640780333317069117147264850291384068338053712809423009097565764707\ + 945202720557662560964127631897773337487421543251587594809897712933202207298421785498016072\ + 254449856519027840276532392122510707729637176938094908140620695527942817590009777550509094\ + 454152645378859315289504747645957548190040101946887130819745338279179159631457317778420898\ + 470611527072781043747280163229876864141766629003055536247648501825111792890761407396390374\ + 874897179718966769929553634685717455680003107614184209129041106624130501684449541327017766\ + 6757753582718", + "0x2000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffffffffffe00000000000000000000000000000000000000000fffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc\ + #3924", + 15, + "7.1054e-15", + "0x2.0000E-12#15", + Greater, + ); + // - !extra second time in cmp_helper + // - xs[xs_len] > bb in cmp_helper + test( + "8388608.000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000684828866957428698438476408479242192022929376940887598\ + 259032840130007525904001877047531991911904326913906546098688715629243382676607047027876451\ + 719639473400356638537379034111884955325977768684942789942877048547849906527713086446752791\ + 858723447410673711365769970369878574737183686864932741554880327679842509372652502021311890\ + 709142794655721430723387345276067736929449744072002738257252158918229576617779883525921585\ + 596123442220897772976221689427398725884900122239984724340651124172908938910231534143853336\ + 754402", + "0x800000.00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000000000000007ffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000\ + 0000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000#4496", + "274877906944.0000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000060373564297453652118256309302784011108922184796264095\ + 964856067554168050454843683714804467407509910692607381159281320687596446281451430072818608\ + 057863867144256826337394425373143511933737397669081937627812007424941677129312470503091170\ + 911733627368176008701133101413396404615425187244748480697366133742242352202719895177017100\ + 690953740117147446309724130962650836546766701719441996132950568128342147049715911045228743\ + 620410093793320012089795191308289370965558751489023393660780664527210525039278006479120686\ + 667916583520393051061889574321018782852304715910223159623785353107527307680073164159574897\ + 425049765870945886337964515155856670447604028696651128918360721209741264488097948768144159\ + 7005421420614212549", + "0x4000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + #3940", + 17, + "0.0000305176", + "0x0.00020000#17", + Greater, + ); + // - rm == Nearest fourth time && shift == 1 && round_bit != 0 in div_float_significands_general + test( + "21778071482940061661655974875633165533184.00000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000038725919148493182\ + 728180306332863518475702191920487908654877629413444163480976859648626822342770145969080575\ + 425075544675393708363989923503155223180506533504920024360652705227860649920024820627696586\ + 039669982633650149716545149281467950945053120039758890080803998602993819265261127978876161\ + 185060505268781766584528622179744118464786493161582046377347178114187510333531866422621209\ + 846804228328353733454965094209076361330420294172109758000406375110313580574114285388890693\ + 305920075040658551907160730659163031529176823334039346417685325080367605674100555171634617\ + 234928876787779313622179077907389499960227122096343446066535190397344011264079006874008414\ + 382439268898793195608363864632580908988059168802931770976116933654316402639901396184475943\ + 729788724295947748963417392515678664943418616270097079670860835720917411673092090040881885\ + 21564006805419921875", + "0x4000000000000000000000000000000000.0000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffe00000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000#3999", + "10384593794440907712397259839635455.99999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999993016492510700454214505644339937412396352916507799605382898196356288572513\ + 255335843325740991172311658773153798524263030870893776870186113616631478977505034859608131\ + 351745273180872140851736147478994985324507666557307045519001087646931454316452554197971038\ + 325854489646439254746059314551440312981763083969256523175727926415817004690047870256478545\ + 703194379897622730743058132509274625798800775561678711877861189187434830350273902228109246\ + 439341677189967895547076747086150572427772646706738189826894090172821355170927596420947406\ + 00086516265683600055", + "0x20000003fffffffffffffffffffff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc#2748", + 63, + "2097151.9843750001164", + "0x1fffff.fc000000800#63", + Greater, + ); + // - cmp == Equal && k != 0 in cmp_helper second time + // - extra third time in cmp_helper + // - bb == 0 in cmp_helper + // - bb != 0 in cmp_helper + test( + "8191.999999999999999999999999999999605569547389494097294135717358606885163396782445488497\ + 614860534667968750000000000000000000000000000000000000000000000000000000009104419837890877\ + 372181354144852214156953700603760262322108787027839695294275046757", + "0x1fff.fffffffffffffffffffffffff800000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffff\ + fffffffffffffffffffffffffff#809", + "1.13686837721616029739379882812499995e-13", + "0x1.ffffffffffffffffffffffffffff8E-11#114", + 12, + "7.206e16", + "0x1.000E+14#12", + Less, + ); + // - !extra third time in cmp_helper + test( + "1220323748666959369108273.2342529296875", + "0x10269e20a74472df07b31.3bf8000000000000000000000000000#203", + "7627023429168496056926.707714", + "0x19d7636772071e31a5e.b52cc#93", + 3, + "1.6e2", + "0xa.0E+1#3", + Equal, + ); + // - inex == 0 in div_float_significands_general + test( + "37825066419214082102958195114240.0", + "0x1dd6b619c4a053851a451b28100.0#108", + "35597.514868846018999", + "0x8b0d.83ce71d761800#66", + 41, + "1.0625760410123e27", + "0x3.6ef13a9ad6E+22#41", + Equal, + ); + // - slice_test_zero in div_float_significands_general + test( + "1.7093142438003562047006422345280738002737985244107760125e-18", + "0x1.f88021f87c2effbffdfffffe1004000fbfdfffc00080000E-15#187", + "5.216412786622324189132254660659649298902e-23", + "0x3.f1003ffffffffffffc0000001fffffff8E-19#131", + 76, + "32768.0019530653953552246", + "0x8000.007fff000000000#76", + Equal, + ); + // - vsize >= n in div_float_significands_general + test( + "16383.875", + "0x3fff.e000000000000000000#88", + "73786413344884785152.0", + "0x3fffe000000000000.000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000#2354", + 1573, + "2.220446049250313080847263336181640625e-16", + "0x1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000E-13#1573", + Equal, + ); + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky == 0 in + // div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky == 0 && q0p[0] + // & Limb::power_of_2(shift) == 0 in div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky == 0 && inex < + // 0 in div_float_significands_general + test( + "3.552659469104e-15", + "0xf.fff00007f8E-13#41", + "4.84676140167789653245e-27", + "0x1.80000000000000000E-22#67", + 39, + "732996567124.0", + "0xaaaa000054.0#39", + Less, + ); + // - xs[k] < bb in cmp_helper + test( + "9444732965739290427392.000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000000000007", + "0x2000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000004#832", + "2.646977960169688559588507814623881131410598754882812500000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000556268464626800345772558179333101016054803995115582957638331854221801108\ + 703479548963570789753127755141009073606571985185530635329448182789571845492934678567064361\ + 332708567592792632774560421640775880919059592137166530735473758036612778924544586718232305\ + 427824501619198614662740023702411729616701208397136180761162254530729075026989491906995358\ + 575857015870579521868248894534215532446934638248802017349968861414212348741850124926530061\ + 137882705366115789406521732304520719972162648696165229524120554795461372143924212631388636\ + 174362506256920084558049677121644286500487074477020716131861235836886832672281595198230113\ + 567709366546419530594295018834136800596699897605463746431155006086897664830884143672193812\ + 44610974066e-23", + "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000\ + 000000000000000000000000E-19#3316", + 166, + "356811923176489970264571492362373784095686656.0", + "0x10000000000000000000000000000000000000.00000#166", + Less, + ); + // - u_size >= n << 1 in div_float_significands_general + test( + "128577.8764868580029756801212656877698983158936282661425976800226962111142207941648763580\ + 988345531602067112079580015968145327129866382559301038263207994838658330066205433266994831\ + 467312285027812918907079178962008936026981323406687199299541735562087171599287887802035024\ + 906243692028775515058236407279458918988174303955662670989299201833922393455224960273024665\ + 835516171507144476172664636956597658975023887814926279578799575403427330090956378386637388\ + 135713599495925645995132841117427501966959959182813336108896940311309853198603275957130349\ + 180224933883131003754623341245570205903946496613695364321801198058339260724701640865654036\ + 186860644657991116300768604961954024465425961935896721280763534922807739569795086883210509\ + 579889273277174558334960325483739866345331038726073720427318649387253214131422147544043776\ + 436460480773469181215055043763336182793567894315442629932401507848298532722652018799777250\ + 015693272603467557015010371191540543654044197350381607085047315086344620959308640376127551\ + 931466260812673044275557327198781497102634261681647151335962486321030934060949982367829468\ + 020749656366004839444427964357828448988474386543697497400049219456871357814121030924016175\ + 400479172517413298974822423000259842805397057515980600295281540360693708678122362364971796\ + 779616611372222055466670808323170951832437930119313259384578003290031387708344288805368337\ + 588807333974140623099430569336560667666750522945572113803323880761652974693642791189155133\ + 946965374070768843306018991682723627881006841722563064115628027286093354777874808024620535\ + 656673153645820545300742916103648617900434641706211663820400676448026510940215813847245690\ + 787061247080030343563700831660998005203777247693478841377389920284883123241874488805072645\ + 154615488002533716177437262647168075186850895612670638062910190731729666226316215350837312\ + 425251155930035494177805868591779327099854491269372890119982152035832492671125032181675364\ + 3983068068", + "0x1f641.e06171567f1fa1ce238d5b2d095d742087c3ea45ea9119d15b04ad4fd22debcddfe61686f85e93d4b\ + 77b8c6117bfe0d897686b10fb2562ff6e4d3b597d38561e37784dd68d9eefbce8d53e8394cca9a3e2dc4566d1c\ + 9dc04bea4f3078e8da6ef5461f25f3bde96a287773d9c8276b6c9374c221c96a70582c7441d2e07612a8c3dd03\ + e35a43d31a9e2671a63722177907b421a95e476796ca49409bffcc43124eb7f620ccf522ed0e21b1b97a662a4a\ + 5b35525007c94fe7415d10ce2fc897c6fb779527f47ad96624541900afc16557a726046c3df3e463a8d759e7c7\ + feef0e9670534db9d04b9d9ffe0466a19dfc275afe386b4af62dae0d9ed645db8afc44566a1737f4ce512e8a0d\ + 04938ce2572f4040cf0d01959d07f5d5df2d20e13e12234e2e5c841a48fd2fd2bb90b8def7c213d1e639884238\ + 3071b76c2f1dc091971382e76e3ca531afb15c870664c6e2640615bd8879fac86f33c0ebf5aab3d0d4b010c955\ + 1bef7718a83f66989073d65be312959c7c9937aaabe885475695d9dd1902651a5cd5f2d9ce22a6048f450b946f\ + 042d4f9a2d15ed6a44d25272dce6b428476ab4a30c7d0300bbdf8a8cbae64493c2f3d0ea96dbe0adc923d55fff\ + 656cc9d6b580f8d0add486b744493d4f9b350e37ff03e161abf2c2fd4893f126eff0a9b7b4f139f5368f126fc3\ + 52362625255424e59ab7a735c2af91f74edfe3d37697ce869643481c7dc622fd11f6214d54709f5388c25fb8e8\ + 690a34e8f4636c8a0ca5813927775ec20ea47fd7f0224e27ed9ebff6f101134d49ff8c6dd63ba49afa639a248b\ + 3f88841d75b76333f69d13436dc569ecefd0683730d63b9249361dc821d6ec48b599171f73d07d2d356ab1b0dc\ + 9dcc7bcd835d04ecb8ed41b2352145ab7136bd22c3c41e6a588a6760c1a914f23552091fad57262a23ad399e35\ + 51b0b228b6dfc03c6869855611a71ea2a1b5016273f7eed2871f29979b0d9ba2abb1b7e380f0cf87a751babe1e\ + 3d654913b9404d39fa3600a7242059cfcb69ccc95cab565fb53487bda573040c9a25205b93635c890bf9a60959\ + 13cffc5cdc250bd50af4696d0d8d39574875a1cdc764ff65ab0#6302", + "0.007532733962226776718609740913688407060156761888422741155537371074310369441516668932842\ + 179178987568947783738784004214845903753330652661093496965654876471036972958909346642328584\ + 201643545013628367738833205156107907841411376234839693950678432472453643018318413087069746\ + 828356026984992515666155286293579263416799907808093203442758385289281722930232963476563039\ + 602580878024432965067810300259817455445278112730792320635207665972350444684469938601305178\ + 752078424498914971701426156771409553942152089734535539717798744531200340412177539019002862\ + 118652155125909377605665570522313722924827432454878041302391573666440354096007833415288205\ + 656765947802568962289596330168089725205490246098452538786079372905549372857234270190725855\ + 849112728556822692019699490095850190529727602819872838218231626101062980913313718469209544\ + 852538752806279742668871810873531954763147922731900653003567552388163440686646259900626789\ + 714304577755153280330851920000826258260164717299978188447909834297914804211039024170906197\ + 475297083472857820673298493173502925728185522784910585353556804550521456290001513633298659\ + 714500938359772146658459237683211430724499182734233300374504698265281053478589566729317858\ + 790913972324776555314345736769665107752609864227197733165374999429056802940957299499067099\ + 921050502361595526540479399993958945176147715155608250079631789775409187220084344594176902\ + 12274124444296788210426683668353271294913726417315879718977231613999863580847401836166", + "0x0.01edaa4e04695976df280a5d8036e4043050607d25086f92fec3527973e673e50d6fe26cc2a98d36ffdcf\ + 64e7201043923f5dc51bce0937d27378352c24808ded1b4b5b3a72dc7bc6709f34a90a426ef3ea922afac190c2\ + 8474a8ca4b8fe2f5cbcaee63764658133bf4ee8c398d367693260118ca7e11a3cf7c60021ea9a5c44e5fd2b55c\ + 5399c4d2af416fb8495ab953e2fe7f8c37c09d378b6b7ef179c89219865c2e112567c3d0e9ef3604c1cd29671a\ + 220859d38f610b87914bda4727d5eb49b9b7067ccd5b9c9ef57e7e59956f66be8e839ab87e7420a7b6d992b60d\ + f12bfa9df09e2ca91b91841d01a991c5a473b0d0e55e6f4fda6266333923fec6358fbe2a3c3c1e0005c483a9eb\ + a2f70261785a9d095677b794e195f2ebc2ed814ff87150cc3b9449451981dac2554d3c18cf95ed5a563a7acd99\ + 5db1f27732d6f2451a3dab2f423f4b7723b8da4c3f303120fc532ea95736220939e15f80b7fd846c650cb099d8\ + a0ace134a39fe85ec810d523e13c25e0b719d1cd0977db7ff0a86625a3cb74ff315e7dc83f55296c934dc15f2d\ + 4b725cbaa31d95ba6f92d9bc74295829174293ceeb74daf101051b9c789701110c3a4116a550a47c228b82da67\ + 245a50e2f1d015ed256175a549250731cf4a90e7f114a6469e323d37552553f60f164d64a8a921b998c466ae6c\ + 631027958fb2f7fa98987fb56bdf12919d0fd1695c202c6d66beaf0d9868a53b16e283f1c970a6c9c90790af72\ + 75b90192f86671e698defb34b13fbcaaee1cdfc4beec69c2c46072b7a53ab26c823b403098b7657e3ca970d43d\ + 9954f49e9d5b94039a66b09f4#4752", + 1662, + "17069217.78090363703967642537830172830995997926929566889372077304847867142361027601405442\ + 286459362568854752643069912976321422774071641269497000825786673743566716666986122201673566\ + 954005548156596610807551133418147862857497307376377531996417888282239877181408646433952455\ + 449832546174770944921797138738845637802606582911913934926484494169960897434718640487978822\ + 397032739913032542773985132071836123040945096104343234766846881246804903855742298793870626\ + 77027180448793731547987433698769543012728726607028778", + "0x10474a1.c7e94cfe69b17ceb496b55c7673d812006e20b007a03948c3a4b4cfa0e6dbd76b73772e1f6a52b9\ + 30ce94a60672db80391db2eb227cad27128df746aae7c1ddb5368fdf97185927d712711fe190297ac2c169017f\ + ac401dc6bb041c5fa94ba4452b5b1c6a3d3f8d6d83892439b9e9525639739ce0fdfe4663acc923263563286994\ + f78a08edfcad551d9695555741c5301f15857227aeb725ecb09ed40468e21e6e6fe4f0f94b9e338a39e9665362\ + acb0922dc06bca5074ed2c965471e97402ed8367fe149485e0bb52e243f78#1662", + Less, + ); + // - rm == Nearest && round_bit != 0 && carry in div_float_significands_general + test( + "2.454546732648863276547885977493137821487607756249724782555774558593552627360857928230048\ + 942018665976138591785782565939256583959305212359451403757412054481726126552732229930964269\ + 470905492198653519153594970703124999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 995761114627674791277020932519574469505017610728137410250159407014720169738824650046673749\ + 059339474479527195633303962573451642912661719349979993453218111358455268175773121496346851\ + 580476856645369527796626919786850732045813122714395701160155300736782415936562761674226693\ + 028929972451809327089060718204876263534635026488050357020524924317959135992439056643999723\ + 656960561739673936265216544476386688997222734833105296938067057205929214479610015975275932\ + 718619380628277147130611593861916399934357066581330096178050556305086195135562253719174061\ + 496425118601354010153670564319137109364713055282273218494183562236985834389291157056469689\ + 9828846337814e-91", + "0x7.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000E-76#4517", + "0.015625000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000771048757510508716764719334683019132168263108153512725551350734409293871565\ + 903519457201213361797567020084883497703807999422859208123581192925346248118136084792628172\ + 988363113468168413497993606331107182531734570308778128025953654408272649725745457159283262\ + 0134958821588759455527143", + "0x0.0400000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffff\ + fffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000#3655", + 2337, + "1.570909908895272496990647025595608205752068963999823860835695717499873681510949074067231\ + 322891946224728698742900842201124213733955335910048898404743714868304720993748627155817132\ + 46137951500713825225830078125e-89", + "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000E-74#2337", + Greater, + ); +} + +#[test] +fn div_prec_fail() { + assert_panic!(Float::NAN.div_prec(Float::NAN, 0)); + assert_panic!(Float::NAN.div_prec_val_ref(&Float::NAN, 0)); + assert_panic!(Float::NAN.div_prec_ref_val(Float::NAN, 0)); + assert_panic!(Float::NAN.div_prec_ref_ref(&Float::NAN, 0)); + assert_panic!({ + let mut x = Float::NAN; + x.div_prec_assign(Float::NAN, 0) + }); + assert_panic!({ + let mut x = Float::NAN; + x.div_prec_assign_ref(&Float::NAN, 0) + }); +} + +#[test] +fn test_div_round() { + let test = |s, s_hex, t, t_hex, rm, out: &str, out_hex: &str, o_out| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + let y = parse_hex_string(t_hex); + assert_eq!(y.to_string(), t); + + let (quotient, o) = x.clone().div_round(y.clone(), rm); + assert!(quotient.is_valid()); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + assert_eq!(o, o_out); + + let (quotient_alt, o_alt) = x.clone().div_round_val_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let (quotient_alt, o_alt) = x.div_round_ref_val(y.clone(), rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let (quotient_alt, o_alt) = x.div_round_ref_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_round_assign(y.clone(), rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_round_assign_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = + rug_div_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + } + + let (quotient_alt, o_alt) = div_prec_round_naive( + x.clone(), + y.clone(), + max(x.significant_bits(), y.significant_bits()), + rm, + ); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + }; + test("NaN", "NaN", "NaN", "NaN", Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", Exact, "NaN", "NaN", Equal); + + test( + "NaN", "NaN", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, + ); + + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + Down, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + Up, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + Exact, + "NaN", + "NaN", + Equal, + ); + + test("NaN", "NaN", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); + + test("NaN", "NaN", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); + + test("NaN", "NaN", "1.0", "0x1.0#1", Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "1.0", "0x1.0#1", Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "1.0", "0x1.0#1", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "1.0", "0x1.0#1", Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "1.0", "0x1.0#1", Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "1.0", "0x1.0#1", Exact, "NaN", "NaN", Equal); + + test("NaN", "NaN", "-1.0", "-0x1.0#1", Floor, "NaN", "NaN", Equal); + test( + "NaN", "NaN", "-1.0", "-0x1.0#1", Ceiling, "NaN", "NaN", Equal, + ); + test("NaN", "NaN", "-1.0", "-0x1.0#1", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "-1.0", "-0x1.0#1", Up, "NaN", "NaN", Equal); + test( + "NaN", "NaN", "-1.0", "-0x1.0#1", Nearest, "NaN", "NaN", Equal, + ); + test("NaN", "NaN", "-1.0", "-0x1.0#1", Exact, "NaN", "NaN", Equal); + + test( + "Infinity", "Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, + ); + + test( + "Infinity", "Infinity", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, + ); + + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + Down, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + Up, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + Exact, + "NaN", + "NaN", + Equal, + ); + + test( + "Infinity", "Infinity", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal, + ); + + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", Exact, "Infinity", "Infinity", Equal, + ); + + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + Down, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + Up, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + Exact, + "NaN", + "NaN", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + Down, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + Up, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + Exact, + "NaN", + "NaN", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + Down, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + Up, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + Exact, + "NaN", + "NaN", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + Floor, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + Ceiling, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + Down, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + Up, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + Nearest, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + Exact, + "Infinity", + "Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + Floor, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + Ceiling, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + Down, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + Up, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + Nearest, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + Exact, + "Infinity", + "Infinity", + Equal, + ); + + test("0.0", "0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); + + test( + "0.0", "0x0.0", "Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", Down, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", Up, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal, + ); + + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + Down, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + Up, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test("0.0", "0x0.0", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); + + test("0.0", "0x0.0", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); + test( + "0.0", "0x0.0", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal, + ); + test("0.0", "0x0.0", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); + test( + "0.0", "0x0.0", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal, + ); + test("0.0", "0x0.0", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); + + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", Floor, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", Down, "0.0", "0x0.0", Equal, + ); + test("0.0", "0x0.0", "1.0", "0x1.0#1", Up, "0.0", "0x0.0", Equal); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", Nearest, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", Exact, "0.0", "0x0.0", Equal, + ); + + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", Ceiling, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", Down, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", Up, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", Nearest, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", Exact, "-0.0", "-0x0.0", Equal, + ); + + test("-0.0", "-0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); + + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", Floor, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", Ceiling, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", Down, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", Up, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", Nearest, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", Exact, "-0.0", "-0x0.0", Equal, + ); + + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + Floor, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + Ceiling, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + Down, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + Up, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + Nearest, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + Exact, + "0.0", + "0x0.0", + Equal, + ); + + test("-0.0", "-0x0.0", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); + test( + "-0.0", "-0x0.0", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal, + ); + test("-0.0", "-0x0.0", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); + test( + "-0.0", "-0x0.0", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal, + ); + test("-0.0", "-0x0.0", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); + + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal, + ); + test("-0.0", "-0x0.0", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal, + ); + + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", Ceiling, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", Down, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", Up, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", Nearest, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", Exact, "-0.0", "-0x0.0", Equal, + ); + + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Down, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Up, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Exact, "0.0", "0x0.0", Equal, + ); + + test( + "123.0", "0x7b.0#7", "NaN", "NaN", Floor, "NaN", "NaN", Equal, + ); + test( + "123.0", "0x7b.0#7", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, + ); + test("123.0", "0x7b.0#7", "NaN", "NaN", Down, "NaN", "NaN", Equal); + test("123.0", "0x7b.0#7", "NaN", "NaN", Up, "NaN", "NaN", Equal); + test( + "123.0", "0x7b.0#7", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, + ); + test( + "123.0", "0x7b.0#7", "NaN", "NaN", Exact, "NaN", "NaN", Equal, + ); + + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", Down, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", Up, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal, + ); + + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + Down, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + Up, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal, + ); + + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Floor, "123.0", "0x7b.0#7", Equal, + ); + test( + "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Ceiling, "123.0", "0x7b.0#7", Equal, + ); + test( + "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Down, "123.0", "0x7b.0#7", Equal, + ); + test( + "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Up, "123.0", "0x7b.0#7", Equal, + ); + test( + "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Nearest, "123.0", "0x7b.0#7", Equal, + ); + test( + "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Exact, "123.0", "0x7b.0#7", Equal, + ); + + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + Floor, + "-123.0", + "-0x7b.0#7", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + Ceiling, + "-123.0", + "-0x7b.0#7", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + Down, + "-123.0", + "-0x7b.0#7", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + Up, + "-123.0", + "-0x7b.0#7", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + Nearest, + "-123.0", + "-0x7b.0#7", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + Exact, + "-123.0", + "-0x7b.0#7", + Equal, + ); + + test( + "NaN", "NaN", "123.0", "0x7b.0#7", Floor, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "123.0", "0x7b.0#7", Ceiling, "NaN", "NaN", Equal, + ); + test("NaN", "NaN", "123.0", "0x7b.0#7", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "123.0", "0x7b.0#7", Up, "NaN", "NaN", Equal); + test( + "NaN", "NaN", "123.0", "0x7b.0#7", Nearest, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "123.0", "0x7b.0#7", Exact, "NaN", "NaN", Equal, + ); + + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", Exact, "Infinity", "Infinity", Equal, + ); + + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", Floor, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", Down, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", Up, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", Nearest, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", Exact, "0.0", "0x0.0", Equal, + ); + + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Floor, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Ceiling, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Down, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Up, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Nearest, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Exact, "-0.0", "-0x0.0", Equal, + ); + + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + Floor, + "0.0081", + "0x0.0210#7", + Less, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + Ceiling, + "0.0082", + "0x0.0218#7", + Greater, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + Down, + "0.0081", + "0x0.0210#7", + Less, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + Up, + "0.0082", + "0x0.0218#7", + Greater, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + Nearest, + "0.0082", + "0x0.0218#7", + Greater, + ); + + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + Floor, + "-0.0082", + "-0x0.0218#7", + Less, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + Ceiling, + "-0.0081", + "-0x0.0210#7", + Greater, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + Down, + "-0.0081", + "-0x0.0210#7", + Greater, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + Up, + "-0.0082", + "-0x0.0218#7", + Less, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + Nearest, + "-0.0082", + "-0x0.0218#7", + Less, + ); + + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", Floor, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", Ceiling, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", Down, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", Up, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", Nearest, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", Exact, "0.5", "0x0.8#1", Equal, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Floor, + "0.45015815807855303", + "0x0.733d90a6f99884#53", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Ceiling, + "0.45015815807855308", + "0x0.733d90a6f99888#53", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Down, + "0.45015815807855303", + "0x0.733d90a6f99884#53", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Up, + "0.45015815807855308", + "0x0.733d90a6f99888#53", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Nearest, + "0.45015815807855308", + "0x0.733d90a6f99888#53", + Greater, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Floor, + "-0.45015815807855308", + "-0x0.733d90a6f99888#53", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Ceiling, + "-0.45015815807855303", + "-0x0.733d90a6f99884#53", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Down, + "-0.45015815807855303", + "-0x0.733d90a6f99884#53", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Up, + "-0.45015815807855308", + "-0x0.733d90a6f99888#53", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Nearest, + "-0.45015815807855308", + "-0x0.733d90a6f99888#53", + Less, + ); + + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Floor, + "-0.45015815807855308", + "-0x0.733d90a6f99888#53", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Ceiling, + "-0.45015815807855303", + "-0x0.733d90a6f99884#53", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Down, + "-0.45015815807855303", + "-0x0.733d90a6f99884#53", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Up, + "-0.45015815807855308", + "-0x0.733d90a6f99888#53", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Nearest, + "-0.45015815807855308", + "-0x0.733d90a6f99888#53", + Less, + ); + + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Floor, + "0.45015815807855303", + "0x0.733d90a6f99884#53", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Ceiling, + "0.45015815807855308", + "0x0.733d90a6f99888#53", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Down, + "0.45015815807855303", + "0x0.733d90a6f99884#53", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Up, + "0.45015815807855308", + "0x0.733d90a6f99888#53", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Nearest, + "0.45015815807855308", + "0x0.733d90a6f99888#53", + Greater, + ); + + // - rm == Floor || rm == Down in div_float_significands_same_prec_lt_w + test( + "1.0", "0x1.0#2", "1.5", "0x1.8#2", Down, "0.5", "0x0.8#2", Less, + ); + // - rm == Ceiling || rm == Up in div_float_significands_same_prec_lt_w + test( + "1.0", "0x1.0#2", "1.5", "0x1.8#2", Up, "0.8", "0x0.c#2", Greater, + ); + + // - rm == Floor || rm == Down in div_float_significands_same_prec_w + test( + "1.0", + "0x1.0000000000000000#64", + "1.0000000000000000001", + "0x1.0000000000000002#64", + Down, + "0.99999999999999999989", + "0x0.fffffffffffffffe#64", + Less, + ); + // - rm == Ceiling || rm == Up in div_float_significands_same_prec_w + test( + "1.0", + "0x1.0000000000000000#64", + "1.0000000000000000001", + "0x1.0000000000000002#64", + Up, + "0.99999999999999999995", + "0x0.ffffffffffffffff#64", + Greater, + ); + + // - rm == Floor || rm == Down in div_float_significands_same_prec_gt_w_lt_2w + test( + "1.0", + "0x1.0000000000000000#65", + "1.00000000000000000005", + "0x1.0000000000000001#65", + Down, + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + Less, + ); + + // - rm == Ceiling || rm == Up in div_float_significands_same_prec_gt_w_lt_2w + // - (rm == Ceiling || rm == Up) && !overflow in div_float_significands_same_prec_gt_w_lt_2w + test( + "1.0", + "0x1.0000000000000000#65", + "1.00000000000000000005", + "0x1.0000000000000001#65", + Up, + "0.99999999999999999997", + "0x0.ffffffffffffffff8#65", + Greater, + ); + // - rm == Floor || rm == Down in div_float_significands_long_by_short + test( + "1.0", "0x1.0#1", "1.5", "0x1.8#2", Down, "0.5", "0x0.8#2", Less, + ); + // - rm == Ceiling || rm == Up in div_float_significands_long_by_short + // - (rm == Ceiling || rm == Up) && !overflow in div_float_significands_long_by_short + test( + "1.0", "0x1.0#1", "1.5", "0x1.8#2", Up, "0.8", "0x0.c#2", Greater, + ); + + // - rm == Floor || rm == Down || inex == 0 second time in div_float_significands_general + test( + "1.0", + "0x1.0#1", + "1.00000000000000000005", + "0x1.0000000000000001#65", + Down, + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + Less, + ); + // - (rm == Ceiling || rm == Up) && inex != 0 second time in div_float_significands_general + // - (rm == Up || rm == Ceiling) && (round_bit != 0 || sticky != 0) in + // div_float_significands_general + // - (rm == Up || rm == Ceiling) && (round_bit != 0 || sticky != 0) && !carry in + // div_float_significands_general + test( + "1.0", + "0x1.0#1", + "1.00000000000000000005", + "0x1.0000000000000001#65", + Up, + "0.99999999999999999997", + "0x0.ffffffffffffffff8#65", + Greater, + ); + // - rm == Down || rm == Floor first time in div_float_significands_general + test( + "9601551840755394477782155306615.400809036690567306698564563582349725588158197630704697078\ + 013417362910194409963799900311565761064675199511838067316509390850104862662213505749078521\ + 770377437536581181743514602025941917984526635269955727174740188131870994016855234632753317\ + 016792561638598147688756431699678956508985348347746587700412259161976828470219450879730366\ + 977549362693268375201952814531271011740413280015272635082852480719566333921902104982178638\ + 916033220231617933208782646056491566119203568817027316959068412927057431189073591651262563\ + 044927867605702941287180061603188567390575475013505450984801866920347023147022407388362970\ + 59088991236828388853335477454316615451511519", + "0x7930498878f5aafc3b8512a677.669b6bc886f9e61b8a5f2697dc5a3b5a2b2256b53dad0634eac355f6a0a5\ + 1716868ade4d034f6702fb8253c1f989a028a5714d4d362b3553fc85427910a52d3d77e4f39bbc7914d902c799\ + e58ce8c619156cf04fd16baabf3b0abeb8808eb23612b9dac1cebfc00ede036daaa891cfe4e827cb450c1dc08a\ + 8127d7ab7af3ad2ad37537634deffc4816e65732919e1337bdf6abce20a753777e12957b9282ddb2d803496313\ + dc5a1048926798d52bfa132da701a4550ee67ff9951f347ffc2fcd57993813839688be78495c10ef533661a217\ + c12a2f3327e0d96f3ee8d9b98f05db022bcbe3a69ce3b5009d3946e0ab02a8f9c18127f132344e97387cb60c19\ + 2f6949d3c05183b19bc196#2230", + "0.055494458197186880675630915676192867532090892470422627386324587939238035948781984969197\ + 293549419550977162311955781124943110956302191334821801709357381779895051695270613703928454\ + 324596584327643817343816609304133584205767499993731432854297161698269943482406592768874444\ + 537959922587924718339566077249075342435855861361805700477320039260219431275491192763683820\ + 335274971653357747385666948482136785955293678142161982025522843889154198503897563042426395\ + 128128925013857602497675148024154470366154782845358820106881972937537492453282371069714224\ + 342987087633028783648188309716648625167308459669051113846104707695985727291553732092985376\ + 828259777127224883258056131830095048084139109366273880047266946456087245977725112865710579\ + 525111935320391211042996099454878241904334424644681645423208503968089041208566140555448097\ + 852910157786980160921009881876094041863058139126904649967001982231878732430835123816538920\ + 677999964668461960985136485079991108378659476109039768366016053541284627738754596865400997\ + 112674267336505852768050602674774522669073467755292625683686148376948941511306559626232154\ + 752250188007464931234370449669484827725942224651581822979291904312419637250173763557353262\ + 213949126273235198961215664565140295983002285722717251104994492638175694612259962414559660\ + 670986455111669460799863783422503680534332809871688740315758114042751185650495859242221856\ + 676315059490112305738127164937772981750053994564437960009449100953381044642977719710987666\ + 446442147625231494914221140350124646594870978197268779196749153799654193158076220975432784\ + 285250458268961487489605062990550609833462756239703423977438296502233632161406744847227123\ + 129345837972247611423244017961911382138681216321381679915794615975763676728759826413970576\ + 860022980739678182223426387634227578298610034617798500806276338343012622846552838812662393\ + 624312342667652111927682534015047744310614980669350777266223429538479188836406048087315918\ + 309894499222120214872928367335411152843249721184424372084873571670196566303743654124450236\ + 183156500319414376380635601282651645722305689309629762280330704861001884908133936528480642\ + 756123234", + "0x0.0e34e28310efa672de91bbf3447b991e67d8318cdf0c4058e4c9c730c71dc5b4bf675e849e3ac19fa3e70\ + d9cbfb926620de7c9c66fc396364a70516bd66e253f5b318c8f82fabc4da09cab178fa55b2cd32603f085d4149\ + a70fb07eb0959a5a78a00603aae495e7a094d9ee04b63747d7a023fb4369e5bf83efc20d6dfe31bafee72256df\ + 1e39a8949cb554b519bb7b532f0ffb97b7fe5238cb68f0cfca74556fd7588422c7b383f4183a4193de48c69bae\ + 7faf54820ec3c71871cbb288daf37266ee4f1fd3e40e483ed25f601b87f9c4a92b8cec5ec0e8d7edbd4234fba3\ + 1a0a463a29b8f32d02f0d1f55195b2ec33db71548c7ccaf7e3a658ee71d308649653be586268e028c9f15d7788\ + cbbd9d825fadf58d6f13183242c54015f254a271b4c89cfc1d82fc8c6182b0d0c620d53cf81728d495822994c6\ + 63bb058d661f74be0ae8c8c10381afa72bc89a2a01da15a5f6d117b31e04e34a6e11e0aa8ad521b7a6117ce813\ + b8e9326335c30e14052e4aa58c9062245ce2b058e7ca1221aa19af3c21653dac76aa59bb843a7a0ad8c6e22992\ + 639766e47bfcc7de81f7a5a43e5faba0bd029002632b5d26d5a4303d9bbf4cf2664d57e50df98491d49ceb0f2f\ + a1db2579ec23c459066023beebebd800fc879d76d59a3d6d2949650b07ef7b31e752ca051f4f107c7ff4af3f56\ + 43eb287784ebcbcbefaa6a9496458e1b5afa0a74a27a47545d2f9091189f54f315a8bc904dedd3248f8cfbf32b\ + 19df9037d47bd021b075b70aaa2087c30b755c65f93508e4564f2d998430e8f68565d451de80e317a96c18493e\ + 662aa4f6ed98647d9051d9c993accc85820fe55a06d956025618ac1fbd020af906edd248ee088ee34f3ec8fc99\ + 1e9392efafd1acd495d65fe834644d939ef5fa91d984969c79257afb98f8d94a3551a1a4b533c182b0d198d8a9\ + 53e030b1532cd0e54117934099dd0b0027cd6058fb4190686ba78ded239aca8ac146e13f4c88052537903cb587\ + 95eae03289ef10a0dee81bb143567c686a600364a57829437fc75160f8660a0ac48daacd98471fb2c0c490cd90\ + 2cea0ea9aa3a814462dd78ab7d573f356b8c0ee7ac1f0c13819e3aeb5b2c8ea9f3a386bf90e5898fb38867db59\ + a9e8ae436df1ececb24a9e478c52dd17ad020f761aca8761acb63eb70ac73687a85f5fc45a10ab7873104f3489\ + 9df7961eaa91080cf7a#6892", + Down, + "173018210334417056237548035723683.1345550599384516271435235732043979258142510481520742047\ + 130035554740186809762152344382670192648388101752940643314971638619112864154957540114182619\ + 545209429070531797326950151630683621502942030447090067022672243119213825092070120260014287\ + 650642444490245716249659346973699250580875272571662195525373996192885786789722040970217252\ + 777370731438163261287964967884564981241085126934825161618449785175399006215884116607844104\ + 145207013638867416463540845880013358109313225877568519816660562362871960260263575794026214\ + 064890992255005169417359526730610750695374229149780488537259076167061214467019669082171678\ + 943457474819859479858903499033921570632357132665267027905891468527976638032942305102942045\ + 515459276591245938425195867555877301085883501327362346064575111830484879274114432829480494\ + 563831995727699779881566675298660138793679903428981563834668966551589617302484043712626362\ + 382798953692078892165133138064987411558895534104001531006894289080282050149571295909335181\ + 515141217224946465992765152346329894825749923118373449366824218493894112781616587290370204\ + 333887308955509161095001732854868950761797166686537700534752075294673973732109977084605381\ + 070618564835872903186336652176818456094869891043565959999476502149984797401333397104760957\ + 841309659194208245402430373249330458021584229695150780497429392832862209911691278370023807\ + 694413776673373810444117733945944078894301474904905817592608430260686560983085185519158848\ + 721775216278449134110149155717067705547304860141801798990958269542345867084594152084822858\ + 297268178452913654780535118518042943385992804181256593442747503443497424231886204147202265\ + 781726406780662404185957882728275703416562894011247737570346607390736902934407385727937750\ + 626919779463789669366072755563597481186609564844136728714713287282513301914775072382866982\ + 311110548050622515213045989841457194255484993918942830103968812317468779964982010673379443\ + 545157108484730053634532297455783144465121662023533540802524486197805471362616441499282252\ + 085672354541543506489067224840744574429825390924134914919433088957785876098287919516428588\ + 72328203", + "0x887cbfd350e72440510425951a3.2272334df26c980a06fd6f49c2120e08d01cbf40066a05dc52d2507fc8b\ + a1f7ad8adcfa81f54c2d43be83c3e9e1b2ae573ad5d2402f63f8286058a24ae0b84f54fb38a3e8763f3f65332c\ + 7370e069a38ad39fac27c8792cedd37255b83172e20e4dad5cd71f1373de167311ac9c40b97f28dc1deb8f917a\ + 4865473383f409e6cb0a10648e46d7a7b4e3635e29b5f290c2b02e89657217e160a8ead0781ee8d369a3f6e0e3\ + 373a660b0b7d660faa1b7d91b4cf5cd42a8bdff468e78bef9c7ea60bb9ae18146e44c1a152917815a88c662a0e\ + 8a69d92af1497fcb3af33505d54a549fda939b9762346d0a3acec60a952593d9b87d971a913e1a736e06692ed4\ + d0790ed0c9756fec1894ac0a4801a0f3ab65d90696cae94d0193ab36015ac78e049348dcf1a40ba53488aff432\ + 71652cc4085e19eb0dee362c9c49aeb3ae6922f6bc840455cda7693538989a16dcbcd4771ea096b89b7b6ec780\ + e4860380764f3f7268711f226e1c48f3f0ae8068a5d25f97b077ce5d6fb11aa921f2c3ba7cf501ff5bc4456ff0\ + a7d490f2e7130fd865897809259d125e6c3a3766e4a746daaf401e8c0be059068b0514c0324881a6f2ed930ee7\ + 2bad1215cb6436b3338bf75f190705e69ea7c9c4ebae6e62a0dce4ed74cbdd87135c82ac73fd0bb545e0f0950d\ + b386f309d2a674b58f9f446549a4ed3ae9a0de62e5e714f93368cb01396ec887f428e0d0df92bd1216c295f4e4\ + 0268e7f8acb642c1e0df9c960e503d5774a53e0042cc13863d67afe7b2e6a631449876b9b307dfb8d3d8d23331\ + a7f27c4e21b77c1e3fa05115cd74fc8ddf363caf1d632bde07c5905d7b004ae049a1eb0b8862b102bab6364457\ + f072e4eda8795c7bb923327eb1948231771fd0cb4ee5dc7380738f0b1c42d79fbd02c6e1825eadf29ecc297410\ + bb9dcb7b2dbfdbf605008a87de17f15bcdae1b2fb9bc31db5d05410224a6ce36fad367262fff7a125c662ed7c8\ + cd2e30f4106d2b7a2ab98d4736946788f9fe057e0b0b1a6f1eb99ca9d05ba0091da8bcf3c05efa1e034913764a\ + 6c0b52c6582c32ce658ca123e9d830d284a0b63dd2e432788616609ae6da4643f7d599c452e4c8b57689f717d1\ + 07559c9efcba9e48001571c49a50a5b8bd100a652034b8f6bca1fe99f6e5537912ce6892e13dd1ccae7d8f4f91\ + cb7902ec4aa0749ea#6892", + Less, + ); + // - rm == Up || rm == Ceiling first time in div_float_significands_general + // - rm == Up || rm == Ceiling && !carry in div_float_significands_general + test( + "9601551840755394477782155306615.400809036690567306698564563582349725588158197630704697078\ + 013417362910194409963799900311565761064675199511838067316509390850104862662213505749078521\ + 770377437536581181743514602025941917984526635269955727174740188131870994016855234632753317\ + 016792561638598147688756431699678956508985348347746587700412259161976828470219450879730366\ + 977549362693268375201952814531271011740413280015272635082852480719566333921902104982178638\ + 916033220231617933208782646056491566119203568817027316959068412927057431189073591651262563\ + 044927867605702941287180061603188567390575475013505450984801866920347023147022407388362970\ + 59088991236828388853335477454316615451511519", + "0x7930498878f5aafc3b8512a677.669b6bc886f9e61b8a5f2697dc5a3b5a2b2256b53dad0634eac355f6a0a5\ + 1716868ade4d034f6702fb8253c1f989a028a5714d4d362b3553fc85427910a52d3d77e4f39bbc7914d902c799\ + e58ce8c619156cf04fd16baabf3b0abeb8808eb23612b9dac1cebfc00ede036daaa891cfe4e827cb450c1dc08a\ + 8127d7ab7af3ad2ad37537634deffc4816e65732919e1337bdf6abce20a753777e12957b9282ddb2d803496313\ + dc5a1048926798d52bfa132da701a4550ee67ff9951f347ffc2fcd57993813839688be78495c10ef533661a217\ + c12a2f3327e0d96f3ee8d9b98f05db022bcbe3a69ce3b5009d3946e0ab02a8f9c18127f132344e97387cb60c19\ + 2f6949d3c05183b19bc196#2230", + "0.055494458197186880675630915676192867532090892470422627386324587939238035948781984969197\ + 293549419550977162311955781124943110956302191334821801709357381779895051695270613703928454\ + 324596584327643817343816609304133584205767499993731432854297161698269943482406592768874444\ + 537959922587924718339566077249075342435855861361805700477320039260219431275491192763683820\ + 335274971653357747385666948482136785955293678142161982025522843889154198503897563042426395\ + 128128925013857602497675148024154470366154782845358820106881972937537492453282371069714224\ + 342987087633028783648188309716648625167308459669051113846104707695985727291553732092985376\ + 828259777127224883258056131830095048084139109366273880047266946456087245977725112865710579\ + 525111935320391211042996099454878241904334424644681645423208503968089041208566140555448097\ + 852910157786980160921009881876094041863058139126904649967001982231878732430835123816538920\ + 677999964668461960985136485079991108378659476109039768366016053541284627738754596865400997\ + 112674267336505852768050602674774522669073467755292625683686148376948941511306559626232154\ + 752250188007464931234370449669484827725942224651581822979291904312419637250173763557353262\ + 213949126273235198961215664565140295983002285722717251104994492638175694612259962414559660\ + 670986455111669460799863783422503680534332809871688740315758114042751185650495859242221856\ + 676315059490112305738127164937772981750053994564437960009449100953381044642977719710987666\ + 446442147625231494914221140350124646594870978197268779196749153799654193158076220975432784\ + 285250458268961487489605062990550609833462756239703423977438296502233632161406744847227123\ + 129345837972247611423244017961911382138681216321381679915794615975763676728759826413970576\ + 860022980739678182223426387634227578298610034617798500806276338343012622846552838812662393\ + 624312342667652111927682534015047744310614980669350777266223429538479188836406048087315918\ + 309894499222120214872928367335411152843249721184424372084873571670196566303743654124450236\ + 183156500319414376380635601282651645722305689309629762280330704861001884908133936528480642\ + 756123234", + "0x0.0e34e28310efa672de91bbf3447b991e67d8318cdf0c4058e4c9c730c71dc5b4bf675e849e3ac19fa3e70\ + d9cbfb926620de7c9c66fc396364a70516bd66e253f5b318c8f82fabc4da09cab178fa55b2cd32603f085d4149\ + a70fb07eb0959a5a78a00603aae495e7a094d9ee04b63747d7a023fb4369e5bf83efc20d6dfe31bafee72256df\ + 1e39a8949cb554b519bb7b532f0ffb97b7fe5238cb68f0cfca74556fd7588422c7b383f4183a4193de48c69bae\ + 7faf54820ec3c71871cbb288daf37266ee4f1fd3e40e483ed25f601b87f9c4a92b8cec5ec0e8d7edbd4234fba3\ + 1a0a463a29b8f32d02f0d1f55195b2ec33db71548c7ccaf7e3a658ee71d308649653be586268e028c9f15d7788\ + cbbd9d825fadf58d6f13183242c54015f254a271b4c89cfc1d82fc8c6182b0d0c620d53cf81728d495822994c6\ + 63bb058d661f74be0ae8c8c10381afa72bc89a2a01da15a5f6d117b31e04e34a6e11e0aa8ad521b7a6117ce813\ + b8e9326335c30e14052e4aa58c9062245ce2b058e7ca1221aa19af3c21653dac76aa59bb843a7a0ad8c6e22992\ + 639766e47bfcc7de81f7a5a43e5faba0bd029002632b5d26d5a4303d9bbf4cf2664d57e50df98491d49ceb0f2f\ + a1db2579ec23c459066023beebebd800fc879d76d59a3d6d2949650b07ef7b31e752ca051f4f107c7ff4af3f56\ + 43eb287784ebcbcbefaa6a9496458e1b5afa0a74a27a47545d2f9091189f54f315a8bc904dedd3248f8cfbf32b\ + 19df9037d47bd021b075b70aaa2087c30b755c65f93508e4564f2d998430e8f68565d451de80e317a96c18493e\ + 662aa4f6ed98647d9051d9c993accc85820fe55a06d956025618ac1fbd020af906edd248ee088ee34f3ec8fc99\ + 1e9392efafd1acd495d65fe834644d939ef5fa91d984969c79257afb98f8d94a3551a1a4b533c182b0d198d8a9\ + 53e030b1532cd0e54117934099dd0b0027cd6058fb4190686ba78ded239aca8ac146e13f4c88052537903cb587\ + 95eae03289ef10a0dee81bb143567c686a600364a57829437fc75160f8660a0ac48daacd98471fb2c0c490cd90\ + 2cea0ea9aa3a814462dd78ab7d573f356b8c0ee7ac1f0c13819e3aeb5b2c8ea9f3a386bf90e5898fb38867db59\ + a9e8ae436df1ececb24a9e478c52dd17ad020f761aca8761acb63eb70ac73687a85f5fc45a10ab7873104f3489\ + 9df7961eaa91080cf7a#6892", + Up, + "173018210334417056237548035723683.1345550599384516271435235732043979258142510481520742047\ + 130035554740186809762152344382670192648388101752940643314971638619112864154957540114182619\ + 545209429070531797326950151630683621502942030447090067022672243119213825092070120260014287\ + 650642444490245716249659346973699250580875272571662195525373996192885786789722040970217252\ + 777370731438163261287964967884564981241085126934825161618449785175399006215884116607844104\ + 145207013638867416463540845880013358109313225877568519816660562362871960260263575794026214\ + 064890992255005169417359526730610750695374229149780488537259076167061214467019669082171678\ + 943457474819859479858903499033921570632357132665267027905891468527976638032942305102942045\ + 515459276591245938425195867555877301085883501327362346064575111830484879274114432829480494\ + 563831995727699779881566675298660138793679903428981563834668966551589617302484043712626362\ + 382798953692078892165133138064987411558895534104001531006894289080282050149571295909335181\ + 515141217224946465992765152346329894825749923118373449366824218493894112781616587290370204\ + 333887308955509161095001732854868950761797166686537700534752075294673973732109977084605381\ + 070618564835872903186336652176818456094869891043565959999476502149984797401333397104760957\ + 841309659194208245402430373249330458021584229695150780497429392832862209911691278370023807\ + 694413776673373810444117733945944078894301474904905817592608430260686560983085185519158848\ + 721775216278449134110149155717067705547304860141801798990958269542345867084594152084822858\ + 297268178452913654780535118518042943385992804181256593442747503443497424231886204147202265\ + 781726406780662404185957882728275703416562894011247737570346607390736902934407385727937750\ + 626919779463789669366072755563597481186609564844136728714713287282513301914775072382866982\ + 311110548050622515213045989841457194255484993918942830103968812317468779964982010673379443\ + 545157108484730053634532297455783144465121662023533540802524486197805471362616441499282252\ + 085672354541543506489067224840744574429825390924134914919433088957785876098287919516428588\ + 7232821", + "0x887cbfd350e72440510425951a3.2272334df26c980a06fd6f49c2120e08d01cbf40066a05dc52d2507fc8b\ + a1f7ad8adcfa81f54c2d43be83c3e9e1b2ae573ad5d2402f63f8286058a24ae0b84f54fb38a3e8763f3f65332c\ + 7370e069a38ad39fac27c8792cedd37255b83172e20e4dad5cd71f1373de167311ac9c40b97f28dc1deb8f917a\ + 4865473383f409e6cb0a10648e46d7a7b4e3635e29b5f290c2b02e89657217e160a8ead0781ee8d369a3f6e0e3\ + 373a660b0b7d660faa1b7d91b4cf5cd42a8bdff468e78bef9c7ea60bb9ae18146e44c1a152917815a88c662a0e\ + 8a69d92af1497fcb3af33505d54a549fda939b9762346d0a3acec60a952593d9b87d971a913e1a736e06692ed4\ + d0790ed0c9756fec1894ac0a4801a0f3ab65d90696cae94d0193ab36015ac78e049348dcf1a40ba53488aff432\ + 71652cc4085e19eb0dee362c9c49aeb3ae6922f6bc840455cda7693538989a16dcbcd4771ea096b89b7b6ec780\ + e4860380764f3f7268711f226e1c48f3f0ae8068a5d25f97b077ce5d6fb11aa921f2c3ba7cf501ff5bc4456ff0\ + a7d490f2e7130fd865897809259d125e6c3a3766e4a746daaf401e8c0be059068b0514c0324881a6f2ed930ee7\ + 2bad1215cb6436b3338bf75f190705e69ea7c9c4ebae6e62a0dce4ed74cbdd87135c82ac73fd0bb545e0f0950d\ + b386f309d2a674b58f9f446549a4ed3ae9a0de62e5e714f93368cb01396ec887f428e0d0df92bd1216c295f4e4\ + 0268e7f8acb642c1e0df9c960e503d5774a53e0042cc13863d67afe7b2e6a631449876b9b307dfb8d3d8d23331\ + a7f27c4e21b77c1e3fa05115cd74fc8ddf363caf1d632bde07c5905d7b004ae049a1eb0b8862b102bab6364457\ + f072e4eda8795c7bb923327eb1948231771fd0cb4ee5dc7380738f0b1c42d79fbd02c6e1825eadf29ecc297410\ + bb9dcb7b2dbfdbf605008a87de17f15bcdae1b2fb9bc31db5d05410224a6ce36fad367262fff7a125c662ed7c8\ + cd2e30f4106d2b7a2ab98d4736946788f9fe057e0b0b1a6f1eb99ca9d05ba0091da8bcf3c05efa1e034913764a\ + 6c0b52c6582c32ce658ca123e9d830d284a0b63dd2e432788616609ae6da4643f7d599c452e4c8b57689f717d1\ + 07559c9efcba9e48001571c49a50a5b8bd100a652034b8f6bca1fe99f6e5537912ce6892e13dd1ccae7d8f4f91\ + cb7902ec4aa0749eb#6892", + Greater, + ); + + // - in div_float_significands_same_prec_lt_w + // - increment_exp in div_float_significands_same_prec_lt_w + // - (q0 + 2) & (mask >> 1) <= 2 in div_float_significands_same_prec_lt_w + // - h == 0 && l < y in div_float_significands_same_prec_lt_w + // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_lt_w + test( + "1.0", "0x1.0#1", "1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal, + ); + // - !increment_exp in div_float_significands_same_prec_lt_w + // - (q0 + 2) & (mask >> 1) > 2 in div_float_significands_same_prec_lt_w + // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_lt_w + // - rm == Nearest in div_float_significands_same_prec_lt_w + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (quotient & shift_bit) != 0) in + // div_float_significands_same_prec_lt_w + test( + "1.0", "0x1.0#2", "1.5", "0x1.8#2", Nearest, "0.8", "0x0.c#2", Greater, + ); + // - h != 0 || l >= y in div_float_significands_same_prec_lt_w + test( + "1.5", "0x1.8#2", "1.0", "0x1.0#2", Nearest, "1.5", "0x1.8#2", Equal, + ); + // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (quotient & shift_bit) == 0)) in + // div_float_significands_same_prec_lt_w + test( + "1.0", "0x1.0#3", "1.2", "0x1.4#3", Nearest, "0.8", "0x0.c#3", Less, + ); + + // - in div_float_significands_same_prec_w + // - increment_exp in div_float_significands_same_prec_w + // - hi == 0 && lo < y in div_float_significands_same_prec_w + // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_w + test( + "1.0", + "0x1.0000000000000000#64", + "1.0", + "0x1.0000000000000000#64", + Nearest, + "1.0", + "0x1.0000000000000000#64", + Equal, + ); + // - !increment_exp in div_float_significands_same_prec_w + // - round_bit == 0 in div_float_significands_same_prec_w + // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_w + // - rm == Nearest in div_float_significands_same_prec_w + // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (quotient & 1) == 0)) in + // div_float_significands_same_prec_w + test( + "1.0", + "0x1.0000000000000000#64", + "1.0000000000000000001", + "0x1.0000000000000002#64", + Nearest, + "0.99999999999999999989", + "0x0.fffffffffffffffe#64", + Less, + ); + // - hi != 0 || lo >= y in div_float_significands_same_prec_w + test( + "1.0000000000000000001", + "0x1.0000000000000002#64", + "1.0", + "0x1.0000000000000000#64", + Nearest, + "1.0000000000000000001", + "0x1.0000000000000002#64", + Equal, + ); + // - rm == Nearest || round_bit != 0 && (sticky_bit != 0 || (quotient & 1) != 0) in + // div_float_significands_same_prec_w + test( + "1.0000000000000000002", + "0x1.0000000000000004#64", + "1.0000000000000000001", + "0x1.0000000000000002#64", + Nearest, + "1.0000000000000000001", + "0x1.0000000000000002#64", + Greater, + ); + // - round_bit != 0 in div_float_significands_same_prec_w + test( + "3.1790543009742223972e-11", + "0x2.2f43e0add6ebd01cE-9#64", + "7770090901.6225594673", + "0x1cf222d95.9f600ea8#64", + Nearest, + "4.0913991113158902183e-21", + "0x1.35232b1b3b9aeabeE-17#64", + Greater, + ); + + // - in div_float_significands_same_prec_gt_w_lt_2w + // - increment_exp in div_float_significands_same_prec_gt_w_lt_2w + // - in div_float_2_approx + // - y_1 != Limb::MAX in div_float_2_approx + // - r_1 == 0 in div_float_2_approx + // - (q_0.wrapping_add(21)) & (mask >> 1) <= 21 in div_float_significands_same_prec_gt_w_lt_2w + // - s_2 == 0 && s_1 <= y_1 && (s_1 != y_1 || s_0 < y_0) in + // div_float_significands_same_prec_gt_w_lt_2w + // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_gt_w_lt_2w + test( + "1.0", + "0x1.0000000000000000#65", + "1.0", + "0x1.0000000000000000#65", + Nearest, + "1.0", + "0x1.0000000000000000#65", + Equal, + ); + // - !increment_exp in div_float_significands_same_prec_gt_w_lt_2w + // - s_2 > 0 || s_1 > y_1 || (s_1 == y_1 && s_0 >= y_0) in + // div_float_significands_same_prec_gt_w_lt_2w + // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_gt_w_lt_2w + // - rm == Nearest in div_float_significands_same_prec_gt_w_lt_2w + // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0)) in + // div_float_significands_same_prec_gt_w_lt_2w + test( + "1.0", + "0x1.0000000000000000#65", + "1.00000000000000000005", + "0x1.0000000000000001#65", + Nearest, + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + Less, + ); + // - r_1 != 0 in div_float_2_approx + test( + "1.0", + "0x1.0000000000000000#65", + "1.00000000000000000011", + "0x1.0000000000000002#65", + Nearest, + "0.99999999999999999989", + "0x0.fffffffffffffffe0#65", + Less, + ); + // - (q_0.wrapping_add(21)) & (mask >> 1) > 21 in div_float_significands_same_prec_gt_w_lt_2w + test( + "1.0", + "0x1.0000000000000000#65", + "1.00000000000000000016", + "0x1.0000000000000003#65", + Nearest, + "0.99999999999999999984", + "0x0.fffffffffffffffd0#65", + Less, + ); + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow + // in div_float_significands_same_prec_gt_w_lt_2w + test( + "1.00000000000000000011", + "0x1.0000000000000002#65", + "1.00000000000000000005", + "0x1.0000000000000001#65", + Nearest, + "1.00000000000000000005", + "0x1.0000000000000001#65", + Greater, + ); + // - y_1 == Limb::MAX in div_float_2_approx + test( + "5.29395592276605355108231857701752e-23", + "0x4.00000007e000fffffff0000000E-19#107", + "255.999999999999999999999947060441", + "0xff.ffffffffffffffffffc000000#107", + Nearest, + "2.06795153233048966839153112178982e-25", + "0x4.00000007e000fffffff1000000E-21#107", + Less, + ); + + // - in div_float_significands_long_by_short + // - diff >= 0 in div_float_significands_long_by_short + // - in limbs_div_limb_to_out_mod_with_fraction + // - d.get_highest_bit() in limbs_div_limb_to_out_mod_with_fraction + // - sticky_bit != 0 || diff >= 0 || i >= abs_diff in div_float_significands_long_by_short + // - tmp[ys_len] == 0 in div_float_significands_long_by_short + // - tmp[ys_len] == 0 && shift != 0 in div_float_significands_long_by_short + // - round_bit != 0 || sticky_bit != 0 in div_float_significands_long_by_short + // - rm == Nearest in div_float_significands_long_by_short + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (ys[0] & shift_bit) != 0) in + // div_float_significands_long_by_short + // - rm == Nearest && !overflow in div_float_significands_long_by_short + test( + "1.0", "0x1.0#1", "1.5", "0x1.8#2", Nearest, "0.8", "0x0.c#2", Greater, + ); + // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (ys[0] & shift_bit) == 0)) in + // div_float_significands_long_by_short + test( + "1.0", "0x1.0#1", "1.2", "0x1.4#3", Nearest, "0.8", "0x0.c#3", Less, + ); + // - tmp[ys_len] != 0 in div_float_significands_long_by_short + // - tmp[ys_len] != 0 && shift != 0 in div_float_significands_long_by_short + test( + "1.5", "0x1.8#2", "1.2", "0x1.4#3", Nearest, "1.2", "0x1.4#3", Greater, + ); + // - round_bit == 0 && sticky_bit == 0 in div_float_significands_long_by_short + test( + "1.5", "0x1.8#2", "1.5", "0x1.8#3", Nearest, "1.0", "0x1.0#3", Equal, + ); + // - tmp[ys_len] == 0 && shift == 0 in div_float_significands_long_by_short + // - c >= u - c in div_float_significands_long_by_short + test( + "1539239.2465826685826", + "0x177ca7.3f200ab152a#64", + "0.00009", + "0x0.0006#3", + Nearest, + "16812597210.673628039", + "0x3ea1bdfda.ac72e31c#64", + Greater, + ); + // - c < u - c in div_float_significands_long_by_short + // - round_bit == 0 in div_float_significands_long_by_short + test( + "1.7088961703394199635e-73", + "0x4.d4baa70e83509ad8E-61#64", + "1.7359472818744e-34", + "0xe.6bf39991dcE-29#42", + Nearest, + "9.844170892645193631e-40", + "0x5.5c13c13c6d059800E-33#64", + Less, + ); + // - tmp[ys_len] != 0 && shift == 0 in div_float_significands_long_by_short + test( + "4.874956728709606165589080471392071684004548689044982493122e-71", + "0x5.6220e3ededa8be921ace72bbb95a16164a2f0abd57c49f18E-59#192", + "1.5092483e-10", + "0xa.5f190E-9#22", + Nearest, + "3.230056172437141772802006354545046772521759341614858124236e-61", + "0x8.4e07636cdfc96e412c1de0a522f40a5f092091c1a3aa159E-51#192", + Less, + ); + + test( + "6.88621557179233820703925296804982406452e-28", + "0x3.68ee78c4dbb67961d201a40495749728E-23#127", + "0.1418399214207466117788070203268", + "0x0.244f9effc4f1edfd85dfab3008#99", + Nearest, + "4.85492060543760755133907256608679730501e-27", + "0x1.80a57d020f8b7083401eec627a6787ccE-22#127", + Greater, + ); + + // - in div_float_significands_general + // - up[u_size - 1] == vp[vsize - 1] in div_float_significands_general + // - k == 0 || l == 0 in div_float_significands_general + // - up[k] == vp[l] && l != 0 in div_float_significands_general + // - q0size < MPFR_DIV_THRESHOLD || vsize < MPFR_DIV_THRESHOLD in div_float_significands_general + // - rm != Nearest || shift != 0 second time in div_float_significands_general + // - qqsize > u_size in div_float_significands_general + // - qqsize > u_size && !extra_bit in div_float_significands_general + // - vsize >= qsize in div_float_significands_general + // - in limbs_div_helper + // - ds_len == 2 in limbs_div_helper + // - qsize == q0size in div_float_significands_general + // - vsize <= qsize in div_float_significands_general + // - rm == Nearest second time in div_float_significands_general + // - !goto_truncate_check_qh && !goto_sub_1_ulp && !goto_sub_1_ulp && !goto_sub_2_ulp in + // div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) in div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit == 0 in + // div_float_significands_general + test( + "1.0", + "0x1.0#1", + "1.00000000000000000005", + "0x1.0000000000000001#65", + Nearest, + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + Less, + ); + // - up[u_size - 1] != vp[vsize - 1] in div_float_significands_general + test( + "1.0", + "0x1.0#1", + "1.00000000000000000011", + "0x1.0000000000000002#65", + Nearest, + "0.99999999999999999989", + "0x0.fffffffffffffffe0#65", + Less, + ); + // - qqsize > u_size && extra_bit in div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 in + // div_float_significands_general + // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 && !carry + // first time in div_float_significands_general + test( + "1.5", + "0x1.8#2", + "1.00000000000000000005", + "0x1.0000000000000001#65", + Nearest, + "1.49999999999999999995", + "0x1.7fffffffffffffff#65", + Greater, + ); + // - ds_len > 1 in limbs_div_helper + test( + "12077.327578390390934514", + "0x2f2d.53dc2d699afa78b8#75", + "4.90332775049862782951473377323022738896770775e-11", + "0x3.5e9a4013acb1890afeca956568e5bffe30edE-9#146", + Nearest, + "246308796656764.923124719743308898445103382544", + "0xe0043c546c7c.ec51e6d16d3ab81c76ba65494#146", + Less, + ); + // - vsize < qsize in div_float_significands_general + test( + "1917511442.613985761391508315964935868035476119276770671", + "0x724ae712.9d2e2bbd62dd31f140b2b9b664635f251b18c0#180", + "3.352896739388742667241376e25", + "0x1.bbc08f6e851e14a094c4E+21#79", + Nearest, + "5.718969570663133425280005234972069245666491961744252885e-17", + "0x4.1ef6b3c1725013efb2a8179983b542a97b0131f39a938E-14#180", + Greater, + ); + // - rm == Nearest && shift == 0 second time in div_float_significands_general + // - qsize != q0size in div_float_significands_general + test( + "1.490328e-27", + "0x7.61370E-23#20", + "2.89262335038499315783322011549431655756e-75", + "0x1.4ef161f7b7fc2c6cb4464f827b58b972E-62#128", + Nearest, + "5.15216656741446303242577558053691246166e47", + "0x5.a3f1d299f6f20544fbba161403f075f8E+39#128", + Less, + ); + // - rm == Floor || rm == Down || (round_bit == 0 && sticky == 0) in + // div_float_significands_general + test( + "2.38418579101562499999949513e-7", + "0x3.fffffffffffffffffc0000E-6#87", + "2113929216.0", + "0x7e000000.000000000#66", + Nearest, + "1.12784561231761934265233937e-16", + "0x8.208208208208208200000E-14#87", + Equal, + ); + // - k != 0 && l != 0 in div_float_significands_general + // - up[k] != vp[l] first time in div_float_significands_general + // - up[k] != vp[l] second time in div_float_significands_general + test( + "65535.99999999999999994", + "0xffff.fffffffffffffc#70", + "22835963083295358096932575511189670382427701248.00000000000000022202", + "0x3fffffffffffffffffffffffff8000007000000.0000000000000fff8#219", + Nearest, + "2.869859254937225361249367321235116718339077564583058127288930659162e-42", + "0x3.fffffffffffffffff000000007fffff8ffffffffffe000001c00008E-35#219", + Greater, + ); + // - up[k] == vp[l] first time in div_float_significands_general + test( + "1.91561942608236107295e53", + "0x2.0000000000000000E+44#66", + "43556142965880123323311949751266331066368.000061035156249999998", + "0x8000000000000000000000000000000000.0003fffffffffffff8#205", + Nearest, + "4398046511103.99999999999999999999999999999999383702417796084544", + "0x3ffffffffff.ffffffffffffffffffffffffffe00000000000004#205", + Less, + ); + // - up[k] == vp[l] && l == 0 second time in div_float_significands_general + test( + "255.99999999813735485076904", + "0xff.fffffff800000000000#82", + "1.35525271559701978119405335351978053e-20", + "0x3.ffffffffe0000000000000000000E-17#114", + Nearest, + "18889465931478580854784.0", + "0x4000000000000000000.0000000000#114", + Equal, + ); + // - q0size >= MPFR_DIV_THRESHOLD && vsize >= MPFR_DIV_THRESHOLD in + // div_float_significands_general + // - u_size < n << 1 in div_float_significands_general + // - vsize < n in div_float_significands_general + // - in limbs_float_div_high + // - len >= MPFR_DIVHIGH_TAB.len() in limbs_float_div_high + // - k != 0 in limbs_float_div_high + // - q_high != 0 in limbs_float_div_high + // - carry == 0 in limbs_float_div_high + // - carry != 0 in limbs_float_div_high + // - len < MPFR_DIVHIGH_TAB.len() in limbs_float_div_high + // - k == 0 in limbs_float_div_high + // - len > 2 in limbs_float_div_high + // - qh == 1 in div_float_significands_general + // - in round_helper_2 + // - err0 > 0 in round_helper_2 + // - err0 > prec && prec < err in round_helper_2 + // - s != Limb::WIDTH in round_helper_2 + // - n != 0 && tmp != 0 && tmp != mask in round_helper_2 + // - round_helper_2 in div_float_significands_general + // - rm == Nearest first time in div_float_significands_general + // - rm == Nearest && shift != 0 first time in div_float_significands_general + // - rm == Nearest && round_bit == 0 in div_float_significands_general + test( + "914122363545.7300954288539961362078521335512160921125366724096502748846903936195389924148\ + 154757063704910629280973433563521737016298541257057972452261335506117124831272191707877190\ + 2119190824963185068512647039440777212199983388696", + "0xd4d5f05299.bae788b5e312f78f55ac79e4ca82e12494296afdb40ba21e0c21a4b3915ba2e217c389f8c9fd\ + 22042f5ed70da20cfb9f1ee797b1433e077a2d34b1ae5781f975eebbcb21a32ee0c5afa5e59f8f382fe0c754a4\ + a3fb57fa4d668#754", + "99775868891207693182758620905617766484977359141657322302733467080906379945858675686059451\ + 2527853476231275058799551652072546.7114971760702609364731573674336745185834760605451122614\ + 680178551142556046183482705875960001033145321970465204907865385015751310573750415565593472\ + 515573584122133946534420508845514863685042630834456885627933663697385547769664847990486584\ + 336882273751721721644989648370590667737234950547668737865047573751482757356022197920174371\ + 088074314780588737501583713833755004374512024407585163195094394292034507503368814534990168\ + 9912721166210129145585", + "0x1826427338bc8ee8c907c3ce5e6a2a793f6ba67df6e738f22dc8aee7eb1838ddc4290e49186e61bdbedb847\ + d19c5d8c4bf88c62.b624adce6b0a3564827e04608c1aec0c8b10390491e15df75402c1788241935e791ebd5f4\ + 25d73042c03e3bad5f0d11257d8bcdab6c8bae677785865be19fa4f42690ddb02174b09bb2c1c9ce6cf3dc2d80\ + 9f0b0b79c42ae70f14ec682ac3850e91ee3b6ef02555e18758417024bf2e8801a759e710b3ac91f28b15277ff4\ + f6380b7ba380aa56c032ce8db2107bfd99a9c789098467f2b27a7b3e1bb6a9e7804ef8a26a3baea51e9a8da4d5\ + 02af09995fd6ced97b00#1859", + Nearest, + "9.161757985214429764992710266551647359057325985892606639113002591596898046569993924851132\ + 469009506849046579846739625666450546615840413944516736833310444241924771226669449467280905\ + 847180462085951493210441487438964221396785151298524525494386941673630175499486324164244756\ + 513337189186243674611400515366863669226025015162200893355049656715514081022497216123358900\ + 204159965608607573130556648229035236124949246847315199932950877590362471534070708393335471\ + 028355306786566135185894674384218244976402468322690432705335567965983855642753641740432604\ + 3437409476409135277542e-112", + "0x8.d032a1c09c5a822250facc4d03dcbdde26d4f5fe102c1e08a4f87e413b615d798e202484a718a7e4ee277\ + 3677de7769fc7d817e371393d771d3460b42f92e9ba23196df3ebdff7cdda4294aecfb6c43776a893a979bdc8c\ + cac166e11d435edd52a1481ecb355a6595fcd794f14478ca886b31b8422e8bc9fdcdbc2261e6c6dfdfea3875fd\ + d48e82b6f89b37437a8064efc36e3671100bf00cb530951d17bbaefe545249991b357ff0fbc5a593a69916e391\ + e844f20336e8635a395cbda774a8ed440b65ccac5a4a48827068b6780bdeecccb424ecbcea085547d055a670dd\ + a2ce7fd1bc8ccfff3fcE-93#1859", + Less, + ); + // - q_high == 0 in limbs_float_div_high + test( + "3.667390117738159207950705349477719105571949429980976394812181671883945054829509256768693\ + 428777428660656941387302685172371854480204626447190818847235223777196475037450938977825246\ + 002439873468885558547110470430228085143851019175355894923610792842932340338852051239754427\ + 095026930245556704615627992643819617817074019244527799280182728405175259498139200084973400\ + 185025632529817381341736837108765891093445296142846875524815723636775475593320258020981988\ + 641285509338653295726597545939874976233498010217572353942629414771256828458910867296816672\ + 522543163090158525097032013393556880192772591230747507060825723928635133507431423165786715\ + 278150157159772706487785219042905040143153742214007713387626849311191420055238664770362170\ + 343983987545766271318010394410223132309343859005046365250499465556871672911799580499791909\ + 295656508202340485571517780009270726548788594036564495463224892161734462687808109262481368\ + 096969794376769660230615691331025217443348007977074560288273633401967130359649250852147512\ + 141074330343117535301250887203664127461249846867757356639750473042390297739319749311431157\ + 14372183907772936544329974943881256368038028229439176970805917055179180439477409e-9", + "0xf.c0568c485e0b826908a56a1e9eed605a795d47bbb3b22b86ff364a5aa967860d79fa907ffa4b598c74ca2\ + 768fd610cc65e72d1328231f74c2896a372707f3fffd4713cd781c36ddc8c429a53c9de0a260ab39221aa6723f\ + 639d4f0a18f42a39ce148ec18caa8292a2404e421cb5af96a525988ace64d3b66492e8b29b9f1982af075eac7f\ + a4c4f560684706f9c92a1babe3a7cedd233045842df3c534b90481e818908a787ba694e61d3bd3d93a45651240\ + a1926f3b818e8c51165d9c7c186dd99b0afededda17332acec6e4419ca2c498ecac62e9670b8cc359ac4ce5abb\ + e6a858a9ad732af4717655c73ab36f06357d16912bd759fba2c774b33607e2ee49fbf3328842b34b1649846034\ + e601a686e91c2040c578ab8676f4c413bc62718b75fe591900b6f10a6ee20a73c59ab3be30fb9a154c1a50b4b5\ + d60d7a76de24b93f804302eb4d625df61cf824be4c93189bd500d72fe88443b2e506a11e3b57403b447b8602ef\ + 45e256c2e9cbfbc69697901d340ae418d96a38e3f87b38c8ee8b168c15df448ce29060725fff6438c91fd406bf\ + 6cf95e07431942e379a50250441c4ed69a634f4e155cb67d47b7b4b285388f957b3809dcfb73606173ca9a64c8\ + 9b5ee06f42fc1ee8c752cf947957f346aac01a1e21759f8267f58d36b22e7bd14E-8#3843", + "3187923845432148642442057154569059.126715487792372839803386914179538752693826970283207166\ + 811288798839227319311871148502823407877176659352907588186871022894787193533982873662011253\ + 290757573915501169313819926148549862448642272469031186766746849160076154409190019980289710\ + 170792165652792217117270925812431819493193080694795589891807146039351866024622601910524654\ + 975993653145125921373829181052606711648254654081125875153947355721451359688668050452670532\ + 460418624462017975144128989503732730892234660879379487543472739334395798501406522301770530\ + 084261662015482020833397653047706275744771695945820139179975325296925632712346348118093097\ + 953095934511815810581175318735500116787412839224213098543182657584610954902591533740060963\ + 289805212670558460977431314581393471573332429725647583364688986461335610003995668212280028\ + 807977055980202986273442266172236653427698776974320204115552560417196660880213932819325142\ + 548937684752935846670101028764484218237392844524558383599287530029421881169570993841163993\ + 843829902198804691520255195056203676272889080365643704609455722537324606271987166289767672\ + 190663805227886932691226996255254535007618551610966568052639325048438160780381909128343538\ + 211967934803057176881479842550254050201767779261994751352264395465646274141983125281497566\ + 020553366225193569060382295548356106219949376044134821789228041804290511458952966410365196\ + 222090758059421770693182158103609003570428820956594490269060711518240230638460085565864341\ + 256289190220580928350048868798606128912317218138793827337661513849296003850300428079774414\ + 62431384255329048179650372924700507846477189871631671161154559755984562472291", + "0x9d2d417f3ca9f32fea99c6482363.20706d1bf7058f4c6275f668a177cd076adccb2fda12b6ed78a3b56bb5\ + 9dfb518b8b3c05c40c48fd5544dac5cf4c4b5097a348e21623af642ca54df95b1dc69591e2bdc1e3f296461a0e\ + 73545f0b1a728f095b34af1c14dc3ff040878852b81a047198ec51c9f7dcfffac0ad33017fdb2f0c43edcff12d\ + ef18336029b6f47a305e278cb4eda766445530f250be179818a2d241b5afebc21b194dbd62400042f887100725\ + 62fb877debcff302fcc5b1162c1450e14478eb4e96906a31d6843172390e3cd69b3c0f474a72a62036579c22fe\ + 1d1ad35fc2be49e475a1be85f30bec6d387e595070d17b17f5b5a6f400fde641d92abee13055777fe7f6b647fc\ + 7850f8002fadb99332ceffb5439a87b2ac7f223b73750c6b42112fffe8b992da6c3fbc5274503b1bba48602753\ + 174ba7260f73f3fa02c00fc495aad0f85c84c966f0a98fa7d85cca68b07d58e6292617f3b67fd0aafc0dc0c457\ + 806b811f2698bea27de70e9ea3de0e898978b9670aa90750e88ac855daaf830c9dedb5d22968f2b01302edc889\ + ce03e2af4ec2e339258ace8efa81eeb76b273039929d7289eadfb0bae898fd0257e0f1db349eba610dfb56e3d3\ + 1520f08012e02d96edfbf9a1a05ad01f682c49e1cf1e0f2b1131943ffe95afd8c6454deffe4bfdbf15fe656e18\ + 13690a6dbdca197ec4c2b29ac61a6ca074a2866ff9f55184ed344bb45b2e44eca9945a21cd78ccdd427dff1dab\ + 1d449dccc0aa07e37c89bb61c7fc94ce0edd5fb60b7e2d8034decb7a0e2bba4c1159236fd7f800450c1516e64c\ + bb2206f385ee11aba1c6993b2d50b2437bc23cc47f6b85d72fdd7348a5e321b5c960e8e23830fc93c4393938b8\ + 98c2f16e8452c9e81ce5aa01460fb108dca1e371c53a1e72ad6ad0cb80bd5bf0ace476ab08fe8#5329", + Nearest, + "1.150400792350488243006374252439239370084430198894097883408930056885079539097149903334801\ + 351771948494649335504249165228317854781872084884358035626531528587565616792440130659246789\ + 547068913471358728267587391921067763401960740658485999234360708658257354709138940743401019\ + 478517400580149085993404074744575447821383623813098520973947955049547026992303475579228215\ + 436224676800479021561310494945776720018368502752527214637080415175177143606297950367602304\ + 149567232708944245857383841379350871799797376084773487408407355299732079377175164962925047\ + 553551234005632068337070468847266947004802579875459884664958168707856865409967591741263680\ + 896819771668163339399940221050773763868745744855354003266260565352234279551485173590767169\ + 460117377689246074482291141675360319952860733464727767370984256722737643645180588444886771\ + 648355387388454942423178644791668457452750839522592156007162798991977390140623536578544490\ + 057707937271642210929120388296125663413585185722459999909564986042307052548228205977082023\ + 238981495642981332360042089388607651948288196055583153394379775735995327224157713864077477\ + 321557707540034099204193983589868016082915953745995091314702115380175700364741814725184464\ + 602065018950641261052531311066491931955988616475785792821351515116629573461861957542243077\ + 532642867446492701937719979200426618485741197144774966492676324343483017759514367363624027\ + 675809506514516688590348320872084123672477458766804242125009602995249222201904595636534318\ + 096670348004414769559053243712710972449074750435098780379781902955436286126620063025099547\ + 80435463720060716005725004637793753168276780047800093479230422676842555945701e-42", + "0x1.9a7a0a4405b5655db3032989d155cf7a58151a06aacabc4789fac720edfb0e835fe88bc9af3cc179149fe\ + 616753cd76b4c7d9c17f2f47389f4e0007572679dad2a5316ede08c14af0283577f171d41d795d4ff13631def2\ + 630089c6f215d7b5b8948c52ff97a4a1d9f1eb6d67b60e55478c40ffd2a7cd9684f43637e46ce3ce3e33085654\ + 9165c4a377c6ab1dbb9c9b40ece8c47d94ddd1318dd2e5e57388b2e8ef80705d97c3db61d805c43cf7ff7a9a1e\ + 41ded3ff033e68dc751b34ffd9cf2eae50cb7e7875b9d8f24116927cd9f609a65c71e840166cf535bbf110404d\ + bc493350b17705c0e23a9091d61f544117f70c6c6387dfb9a1dcc2f513cfbebc4cdd4b7d94c9fc57ceebebe3a2\ + e7d85b9b488b5571ef7b7c8621b770d99c67f9a19252ec5f9be4b129c7755b4a8585b97ea68e60e390c0b5c2b2\ + 7b5fc3a47825c136e3b2517a6a7490ae84cf61659a9b819bfe59d45f7254dd48e028c7b694a9b9b427e60358fd\ + 52afbeed855580a61e351d523d4ffaabfc7ca00e9a5b40128e9fd8b2998c189e95abc1857ff9ddf1dac904a2de\ + dfce45cbc4f1ffac50c26ec7e1135aa9ca96f6d3ac8cb3a6620a3aecb003d246eade4cf0e6394df920dfba899f\ + 44ed41072e121f0402f19fc4c43c348467a07566df372a7b1af45354f2b4c7f94d52f355813e84c1a95202029c\ + 0056a974e856e7c42fd6463561d1b5e02ed6a7e0ea0ca50887bd1047f4abd068ea61e2095abdad6a0cbaf91846\ + a340717aa624d6c6ba02f5d3e835ff06c742f1343479ec9a9b184eaca8e7c8be7eaf4fa322afc13f046a4a2e5f\ + 4e84c723c68079991a080ac6939780e172640d568c2bc3452c14317358ee8d27a18af7c9bf2de8bea3e5b8b113\ + d8e61b810d6103e805c2a8f85b9b88f8c9129b924ba95521aa83a066991bea980c8be16f1df53E-35#5329", + Less, + ); + // - qh != 1 in div_float_significands_general + test( + "5.001744775175450910666028825162941035057223155811961434576858983758571141018459147239961\ + 203150588371507863692097065128597336587126035820647361489875366021800666979434518756504925\ + 080057234368614339602900137940067888065298554658519361482160014564328827389146902718969285\ + 655774560873251528749737416878097111467317878479458938947793439179987668446365650646689222\ + 368834166803110702160567896615568919058064520266761717855703906871630752776256537972706691\ + 492064397304429453321564568279795029252524047182880248127317544801138445700458013706547493\ + 607273723210196209139384085476634511414334117395068648152693457778920460359930382343697178\ + 078573995749595631668772420417704996567074590195305455833132484492282116574194971013126880\ + 3791636230633361526548302742414616516594455084620537903358416e-16", + "0x2.40a97302ee75111e17146bc65c8925811ce517da511093e155a5f8d319eaddbeb4108f1636a175bfa8c49\ + 995045d6820b2f007a269091d024c939d8b02f4910a81e4eb38a836a327a5c12207dbd4d7a81228e55fec96493\ + eb7d51704a03ee77c5caca6616fdc0b6cbe90c676923de6ef8bf3f132b9e5e0dcbae8db3a41502b6d35629f01c\ + 0834af3506639efdaa9dba6adf35a24b53b04e032ba7f9821a7155eb04aa7d235436bb878e13e2f265b7a183bd\ + 7830bf484c2c6b19e1df88120105ab6ceb5f940ee7e82d4a6da4e67b7532f20750db350a532138117c02fd3f63\ + 1e917747a8217c0e647adfae38491beacae6be9197fecb6a639604eba9f3e2a0e1250124f9d994d6ae0f8077c0\ + ad1f961f00f0513cb1b3b92f03fd2e19ce799415d8c26352d23ab730bff342c3d10823b5d476e3a74e5e3a1265\ + 3a2e81ad38c5d7f45687a8E-13#2587", + "1.142392802815468388118014752111991104436260746248041498551240097570984474280784266879307\ + 592064853042631818930172030116326290909317377878988867978348974337550025356060840134215623\ + 183687852648862683292152461337367387727519703906836027722282460995072637442171724001503892\ + 471336699233392710738717656085295397789876649817787754823752786376233371866685422498954888\ + 388883747226256845650864591251580129661172288008506642506027201072159168710566406994425528\ + 61698637621752755004821872e-17", + "0xd.2bbf98dfde60cfd72ff373085dca4697e7a8a2b1b6d379d3c49be918a519d5508c59f210662104e5d0b4b\ + bb4e9f09afcccb3c1655f91f2a86657e3f1315aa4e7c857d68f4d7b989d2a2f5d56a205e85ef7d6d2e9325e0fe\ + eded2158374d99d513a6d203143a26cfd251731f49e63a0e342dec62e52287bd673124d763a94038f4529cffd3\ + 3599c97c0e19c589ce5603d9c26a084d360b9e7decaa7dda44ce1c27bb7c21adcb23b90d069b0a9b53b9d66094\ + d817f0420227841d34052ed2bd52e148923f8E-15#1571", + Nearest, + "43.78305573046740119713641861874642911154821650761595780287653003720809501996262685108891\ + 851641972710141298162279987632328545443442081070773994511258975201978303856309243168868354\ + 195798884971190979692045031917290903217918542303368118161338247041052975773351929884789101\ + 115569142934332750399827875003719838494787907290778719530315375971295186399328856671813524\ + 401338950750393532748258170809380674066918530153006391759208813425198252649570832466781508\ + 205219467712658427254330831981130973959961174357861904110964877950640959685965415405374479\ + 749995867814629083616329619361738872731212580413192190669870683344353586783786957328312637\ + 080558281918488071596583884466679323108552730394571978915258990045025562636051246193761815\ + 9037942507064891051161378037771712070204599081778501997567779", + "0x2b.c87657214d897953f5e5edbb169c290285fbd11622c9cf401ba99ad9f03da7ffc778df1db0d888d67c18\ + 379efc8b4b36ed8cbb67da04b5b4cfdabc5f751b0a6fc68b1e3a2a16a62c4160ce4d10e00ae47020ca5d3867a7\ + 2213145fe6456480971ef0cb9716c6136384fe41721979e86d1ea1bdc104f2967865add528a1367b01cc449a48\ + 5786a74209d8e4c5e216fa7ae2dc897fd4926b55eacde3321f7c41bf2875c24933c8eecc7a8a26f738fd6d666b\ + 678ec93b48bab7b34c5392d3ca76949dab6958fa5caaf70927d3e8b40d050bb607bc1b4fe656506e1b3e468e87\ + 8b257c21e926286697a97538d3230475cd54415b8154351e72363b4b7509061108fc6ac5db47219368f3ca4011\ + 5309edd7318a116c2b62a34277bfdc8a1faf656b14b6a046087cfc5dd238cd94fe91967fb6dfc52f8afa5699df\ + e2970ca40fb03c71d7d668#2587", + Greater, + ); + // - n != 0 && tmp == 0 in round_helper_2 + // - s != Limb::WIDTH first time in round_helper_2 + test( + "0.029226865494398284939675773661541675546326681033634876986774906885711036844605915426240\ + 340310096249605517533494947862661721742262334681480455706389428160732541825851560446846541\ + 984468705310228771603694136853587701004882713625816107989162498255925332620064155091399923\ + 221735997586925448254801064429910518067322424203818026901404115120552071966804127784634236\ + 948421057038304255272147630765439482924461011451862112889343084859504616664030668233890526\ + 750016895266382189553251377266295422223247821668554701473442441938933867323625955488726630\ + 366895993417469747854898337776376811834753617592182604418498468334055402941851068346511528\ + 636460609896950078921029074658151972716364203699936241491820871671807186599907001653993018\ + 871354678119954470481273332266267481346670395677171242596948926022697465301700258863974068\ + 74909984356479995046141060221761701111762543380195142151878885588292130260647185", + "0x0.077b696f76893b930df354ab0e34b0df1508ee4503f673e22fa3b41867c5e4ffbc43b589d4cb4a00c472e\ + 4046ccc9dd4a2b88b59dde14b46da030dc5a0f825fc1d9ff0213e8b046b1cd79785dd554b78e98759eae454c23\ + 4fddf6ee7ae174bfc7c1ed096e905b41ce6b18511a9bfc9cfbc43c536393410fe83a634f402b0f18a446a3af90\ + 9a4079394959da6918bd9094c5b587839c67f902f1f107259257f4ae96549552e41dbe7dbaddda5b9d8fa2b2bd\ + d01ba920c27d6ff6e44bd8f0ef230d60508f693680e1d769f920949bd35768a7ff10fa62210e3caf84f93cdccb\ + a5238b5e4be804a1422da22abe509c758d0cf44f202896613342ffd0fa93939f0c9bcd4de899fb72b286773da8\ + fe9cbfbd51894ec97176996bf2b6a61ac27a5f524cd408e8bca09d7cefc329a98f17616d4b48652d0a3f14cc49\ + a9bbe75a69ae9167aaa9d1951d446e95bb89c1760a549ff81f7b1d8ee454047a7d3c3e244dc499d97b256eca33\ + 3d43933df1e0a046136e10#2940", + "13755175900776476.03444104347769161034491994978466673515315430911280875941467408228432201\ + 072744723926732268661761372710838010056791678637659254162102142124198282086034764229922487\ + 783612307113854432839997318024745178344073274492535681224805316900558167281372795857375154\ + 556654904332875058382920111153919687941523340022403648029377155100560618075774147398400587\ + 446623619383420263487024723715538921428293815054071349051549046244877203394687286110159347\ + 188168590858399073350484327515115795260226962105536078430163098017753828590552884767518140\ + 1985404905771271934", + "0x30de427563881c.08d120d36075efcee88657ce81cdcaedf45cd89aeca352b6e32212d20771ea31a54387b4\ + 8b1eb8738ae1d31c6213ddc44bdc809d5f5b278e3449ebd13c9ab8d89ec9f0a2d87e7233cbd5128caca14e0c42\ + 61e5c9ed6444b50d0cce082673e3c80b1a7102c8fc7520036bc3c6900dbcff7cecdf27ac4022bd4095736dba93\ + f47ec8ed66154c32a8eb07e14079a264e1e3370aebbfeacf3a1bbfe7aa657d9911acc70d626a35a29d86c84029\ + f97428f7cd8a3965838abf5dba9a9943b07c0ad2541156ef8e2aca1afd50c7dc55f986c835b95647701f744563\ + d15716174f2ac444#1845", + Nearest, + "2.124790384741531086324618396766014790807036315098759090708607153306148130187657728807205\ + 824808003798574987452867827342282934278081982848900135498971286785256137258700150407383617\ + 040883394430575593960834148265479663570529896251340120502267014474793716347382140126837773\ + 997589830815187190064041312015350810806968062929485379465521677249527992330225473850965169\ + 559943150658138282772411679190301632849325467452565481282203194749783450341076382685241552\ + 308193411477432500590221491760317417660435511777399629140824293491122934845121250984106958\ + 267596015361360781611025519421253206751640221273565905944385402975185311734694681019948131\ + 664198303801199498616289444621169851399879692298796098215712787193626312888177618196672010\ + 550069281366814417353104090880010484400040465312380510548737422916103805415326232623198929\ + 338433641210905412883566788706510371353536321443505713555119784985687877546815e-18", + "0x2.73209f5170c5b9aaeb5a7e9e79e1dba6ba9eb57b8701701f4d2be387a03993b7e53f907a48a9029ff962b\ + 4eb20e6ade6771889642b19b1985ec76b2b24fb517b27eb86681dab6bc7d5a5a203545d850396986ce5c6f9542\ + 50b478a0dd27222c6c45900f2d06dad9d7f78a79b9978e3ce203479c5dce6dde3affc40e370565c038007c8bc1\ + ef1fdf0f6398b88721063c52e5eb2c4b5ba1f10d93710d5abe8aab35f5bc5cdf7031f7765dd4f9d4065b1b5b86\ + 4ccd6665b73715bdfe783fae157cdc8a78e9d053cae011d4dddf28499ac3809e290ca0a221e38d2a6dd8d01980\ + c64da2f6836e0815e2ae3feb8a0d765808afcbdf6df10cf661eaf6c064ec8023cad01912101fb7e8b732b555b4\ + a053a203ab5ec17c24af5694ed7db4f67c3c76a7f360512bc9a2018d2860111211238048d21af3d79aa0904474\ + 22c0d9c9883b2f3769a5fe3faeaf8bab1409329c376b70c7b54fe1393115359c5a7ff43560bc0e2548a02ffb68\ + 184585e5023a6fb507d0E-15#2940", + Less, + ); + // - rm == Nearest && round_bit != 0 in div_float_significands_general + // - rm == Nearest && round_bit != 0 && !carry in div_float_significands_general + test( + "767950667289861979450190915916317600206727962344150969868.8721759327117422801652737665276\ + 756590281054535919141164571740727630029753345081284383462360338144272865435150624843971065\ + 632159910277471560574746205336214689461444841220676837587640834824669960199738043592424986\ + 826697488691269778053087892841924823231361961899657984958299046295741089107389167540777341\ + 1137893901502419455", + "0x1f51c7714fd0115fee394111538cd8cc2697edb4db72ae0c.df46ec035af05536a25a7e2694997099b2577e\ + a12f12bb82f781cda7cd6a148cc07ab56a0bac9e90b8590cb04b95fcb27209c3c8704cb6940c7fb857c1688d50\ + 6042d2fb6c58e0600ed4d86a5af398f029ebf3521880629fcd23f2bfd5f9447e8dee8310647fde5e5f5e2a0a18\ + 7cdc4e8c046be95417ea73f5d4a1962ebecd092b613af810#1250", + "51.02908107282950125513822733633990251324880237789609831750259919822628384179764854139813\ + 664310170076349095466129599769105832710389521373306698912599298264052853550294941822816681\ + 854313580668986120583821047373123379751687690065811623363578923931243167028825931454472450\ + 957582633858214796963862561877157489833071159740156527107422181977546544800568916528954101\ + 973657910504690951238460938847030239913388867386095316629182004723248011669496406544341717\ + 280330814897033602543594303927085904297027340275835376721330553519116838042737905906942433\ + 571685773257005175176741271374980135164819404821829229591371965448368260666618720681201228\ + 891015077648242337901859343084853665103006650868094946302847691177013349096688713595881758\ + 621480481903927608236275982505035171940737146501502983532266096788435188627685343250723400\ + 305856753098249087347464717300786991295322157886984156263306019163631926110778355478267431\ + 730519001037411438399866507817311259465545754442998333101310788661554118860610086857525556\ + 649462275011688416941329847092728287810185063940836755796270353054485056127471728114260616\ + 408519706805571508639638485588089026599284155688404740772260862102363921554760355678529807\ + 545078380365647104062842403550988330511500383389703046031841433893387481098301402534069795\ + 658730174573583314000979689827444189825731612831252242895060479770394162281620141901978731\ + 360879005964038152579829187416621515149774573766217606037565254139422563209723838864340747\ + 448492223949482531030183865551640816462517599780266133382572731428229045787209942986614817\ + 192016158247860998226332096129248802519217902568127470669978186812858044800325333178140023\ + 387809105983555698845635663825858578549915679237164757880235025950739307212793316009945989\ + 415835829851915334677834156538103555704104713171341701847682567317855121655570126973890951\ + 3929068030854124664713500553256", + "0x33.0771db70bc3cc1bbfd03fee9ecfaaa1f99d76266a08107a7c922f5787496298c9bd6b5bfa13889bc0bb1\ + 0f2e280f2673b20cb2191b3f747978b1483ed5890a8f1e9b4ef8665dff89aeff7e04820fcb58e76837b70b36b4\ + 946ecf9ebe8fba5e510503f922f8e39500946e3ba0fd0a28c3a881101047c77426f1160e2835ecd5cdfc3c85d7\ + 78adf772e0b5f5d5913cda27866ff4a68981bb0b247705d4a7a13e0cf5df9064561c207ad89d6bd10ed4faf445\ + ceca3d7f86bbdcd652aaf5c547a0071a203dca41ee8ec829aff439308e3dd8d470556949fb583c7ed1bd6c7854\ + bb629c27db1c0caa83e77e13d983d022e1865331aa5f67de9bca45976769e471933efa23a7d5fe8e03b8eed13a\ + 3920db5d0f4052f811bcd1955c217ad35a8b75478eb3f2e077ecc810af955e23d57d0b957bf2104261c9f16ba6\ + a16f119f6d83e2b35b1a28b6fc7a029bcec426c495328cba2082e252a65c7267a9a83365475cc6b4672f77d481\ + 40ec81e987a366445896d2ae795891105da2f608b56dca4a3e4166c6a0338423e51de87dcbfe3717817893141c\ + 8b61f1377d82379374f5ad121cb9e04cf51776a20bc8b0ccaa51862efa4f51d52333818ee4877c039261bcd8dc\ + 152db0a6119f3724603b4aaf9994eaf197d5adbcb723d1dc6ebdd8d2cfd37952c4128f3b79556ea134b7193dcf\ + afdc170fa41bf528ba4deac3f3d79d4407db9fd076aaca428efe74dbbc1bc7fad8b57ab1a693330f49aab1ddcc\ + f26bdc853360568f201c8fea22c816ae67afff2668debe399f951e72144cfa93dea4f18d1ee734ed2bf350fed9\ + d126c9b660f6b27ba5e13f15a8be20837e071c52d7588c0a856a969903419e91d47e7011235886759942c1c0e1\ + 896e1621b2d23df869694531248722482999c8600632a5ab2279907e29cb3c38994bfbe299cb368a72ef45ecaa\ + b9646b4f1e2f37f24aa954535b1ba220c8e91dfb8f81e56dc45ec4cb3181511fa5b1854096fb3f03f2aa052eb1\ + 5111548f398b2a0ffeecd95498fef2bd7f25126507f63bd3803c3a9d1aff24563f7f0baf024307e9c75#6074", + Nearest, + "15049274867282653916783425765897232338286237097021544510.63055696334657926692700975852105\ + 429908991325181901560777184807721684871576977542689434849596891044659963521044055457283641\ + 367304991334226236960366994118987961185804836414630696056584495778598754606288486597978327\ + 332370268104018122071463105903604569912790301532188931593783003198530412792016208481406460\ + 177569545284296438034561831086095957417103960718034276692579871391678752019863068680376188\ + 441084892942908419595289335759422879108451807263984856494740183999962091220506257869533189\ + 151879060260534882539324732360323776701789524149049182180697710000483323367419829770508959\ + 886298233038628402259126153349007515813222501560286947664943532169644098519601985837510236\ + 220345218089637472842801890223279059211522040546360301667071765816467200381174390649332596\ + 068474921226001156721359127966627401319343668619013146928630922944213877247277873392955093\ + 504639915667110210542526572018725370251615388653789028473354868425502960351888594917293217\ + 742712292964655900915998259809033409553076012583762301750508167459913039705278696038307105\ + 198133823120123667996810391703122691279674638629684591634520584549627376733588876153831722\ + 199369165407756045645488517825617351416613370266999295351664343537186993481753740631996768\ + 537474147168714208012012313452364629821090786481898210882140832386720226088895885830143936\ + 713915428453413001094302216345205004980013281182978168058085052927135299009881922560519790\ + 174395754146412113876346433499785448301225654969985504964945207336686282652994022882395571\ + 250336046288750244045997533647713495015654011612857222465008362940468446125031495141758501\ + 398188163302138089732641998828146315905675208381266922364102647252983963785718802006725178\ + 667871858412814374481149992996719213942377608145948042933317201168269095689729130915320304\ + 63030844892155532105060912300876", + "0x9d1f2bb817353ba61ad13135f94f65b1b52180f58a183e.a16c2e5fd6b05e4155475ec873e35d0f193a9765\ + ef45957a4681138fd789135172e7be4efd1b67c60d22430a10832c82a4dc4a53156de6d8638ce6ffe089ebf880\ + f2e1c68c90b576b5dc0b99085865ed663bd642b7743ff5500d4c6d3e2cf4977af36122c98fc49e81ee87b80d89\ + 3fe81fa07bdc5986b40bdb0bf7e6bfde432dcedd2063308cf685bfee2b964ff62d434434a9518683156e532f30\ + 11f2ac8f98a75178cd412e00f2261a83f952b6a94bb97c280cb51f16f85891ddd7fe6ad8030e20422da11497e5\ + efe8d88db4f96479fd0b16f3703dca8946d944979a3454bb8155d8dbdd3a765584148771967d02f798d157b6a1\ + 59e10461bc83d8ec9e55b557614c35d75b391c0c9d04aefe96cab5078bd3a13d5618ca219640c68919f1fefea9\ + a3d1e47a3fcbc8c19de2210708fd96fed608648d183fd4c1177d803a49f7d276f940aeef6feaffded75f8e03ce\ + 33df996eeb67ac6c0bec62d821bfce22d9a30baa6f7f4963eb4eaa91707ba1b12fd6f3e04f75cfea4dc39c6488\ + d72e86c36ba981115f42300b97a7caa427023f16c4f66213cf0c18f04cb6aa66e4830cc7040b3103e27c2e800a\ + 0bce21b653566628a5bb8b0becb80b441801f31aa100fb4539cf7e4d6d68815a666c11c6cf4ac97878c551c043\ + 3750e9ab6fdeb65765ae3ece107302baf12b3086988bf4d0b37206bde4041cc7c4fa79d38170719e92c052187e\ + e810ed1b2b425c081512c7ee6ea722c413215229ebaecc207fb1126644e66dea7e0139682e90f91c71b579cd86\ + b91211305fe40770c3176e35b783732c2d74c8aa1a09da66c4f34dfa1f9fd35662c5c3d1f82eeb37498b121357\ + e73ed7eea79adeab91001b3c63b1f75aa82793cd1a2b39e1bb09ecf5c6522ccc46652d831abe3ad1f9bc301df5\ + 2c646068fd97c0402a29caa4ea3f4de8e5fb8a4d537d45d685f87d05d95f7ba40fbb6a919e93b44fb78b9c80ea\ + 6c0a75b4dff2f73844bf4f7172907d8165f606a47821da925eda50af0ce44be22fa2b36d56e1d1698a8#6074", + Greater, + ); + // - s == Limb::WIDTH in round_helper_2 + // - n == 0 first time in round_helper_2 + test( + "2.169542166817986625468879014599175406350620737442480370882139687492174119453066131804433\ + 632496405940270655469169364935548092764516132338564210201385531365409396738163453793191332\ + 174443470862749001312126324808896288354477512722829484994475343567852816045883088813362218\ + 109536965926916816038009290804934132950340684582117875938116310656669280480683072639988319\ + 858148103369026349100099758130382359401952836454392007054797540845974323496094771400665868\ + 125503436816661354237720713751777833086011158065863046075212704099660843597053397398549954\ + 8348685976904925033580113969653312280822082757679509546197165e-14", + "0x6.1b51e41e16de577dd7b5a3a6222357b305d4e7313b1d47721ebe3d4275ef95b0d98ad997627ec7acc76f5\ + d426b7c5a9333cbc0dec080499093952901e541880379e2fdf874d1d931d1243e2b2ab072c0772ce94734ae65d\ + ff7afda628d44635b3fba75efa9bd2c10d8bdcb3a61a8b6a7697f598758d80bd808f17f8351b1761850fd75cc1\ + 9f86409ac25dd27dd0ce7c26478dae9d50aff0210dc4fa18674fd87aa017255dabd141e1289a7e734e21577610\ + bf92b6ce4fe21881cc5209081e0536f0aeb1dcf6e288feeed183095b510c09e50c432ef280e742528c0c4dd6d2\ + 5e65c8b6d19c28914472a930aae1ad7fac96f6442134ee95f3bd8E-12#1993", + "301180.0045246172416425721655892719573457356766058630317841133942315022590404351104810586\ + 213517139802439747677458029756555586634849124296886483237621871644459126081050822492233083\ + 707945595254133438910359944302659214080172068073620764660184379004827633051943726032292014\ + 225559234820452819113849827971319776547835482966443724022128469656550054145203573809984759\ + 336239968661049955088445384576034864711412948863817402256055440443111246220943775270251981\ + 245519547063921282094595332683031347213016637666849460902039610984880445147686118036204784\ + 051476863264255027838976527798504452504598268980029728768388473210371246534136227460265249\ + 86471927", + "0x4987c.0128867b146bf9c05b0bb90d2c480c2b610c9c19a0a03f58f0d0aefa84d41a94dbc0c1206d80eab12\ + 18d0f5e72e0b72a6f063fe0f604b1eedcc3760c7f60b2aa6e35735292ea939fa59fc7da94b3e86d7bbba5f8ef6\ + 8136a9a4c5d98df58e4ad215fee20274cd18a324d8b66b0119d3cf93efacf51659a9814222c8f9b53fe6356392\ + e2b27f1ee07621f888214936f129248d805ae614b37cae5b83f51b2be167dc62ef96c1322204921369dc6c7475\ + c195aa735676f467be6a45d895b6b08fba56a7919ac216a6dc76cf9f5c3184a2ffa7b1bc3d8760c250d651afca\ + 18aa90ff70ee4532482978816617fb02f0de87b2abd54886d1c7c16d62550d5fd8a4abb55b0c4ebb8c#2111", + Nearest, + "7.203473451839519375659920800256968930150281137907207966420457324091308743561158996788387\ + 290694159461823269997598092194316979651412090098764718003237064733792291895103263169730962\ + 123418174759909091404064508319172962888992299461557410206033700688023479037478761668781891\ + 761303156472454780198812373188616203221872171676002219543916314587725944225532571475160352\ + 707938049990541748698746656039607206067984173221685967465441429896808706646646536972493098\ + 282122681082474772608417991249668805473092287771115239878542545454824251859441724816281902\ + 754574769925885897122660854445163455617440019293712118274988718965330199709067927675503187\ + 81705947e-20", + "0x1.542ca6851865ac89e311ac1608cac34c9fe637305345b739b624981a50028d6f60e7fd803167413e1285b\ + 796e7a5ed37e1cb19125606ca9d15a697c9c497b14455aae6477ad96ffa4f216a14878a9802e8350d104f0b9d8\ + cd86ff511d7efbd74d40104b107a9d7f33d0e8894d3b157e46b7fd4e6386f823e75ae0efa9be33aac3e252d7d2\ + 411f8e2afd3773f3914778d26a6b76f5569fd822db5a66db515e3cdd6699301b71cbdb73f07c24fb20d0c66059\ + fe1f236a4656c3f508e25958bdef5ca863d7950c5740d7849b46bde7e1a38b797265dedd7d4dfdaee7bcb69dce\ + 887bddd7a7bbd45a6561cfad8cd840e7d95599a81bb274cc02a161439f7280459a15c9865ad5b658ed8E-16\ + #2111", + Less, + ); + // - n != 0 && tmp != 0 && tmp == mask in round_helper_2 + // - s != Limb::WIDTH second time in round_helper_2 + test( + "7.967842945782984973942186035477141750978306951371418866981413625233901049016799636923049\ + 043510064598367854094347269064974737243308027061881036076018766384961823690368428913274793\ + 537e-19", + "0xe.b2b51b3ba9b3fa4c3c91f60bbe2f30efe9403d1c1ed1fa2688711592167dc11f579d747f20609a0e8704a\ + 660072ec620d514ab31d0845381f10e96f76ac41c97c2a7b53849757dc846fdeE-16#599", + "4.290314881292277334232122993869736164625712811477787127079554140127474408529492187148865\ + 860241941174878594521708166855716060386064937593774872957730026516247807479269506509835640\ + 014575725456051856772978910171974972671741113731811243859146099959299700690748160884209812\ + 639693266282036645473254451466381125403186024743001502094065938286200460441378264282871237\ + 445194601993083290951436490295842815606015494575193282638997440331311694865085507331318327\ + 437042408938144577985735854973264189023250983346696190654635795462654945584732891184659237\ + 746883228154089313101793763347136552004708447204474905674167880735273390965084667673056531\ + 378593414825374458582134295243495148718875340371312206621884585775967428131940924035968587\ + 526069447315202760539547246403295371510536211424729007907823710381420209210303664575050843\ + 559776729235120592670693730372232402604761499044741741752247404544150954858075273585139895\ + 643242778698674255451287458469387850297372316908957826221759549123594364155475346755476293\ + 552962991845182999537688763267208310118481794778770137863789646906639637779481228371710954\ + 980900001879766864929946144490423459237336070803276511200399191948305713293997532907864745\ + 24489311444825214442690999e-14", + "0xc.137f67f6b60895b6164f36c36d5b134858a21d493d7d49584a1811d76bd92f10b6d0aa0bea20843896e0f\ + d0d2e93957b024a1b5e7101d0f679c3dcc134107c20f0664acbfdf6bafac9013ae41ce018c62b6cf36043f13a8\ + 1c35291946c79569662de17adff4ec759b1ccbe440675ef95167b0d5a5481ea6e7a6b998233e094436c8eeaefb\ + e21fa0f9c24aad8d11f378034d73a5daec0111cef1b0b8426dd5df78555318d44c992e40ad5fa98171908c4019\ + 636becfe749a93747c965c11e84b68df48e887e933449d42c1ec5c2d6a7658e91f6d68333ddfde5719ca117d72\ + dadec43975eb0b6b6a076c4ada32d70b0e93250cf5e8836b11ad6a8b13a4a957de6221168782640f2313ca3716\ + 3e4da0decaee000e5824d53c71d0a36a55295f8ad1c7a86eb35eab709891d1a6ac96a10448e0e307c7d6742d8d\ + 0617a3e21978394d0393bc9be8e32ff2d87e85ae44c3a76ac79752bcca4927ca5dc6dcfc4db10793dc0cfc2161\ + 24fdf30070db19fd8a89982adf45a408e08499b77cf25011c54cf9270bf491a2186e1a5fad26087812cc3c2446\ + ca7e5457d75f66fe9e736ad07c6b1fe4b20eaf1f073d454f371f659f7402d24e6666c8e212ddccf50c22209ca5\ + 7651a266ecba0559cacf587691f7f7df3389d9968023d71b412cc20516c9b1d00f1392474c6683bd0fd6c6dc7a\ + 705d88E-12#3966", + Nearest, + "0.000018571697337476093645597974800042221391343383471511758884717235995391699590980821846\ + 925772010524277797520625056343676345716562878283777572676679678398279369283853673423775272\ + 117775978501001731220831012727542639628984101788862199591237806493805996059161201835253203\ + 204357442043212398495525692960904672132359565047969002327766123188917268873022220728326927\ + 266813579456518458545345939557868848624450974456390610446369728959726525392113471132021539\ + 038960803550352390128253151270734177749632737865390247648212171456318006032507634424453843\ + 795159031314496937836591202252458892414236797451738560115150573320872948069964155298984838\ + 456270978739037104719669912968807593222214861520588395175617611807975267322946381339673265\ + 479787948188151606275111200784895864164305724683464061829109671306661764726602634895903888\ + 287506327660181397735839535481997625450956961420572462126703944263526095290954835871182404\ + 868513321447417245068813964246287015709186652991049553947407472630595976266674750290084010\ + 397575525528176465754260767775733418629588880876176812207672741703984898153224615968196909\ + 775917982890995046346113085550279268258183711136206964350043642244181512435164664671221839\ + 6370838653686792137638621224928", + "0x0.00013794d52b8b1e96ced9de16a585696e655c080cbd5da8030eef302763f4138b28d7261786b8ff50bc6\ + 9d0a5f06f20dad7ee2a65fae9caeeaee187ea820eae6fd4c8a673a92def1c9a165c1aeec8807ddb464eac6f550\ + 6dbe6d6e3a21a035c4472d414f4887b05775ede2ad98b9b380b663c0929394c811648792ef20f0756b6bad50de\ + 099fda3dd792ae5616df8837945c3cb4cd833fb9bf0db07243887c0a8fedba7030c428024be8572bca9398f563\ + b2a661574fd7faf130ac3d404dbe94b7e0ca06f440962616e1879d4f15895a10229f04969c26dbb9a1b733f734\ + fd2be1c88c7b20af178cd1d3fa116fba33a435b040155b5f5f28f0668b798810c2acb1faf0581e46cc71e9b07f\ + c9e4ebcd8a96a7d7d318d649e4468baa2ce2cdf9b1adf74f6a6b8b95a3eed5991934327ddfeb243e80db0c230e\ + d593df31dce1201e64430a27d39e6760dcf2086c1cb86bfb4e9211f18940b72d1a492a5b9109c0fdf4f5fa9fce\ + 9e0ec199756ee5f8e69ba7ded6b7507facbc46df62adaa4546b3113a80e7ea40bab782194bfd006099f6a79bb8\ + 19aad950497cae351fdc370756b86b3188e5c2cf71ed56fdb3683c9cc38facff80b0f2076d0f3b3a8605ca24d2\ + c8b6301601e23b50ea0940f7ba05f92ddd4a644cca6e420d6bfcd06caab9c695ba67b857bc57e1000b5935d0a8\ + 79821217280#3966", + Less, + ); + // - rm == Nearest && shift == 0 first time in div_float_significands_general + test( + "3.494003589335061592114850452482839587826456952956376068177291318828682713177358264760784\ + 874304744009907216335963217912223351596098015455390432300579562836209635380394751634810606\ + 195414389573610568068623776330707730813932586805062287543490729241818555718410383777926489\ + 343323917900958772688451527795643412381235039158654803215405274640835172391547486080681691\ + 827169629800140882523056966137099117587677259077996268577162491409610597231997851472454718\ + 312803304389117924206548413988545367622912505139619073824279361037770537659001099972259551\ + 367613373821227769095845567435994753397767332318253172120529133505790353120177308303588487\ + 770407205738279213609665027613843515660027068482463985188375646552261141849026408186728824\ + 80307838589616979262426550353243006148083216398932181e-12", + "0x3.d7797e014d587584d7875beed50257a2555726437bf03fdebac1110cae2c4b64f09f9a338bf2ca8b1fcf5\ + e0128d7f387a40893706e25c04e65fdd316e3fc348d2478632d632bae209325b6c681dde52405cd7f8d9707d7f\ + 5d6de0abb73e130c41c21c4537ce41381fc43788187dab4fa280fa46503f1890d663ca441f49a6a7e2b712e710\ + 4c826535fdf1c8ae0282d162e3d128a982e44f67c6104624863e7f3c2c60833df521e5bab88feddd4843e4b50b\ + 81ba442bc612787ad38f640412f6cff81df9793590dfa6a0debdd7f2f6de7a089fc50d597d700dbeeecfc9d795\ + ceb9a69d05db5c520717ddd7e73fabaea4e2cb06b1e1874b8b541dfca2083cb277e4d1bbefa48c0a427afea0a5\ + 87cd5085c2ba28c1cad42a97be72844e851abf698ac844915e9f5ac4af406a2c354aa055f3c0994b7932d1bdb7\ + b4999768f776148E-10#2560", + "8.388557903692744678886673027706512178020882171440574341138664910770681048759242342335520\ + 689291884051853125391850946672822384185374426629671262437149651332606541726962233658521936\ + 440197380293004778812876511148916284206096731251130678261803308370362817534297504354768207\ + 175302739282372189357904919163400327254111204148827422042723518774290057028465296755126014\ + 371014512774422430414368313070504306047237723842986944935010614200247398223867859750512432\ + 528263508555538801970472032683504663202558316239308702078808690323956381650112536926354687\ + 819619269837340011822483859668579241157516055938780563664184620140501025776680716962470155\ + 2e-35", + "0x6.f80c88bef08546fc8a21f0f2152ee0612eebad2635acbe0d49ce7179b387d0719cd657923976ec2796026\ + 5e330a5e71c0cd8417c2cf919556130f9b353cdf2435349f846c895ede372648bccd9c217f1bb7c3e4197c1806\ + c4744c8a05ddf4f67946a4972f056d84028e7023d956a95b2ff067c093002267f7015fecb9ca5ed8f58dde48d7\ + 4510e965bfa6478370f4e71e5a240dabdd9a4d6e000d4af93eea8510c6c4e095290bce062925fd9a7245caff37\ + 8b7be01d3b94b56154cbeb98c26f78338a98e416fa9acc3bd12c4953b058efdcdbe56335f952208a15166babaa\ + 698da808f96df97655d3f5cdb4768e6370755a01515d4ad54f625432fc742e9121b7cce4fdb08E-29#2088", + Nearest, + "41652017300815899948547.94831484736938823572318695739742204735159366375620848030675947597\ + 937407214848121136435440017047965685656179645007771422864559798518659544278806178160023554\ + 020245599674536568425190916908552958650848910192845046055088066614557330847090320384899468\ + 575304634050066348271499359839369427201019441174516439045175255034723132436872248790761539\ + 506937527488424041602486298663492699846695028977559705152038731125314966620233281505474337\ + 677248672173837029868825260085661764008715204976773612281854954844288452423998027475082981\ + 779489389492756600188312999400831430516184077432877044587246391185262444911853744883006186\ + 684049728461939709785134255700251964580618924591175050653894151676243677123400686218961075\ + 24208104943935667403367286485079704207117845193523456", + "0x8d1f5db9d3f145a7603.f2c4c307c343da5b63ef331aa97f5e951921921a937336258bc4ab65fdf9d715d36\ + ef6755e61dd29859283e35c618271ec076a196c3ddb06ce536bafe52ad10a521ebfdcda2a3839fce6eadd33d87\ + eba1d25c5eacfa66f0af4f1ce568be4792717319611eb807fe7fc0d855f2cf1b099f908a269208b3ee36d33e71\ + 3912e0557515bf16566f8cc4c8c45fd6bb2ced1b3d3f27c9b272c6e5dfaacdd66335f658951d70cd7b3190aac8\ + b90d7e564b5c0ac68a04f4681a552c50de11c466e3ac1230d426fdc851e7d5705e73d7ad30a82c2febb82c46b4\ + 93762b8d7c80e514c1fe29a64d4189fc176b72bb816f1223676b93d38dc33a2fd578eaf5fa512468b21e723d6c\ + d5595dac5bfd84c94e4826fc5b9aff74dec22c3cb43d7970a1359eb2642295a920a70da20a166db400602f0f4f\ + 2aee9255f2251c#2560", + Greater, + ); + // - !round_helper_2 in div_float_significands_general + test( + "3.999999999999999999999999999999999999999999999999999999999999999999999999999447285212473\ + 955543975273480780774427448575976676077991358482977909210124597604668289823519777773553500\ + 1249731874464215297923136674027554116062077582682832144200801849365234375", + "0x3.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000000000000000000000000000000000#2090", + "3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000038180485e-31", + "0x8.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000001ffffffeE-26#2567", + Nearest, + "10141204801825835211973625643007.99999999999999999999999999999999999999999999859870153567\ + 518292907627041671008386871973805812348422824293171611020891731413939851336181163787841796\ + 874999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 99999999999999999999999999999999999999999999999018341217", + "0x7fffffffffffffffffffffffff.fffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffe0000002#2567", + Less, + ); +} + +#[test] +fn div_round_fail() { + const THREE: Float = Float::const_from_unsigned(3); + assert_panic!(Float::ONE.div_round(THREE, Exact)); + assert_panic!(Float::ONE.div_round_val_ref(&THREE, Exact)); + assert_panic!(Float::ONE.div_round_ref_val(THREE, Exact)); + assert_panic!(Float::ONE.div_round_ref_ref(&THREE, Exact)); + + assert_panic!({ + let mut x = Float::ONE; + x.div_round_assign(THREE, Exact) + }); + assert_panic!({ + let mut x = Float::ONE; + x.div_round_assign_ref(&THREE, Exact) + }); +} + +#[test] +fn test_div_prec_round() { + let test = |s, s_hex, t, t_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + let y = parse_hex_string(t_hex); + assert_eq!(y.to_string(), t); + + let (quotient, o) = x.clone().div_prec_round(y.clone(), prec, rm); + assert!(quotient.is_valid()); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + assert_eq!(o, o_out); + + let (quotient_alt, o_alt) = x.clone().div_prec_round_val_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let (quotient_alt, o_alt) = x.div_prec_round_ref_val(y.clone(), prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let (quotient_alt, o_alt) = x.div_prec_round_ref_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_prec_round_assign(y.clone(), prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_prec_round_assign_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o_out); + + let (quotient_alt, o_alt) = div_prec_round_naive(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_div_prec_round( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + } + }; + test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); + + test( + "NaN", "NaN", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + 1, + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + 1, + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + 1, + Down, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + 1, + Up, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + 1, + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "NaN", + "NaN", + "-Infinity", + "-Infinity", + 1, + Exact, + "NaN", + "NaN", + Equal, + ); + + test("NaN", "NaN", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); + test( + "NaN", "NaN", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, + ); + test("NaN", "NaN", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); + test( + "NaN", "NaN", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, + ); + test("NaN", "NaN", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); + + test( + "NaN", "NaN", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, + ); + test("NaN", "NaN", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); + test( + "NaN", "NaN", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "NaN", "NaN", "1.0", "0x1.0#1", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "1.0", "0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal, + ); + test("NaN", "NaN", "1.0", "0x1.0#1", 1, Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "1.0", "0x1.0#1", 1, Up, "NaN", "NaN", Equal); + test( + "NaN", "NaN", "1.0", "0x1.0#1", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "1.0", "0x1.0#1", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Down, "NaN", "NaN", Equal, + ); + test("NaN", "NaN", "-1.0", "-0x1.0#1", 1, Up, "NaN", "NaN", Equal); + test( + "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "Infinity", "Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "Infinity", "Infinity", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "Infinity", "Infinity", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + 1, + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + 1, + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + 1, + Down, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + 1, + Up, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + 1, + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "Infinity", + "Infinity", + "-Infinity", + "-Infinity", + 1, + Exact, + "NaN", + "NaN", + Equal, + ); + + test( + "Infinity", "Infinity", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-0.0", + "-0x0.0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "Infinity", + "Infinity", + "-1.0", + "-0x1.0#1", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + 1, + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + 1, + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + 1, + Down, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + 1, + Up, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + 1, + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "NaN", + "NaN", + 1, + Exact, + "NaN", + "NaN", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + 1, + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + 1, + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + 1, + Down, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + 1, + Up, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + 1, + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "Infinity", + "Infinity", + 1, + Exact, + "NaN", + "NaN", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + 1, + Floor, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + 1, + Ceiling, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + 1, + Down, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + 1, + Up, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + 1, + Nearest, + "NaN", + "NaN", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-Infinity", + "-Infinity", + 1, + Exact, + "NaN", + "NaN", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0.0", + "0x0.0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + 1, + Floor, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + 1, + Ceiling, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + 1, + Down, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + 1, + Up, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + 1, + Nearest, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-0.0", + "-0x0.0", + 1, + Exact, + "Infinity", + "Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "1.0", + "0x1.0#1", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + 1, + Floor, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + 1, + Ceiling, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + 1, + Down, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + 1, + Up, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + 1, + Nearest, + "Infinity", + "Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "-1.0", + "-0x1.0#1", + 1, + Exact, + "Infinity", + "Infinity", + Equal, + ); + + test("0.0", "0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); + test( + "0.0", "0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, + ); + test("0.0", "0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); + test( + "0.0", "0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, + ); + test("0.0", "0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); + + test( + "0.0", "0x0.0", "Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal, + ); + + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + 1, + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + 1, + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + 1, + Down, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + 1, + Up, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + 1, + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0.0", + "0x0.0", + "-Infinity", + "-Infinity", + 1, + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test( + "0.0", "0x0.0", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "0.0", "0x0.0", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, + ); + test("0.0", "0x0.0", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); + test( + "0.0", "0x0.0", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "0.0", "0x0.0", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal, + ); + test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); + test( + "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Floor, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Down, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Up, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Exact, "0.0", "0x0.0", Equal, + ); + + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Floor, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Ceiling, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Down, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Up, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Nearest, "-0.0", "-0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Exact, "-0.0", "-0x0.0", Equal, + ); + + test( + "-0.0", "-0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, + ); + test("-0.0", "-0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); + test( + "-0.0", "-0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Floor, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Ceiling, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Down, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Up, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Nearest, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Exact, "-0.0", "-0x0.0", Equal, + ); + + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + 1, + Floor, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + 1, + Ceiling, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + 1, + Down, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + 1, + Up, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + 1, + Nearest, + "0.0", + "0x0.0", + Equal, + ); + test( + "-0.0", + "-0x0.0", + "-Infinity", + "-Infinity", + 1, + Exact, + "0.0", + "0x0.0", + Equal, + ); + + test( + "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal, + ); + test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); + test( + "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Floor, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Ceiling, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Down, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Up, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Nearest, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Exact, "-0.0", "-0x0.0", Equal, + ); + + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Down, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Up, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Exact, "0.0", "0x0.0", Equal, + ); + + test( + "123.0", "0x7b.0#7", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "123.0", "0x7b.0#7", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "123.0", "0x7b.0#7", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, + ); + test( + "123.0", "0x7b.0#7", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, + ); + test( + "123.0", "0x7b.0#7", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "123.0", "0x7b.0#7", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal, + ); + test( + "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal, + ); + + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + 1, + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + 1, + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + 1, + Down, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + 1, + Up, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + 1, + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-Infinity", + "-Infinity", + 1, + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-0.0", + "-0x0.0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 1, + Floor, + "6.0e1", + "0x4.0E+1#1", + Less, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 1, + Ceiling, + "1.0e2", + "0x8.0E+1#1", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 1, + Down, + "6.0e1", + "0x4.0E+1#1", + Less, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 1, + Up, + "1.0e2", + "0x8.0E+1#1", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 1, + Nearest, + "1.0e2", + "0x8.0E+1#1", + Greater, + ); + + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 10, + Floor, + "123.0", + "0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 10, + Ceiling, + "123.0", + "0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 10, + Down, + "123.0", + "0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 10, + Up, + "123.0", + "0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 10, + Nearest, + "123.0", + "0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "1.0", + "0x1.0#1", + 10, + Exact, + "123.0", + "0x7b.0#10", + Equal, + ); + + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 1, + Floor, + "-1.0e2", + "-0x8.0E+1#1", + Less, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 1, + Ceiling, + "-6.0e1", + "-0x4.0E+1#1", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 1, + Down, + "-6.0e1", + "-0x4.0E+1#1", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 1, + Up, + "-1.0e2", + "-0x8.0E+1#1", + Less, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 1, + Nearest, + "-1.0e2", + "-0x8.0E+1#1", + Less, + ); + + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 10, + Floor, + "-123.0", + "-0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 10, + Ceiling, + "-123.0", + "-0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 10, + Down, + "-123.0", + "-0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 10, + Up, + "-123.0", + "-0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 10, + Nearest, + "-123.0", + "-0x7b.0#10", + Equal, + ); + test( + "123.0", + "0x7b.0#7", + "-1.0", + "-0x1.0#1", + 10, + Exact, + "-123.0", + "-0x7b.0#10", + Equal, + ); + + test( + "NaN", "NaN", "123.0", "0x7b.0#7", 1, Floor, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "123.0", "0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "123.0", "0x7b.0#7", 1, Down, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "123.0", "0x7b.0#7", 1, Up, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "123.0", "0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal, + ); + test( + "NaN", "NaN", "123.0", "0x7b.0#7", 1, Exact, "NaN", "NaN", Equal, + ); + + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123.0", + "0x7b.0#7", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Floor, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Down, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Up, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "0.0", "0x0.0", Equal, + ); + test( + "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Exact, "0.0", "0x0.0", Equal, + ); + + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Floor, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Down, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Up, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "-0.0", "-0x0.0", Equal, + ); + test( + "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Exact, "-0.0", "-0x0.0", Equal, + ); + + test( + "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Floor, "0.008", "0x0.02#1", Less, + ); + test( + "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Ceiling, "0.02", "0x0.04#1", Greater, + ); + test( + "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Down, "0.008", "0x0.02#1", Less, + ); + test( + "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Up, "0.02", "0x0.04#1", Greater, + ); + test( + "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Nearest, "0.008", "0x0.02#1", Less, + ); + + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Floor, + "0.00812", + "0x0.0214#10", + Less, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Ceiling, + "0.00813", + "0x0.0215#10", + Greater, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Down, + "0.00812", + "0x0.0214#10", + Less, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Up, + "0.00813", + "0x0.0215#10", + Greater, + ); + test( + "1.0", + "0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Nearest, + "0.00813", + "0x0.0215#10", + Greater, + ); + + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 1, + Floor, + "-0.02", + "-0x0.04#1", + Less, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 1, + Ceiling, + "-0.008", + "-0x0.02#1", + Greater, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 1, + Down, + "-0.008", + "-0x0.02#1", + Greater, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 1, + Up, + "-0.02", + "-0x0.04#1", + Less, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 1, + Nearest, + "-0.008", + "-0x0.02#1", + Greater, + ); + + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Floor, + "-0.00813", + "-0x0.0215#10", + Less, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Ceiling, + "-0.00812", + "-0x0.0214#10", + Greater, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Down, + "-0.00812", + "-0x0.0214#10", + Greater, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Up, + "-0.00813", + "-0x0.0215#10", + Less, + ); + test( + "-1.0", + "-0x1.0#1", + "123.0", + "0x7b.0#7", + 10, + Nearest, + "-0.00813", + "-0x0.0215#10", + Less, + ); + + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Floor, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Ceiling, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Down, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Up, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Nearest, "0.5", "0x0.8#1", Equal, + ); + test( + "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Exact, "0.5", "0x0.8#1", Equal, + ); + + test( + "1.0", + "0x1.0#1", + "2.0", + "0x2.0#1", + 10, + Floor, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "1.0", + "0x1.0#1", + "2.0", + "0x2.0#1", + 10, + Ceiling, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "1.0", + "0x1.0#1", + "2.0", + "0x2.0#1", + 10, + Down, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "1.0", + "0x1.0#1", + "2.0", + "0x2.0#1", + 10, + Up, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "1.0", + "0x1.0#1", + "2.0", + "0x2.0#1", + 10, + Nearest, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "1.0", + "0x1.0#1", + "2.0", + "0x2.0#1", + 10, + Exact, + "0.5", + "0x0.800#10", + Equal, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Floor, + "0.2", + "0x0.4#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Ceiling, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Down, + "0.2", + "0x0.4#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Up, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Nearest, + "0.5", + "0x0.8#1", + Greater, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Floor, + "0.4497", + "0x0.732#10", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Ceiling, + "0.4502", + "0x0.734#10", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Down, + "0.4497", + "0x0.732#10", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Up, + "0.4502", + "0x0.734#10", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Nearest, + "0.4502", + "0x0.734#10", + Greater, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Floor, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Ceiling, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Down, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Up, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Nearest, + "-0.5", + "-0x0.8#1", + Less, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Floor, + "-0.4502", + "-0x0.734#10", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Ceiling, + "-0.4497", + "-0x0.732#10", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Down, + "-0.4497", + "-0x0.732#10", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Up, + "-0.4502", + "-0x0.734#10", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Nearest, + "-0.4502", + "-0x0.734#10", + Less, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Floor, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Ceiling, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Down, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Up, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Nearest, + "-0.5", + "-0x0.8#1", + Less, + ); + + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Floor, + "-0.4502", + "-0x0.734#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Ceiling, + "-0.4497", + "-0x0.732#10", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Down, + "-0.4497", + "-0x0.732#10", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Up, + "-0.4502", + "-0x0.734#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Nearest, + "-0.4502", + "-0x0.734#10", + Less, + ); + + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Floor, + "0.2", + "0x0.4#1", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Ceiling, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Down, + "0.2", + "0x0.4#1", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Up, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Nearest, + "0.5", + "0x0.8#1", + Greater, + ); + + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Floor, + "0.4497", + "0x0.732#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Ceiling, + "0.4502", + "0x0.734#10", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Down, + "0.4497", + "0x0.732#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Up, + "0.4502", + "0x0.734#10", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Nearest, + "0.4502", + "0x0.734#10", + Greater, + ); + + // - (rm == Ceiling || rm == Up) && overflow in div_float_significands_long_by_short + test( + "2.493205886061172926", + "0x2.7e42bdaed3d31b2#61", + "7.459893537e20", + "0x2.870ae94cE+17#33", + 5, + Ceiling, + "3.4e-21", + "0x1.0E-17#5", + Greater, + ); + + // - rm != Nearest third time in div_float_significands_genera + test( + "3.7563361266e88", + "0x4.b87f4dfa0E+73#36", + "6.769173652614128677797571270436826716e-13", + "0xb.e8909656207637d3379c02628519c4E-11#123", + 63, + Ceiling, + "5.549179736559369991e100", + "0x6.57b76abe8193e56E+83#63", + Greater, + ); + // - (rm == Up || rm == Ceiling) && (round_bit != 0 || sticky != 0) && carry in + // div_float_significands_general + test( + "4.70916604581e-30", + "0x5.f8363584bE-25#39", + "341290809831481093.63402342431195212374059", + "0x4bc822eed1c5f05.a24f5bf051591756f951#139", + 1, + Ceiling, + "2.0e-47", + "0x2.0E-39#1", + Greater, + ); + // - rm != Nearest && ((rm != Ceiling && rm != Up) || inex == 0) && (inex == 0 || rm != Exact) + // in div_float_significands_general + // - goto_sub_1_ulp in div_float_significands_general + test( + "6265419941341407687.894108147333", + "0x56f33e3db44da9c7.e4e44583e2#102", + "28506201793260972591.2041505871822190859316631273737217979877602592305648246097", + "0x18b9a5f7fa6ec6a2f.3443367f6825dd51709bc60beed373653861dd1a1c6c0422#256", + 63, + Floor, + "0.2197914680735399977", + "0x0.384440ef50d090080#63", + Less, + ); + // - rm == Floor || rm == Down fourth time in div_float_significands_general + // - (rm == Floor || rm == Down) fourth time && shift != 0 in div_float_significands_general + test( + "1.274876025e31", + "0xa.0e9775E+25#28", + "7.104011072486714881105976022274735719942619445087760266603169705559e-82", + "0x5.6412fa517e8e5c9e2826903dbe9c6b4f020acbf4d07a5f83b6e4008E-68#222", + 126, + Floor, + "1.79458620199896394199805694868744557483e112", + "0x1.dd946a676df629632baf4759d5af1088E+93#126", + Less, + ); + // - rm == Ceiling || rm == Up fourth time in div_float_significands_general + // - (rm == Ceiling || rm == Up) fourth time && shift != 0 in div_float_significands_general + test( + "1.766000056026770292793619415e30", + "0x1.64a410213aff5d6e713e280E+25#90", + "3.8777897715163284337835091275987988e-9", + "0x1.0a7acc91ecf72f35cdef4a25d008eE-7#116", + 63, + Ceiling, + "4.554140786585790019e38", + "0x1.569d8fa574bc1b5cE+32#63", + Greater, + ); + // - (rm == Floor || rm == Down) fourth time && shift == 0 in div_float_significands_general + test( + "2.6837e8", + "0xf.ffE+6#12", + "33554432.0156249999999999", + "0x2000000.03fffffffffff8#79", + 64, + Floor, + "7.9980468712756191975", + "0x7.ff7ffff001000018#64", + Less, + ); + // - (rm == Ceiling || rm == Up) fourth time && shift == 0 in div_float_significands_general + test( + "0.00341799855229", + "0x0.00e0007ffff8#37", + "9444877080927366283263.8", + "0x20001ffffffffffffff.c#76", + 64, + Ceiling, + "3.6188915144233536057e-25", + "0x6.fffd0002bffd4008E-21#64", + Greater, + ); + // - cmp_s_r == Equal && shift == 0 in div_float_significands_general + test( + "6699743.0549682103909956055738813882394392365647386167825", + "0x663adf.0e126589f2efed5e335a996cf4ea2b00000000000#186", + "2.7716996157956048532084742e-18", + "0x3.320fb3ad0fa6bc833b14E-15#82", + 64, + Exact, + "2.4171966604126677691e24", + "0x1.ffdc7e57cc8990bcE+20#64", + Equal, + ); + // - (32-bit) len == 0 in sub_helper + test( + "30600.896887617100679", + "0x7788.e59a6d47a2818#64", + "2502994226528294594711254131620329726924950421806.930251136099954006921970343593452748426\ + 707752157088293012113325450782206798004004382505336607707515733277073230960543511755657896\ + 564954610313805343294199781328288665758818764110630501992193446364134574345717105834955361\ + 7609386520869921223421139170307521302744186647065523683732731123797753054753663", + "0x1b66e24958fe115307da9ef9c4f815e31129d412e.ee24f03e9dbbd6cdaa800176f4f7a592b62d2ecb1428c\ + 19779d86494af5a809600728d36c503347da5f0182f00935e63a628c673a55a1e67334c368efde2d7a0fccbc62\ + 0edc630bdd9fafc83b3088a3186480eefe67a7c19b91b866c079c0716d7b844259f598eeb31d6c0baf035c6bc4\ + 6b11b5efad4f3ae582c7740#1151", + 32, + Ceiling, + "1.2225716132e-44", + "0x4.5cbe7760E-37#32", + Greater, + ); + // - rm == Up || rm == Ceiling && carry in div_float_significands_general + test( + "2.454546732648863276547885977493137821487607756249724782555774558593552627360857928230048\ + 942018665976138591785782565939256583959305212359451403757412054481726126552732229930964269\ + 470905492198653519153594970703124999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ + 995761114627674791277020932519574469505017610728137410250159407014720169738824650046673749\ + 059339474479527195633303962573451642912661719349979993453218111358455268175773121496346851\ + 580476856645369527796626919786850732045813122714395701160155300736782415936562761674226693\ + 028929972451809327089060718204876263534635026488050357020524924317959135992439056643999723\ + 656960561739673936265216544476386688997222734833105296938067057205929214479610015975275932\ + 718619380628277147130611593861916399934357066581330096178050556305086195135562253719174061\ + 496425118601354010153670564319137109364713055282273218494183562236985834389291157056469689\ + 9828846337814e-91", + "0x7.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000E-76#4517", + "0.015625000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000771048757510508716764719334683019132168263108153512725551350734409293871565\ + 903519457201213361797567020084883497703807999422859208123581192925346248118136084792628172\ + 988363113468168413497993606331107182531734570308778128025953654408272649725745457159283262\ + 0134958821588759455527143", + "0x0.0400000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffff\ + fffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000#3655", + 2337, + Ceiling, + "1.570909908895272496990647025595608205752068963999823860835695717499873681510949074067231\ + 322891946224728698742900842201124213733955335910048898404743714868304720993748627155817132\ + 46137951500713825225830078125e-89", + "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000E-74#2337", + Greater, + ); +} + +#[test] +fn div_prec_round_fail() { + const THREE: Float = Float::const_from_unsigned(3); + assert_panic!(Float::one_prec(1).div_prec_round(Float::two_prec(1), 0, Floor)); + assert_panic!(Float::one_prec(1).div_prec_round_val_ref(&Float::two_prec(1), 0, Floor)); + assert_panic!(Float::one_prec(1).div_prec_round_ref_val(Float::two_prec(1), 0, Floor)); + assert_panic!(Float::one_prec(1).div_prec_round_ref_ref(&Float::two_prec(1), 0, Floor)); + assert_panic!({ + let mut x = Float::one_prec(1); + x.div_prec_round_assign(Float::two_prec(1), 0, Floor) + }); + assert_panic!({ + let mut x = Float::one_prec(1); + x.div_prec_round_assign_ref(&Float::two_prec(1), 0, Floor) + }); + + assert_panic!(Float::ONE.div_prec_round(THREE, 1, Exact)); + assert_panic!(Float::ONE.div_prec_round_val_ref(&THREE, 1, Exact)); + assert_panic!(Float::ONE.div_prec_round_ref_val(THREE, 1, Exact)); + assert_panic!(Float::ONE.div_prec_round_ref_ref(&THREE, 1, Exact)); + assert_panic!({ + let mut x = Float::ONE; + x.div_prec_round_assign(THREE, 1, Exact) + }); + assert_panic!({ + let mut x = Float::ONE; + x.div_prec_round_assign_ref(&THREE, 1, Exact) + }); +} + +#[test] +fn test_div_rational() { + let test = |s, s_hex, t, out: &str, out_hex: &str| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + let y = Rational::from_str(t).unwrap(); + + let quotient = x.clone() / y.clone(); + assert!(quotient.is_valid()); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let quotient_alt = x.clone() / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + let quotient_alt = &x / y.clone(); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + let quotient_alt = &x / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + + let mut quotient_alt = x.clone(); + quotient_alt /= y.clone(); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + let mut quotient_alt = x.clone(); + quotient_alt /= &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + + assert_eq!( + ComparableFloatRef(&Float::from(&rug_div_rational( + &rug::Float::exact_from(&x), + &rug::Rational::from(&y) + ))), + ComparableFloatRef("ient) + ); + + let quotient_alt = + div_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let quotient_alt = + div_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + }; + test("NaN", "NaN", "123", "NaN", "NaN"); + test("Infinity", "Infinity", "123", "Infinity", "Infinity"); + test("-Infinity", "-Infinity", "123", "-Infinity", "-Infinity"); + test("NaN", "NaN", "0", "NaN", "NaN"); + test("Infinity", "Infinity", "0", "Infinity", "Infinity"); + test("-Infinity", "-Infinity", "0", "-Infinity", "-Infinity"); + + test("0.0", "0x0.0", "0", "NaN", "NaN"); + test("-0.0", "-0x0.0", "0", "NaN", "NaN"); + test("0.0", "0x0.0", "123", "0.0", "0x0.0"); + test("-0.0", "-0x0.0", "123", "-0.0", "-0x0.0"); + test("0.0", "0x0.0", "-123", "-0.0", "-0x0.0"); + test("-0.0", "-0x0.0", "-123", "0.0", "0x0.0"); + test("0.0", "0x0.0", "1/3", "0.0", "0x0.0"); + test("-0.0", "-0x0.0", "1/3", "-0.0", "-0x0.0"); + test("123.0", "0x7b.0#7", "1", "123.0", "0x7b.0#7"); + test("123.0", "0x7b.0#7", "0", "Infinity", "Infinity"); + test("-123.0", "-0x7b.0#7", "0", "-Infinity", "-Infinity"); + + test("1.0", "0x1.0#1", "2", "0.5", "0x0.8#1"); + test("1.0", "0x1.0#2", "2", "0.5", "0x0.8#2"); + test("1.0", "0x1.000#10", "2", "0.5", "0x0.800#10"); + test("1.0", "0x1.000#10", "3/2", "0.667", "0x0.aac#10"); + test( + "1.0", + "0x1.0000000000000000000000000#100", + "3/2", + "0.666666666666666666666666666667", + "0x0.aaaaaaaaaaaaaaaaaaaaaaaab#100", + ); + + test("3.0", "0x3.0#2", "2", "1.5", "0x1.8#2"); + test("3.0", "0x3.00#10", "2", "1.5", "0x1.800#10"); + test("3.0", "0x3.00#10", "3/2", "2.0", "0x2.00#10"); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + "2.0", + "0x2.0000000000000000000000000#100", + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + "2.0943951023931953", + "0x2.182a4705ae6ca#53", + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + "-2.0943951023931953", + "-0x2.182a4705ae6ca#53", + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + "-2.0943951023931953", + "-0x2.182a4705ae6ca#53", + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + "2.0943951023931953", + "0x2.182a4705ae6ca#53", + ); +} + +#[test] +fn test_div_rational_prec() { + let test = |s, s_hex, t, prec, out: &str, out_hex: &str, o_out| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + let y = Rational::from_str(t).unwrap(); + + let (quotient, o) = x.clone().div_rational_prec(y.clone(), prec); + assert!(quotient.is_valid()); + assert_eq!(o, o_out); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let (quotient_alt, o_alt) = x.clone().div_rational_prec_val_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = x.div_rational_prec_ref_val(y.clone(), prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = x.div_rational_prec_ref_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_rational_prec_assign(y.clone(), prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_rational_prec_assign_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_direct(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (rug_quotient, rug_o) = rug_div_rational_prec( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient) + ); + assert_eq!(rug_o, o); + }; + test("NaN", "NaN", "123", 1, "NaN", "NaN", Equal); + test( + "Infinity", "Infinity", "123", 1, "Infinity", "Infinity", Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + test("NaN", "NaN", "0", 1, "NaN", "NaN", Equal); + test( + "Infinity", "Infinity", "0", 1, "Infinity", "Infinity", Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + + test("0.0", "0x0.0", "0", 1, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", 1, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "123", 1, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "123", 1, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", 1, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", 1, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", 1, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", 1, "-0.0", "-0x0.0", Equal); + test("123.0", "0x7b.0#7", "1", 1, "1.0e2", "0x8.0E+1#1", Greater); + test("123.0", "0x7b.0#7", "1", 10, "123.0", "0x7b.0#10", Equal); + test("123.0", "0x7b.0#7", "0", 1, "Infinity", "Infinity", Equal); + test( + "-123.0", + "-0x7b.0#7", + "0", + 1, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + 10, + "-Infinity", + "-Infinity", + Equal, + ); + + test("1.0", "0x1.0#1", "2", 1, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", 10, "0.5", "0x0.800#10", Equal); + test("1.0", "0x1.000#10", "3/2", 1, "0.5", "0x0.8#1", Less); + test( + "1.0", + "0x1.000#10", + "3/2", + 10, + "0.667", + "0x0.aac#10", + Greater, + ); + + test("3.0", "0x3.0#2", "2", 1, "2.0", "0x2.0#1", Greater); + test("3.0", "0x3.0#2", "2", 10, "1.5", "0x1.800#10", Equal); + test("3.0", "0x3.00#10", "3/2", 1, "2.0", "0x2.0#1", Equal); + test("3.0", "0x3.00#10", "3/2", 10, "2.0", "0x2.00#10", Equal); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 1, + "2.0", + "0x2.0#1", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 10, + "2.094", + "0x2.18#10", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 1, + "-2.0", + "-0x2.0#1", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 10, + "-2.094", + "-0x2.18#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 1, + "-2.0", + "-0x2.0#1", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 10, + "-2.094", + "-0x2.18#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 1, + "2.0", + "0x2.0#1", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 10, + "2.094", + "0x2.18#10", + Less, + ); +} + +#[test] +fn div_rational_prec_fail() { + assert_panic!(Float::NAN.div_rational_prec(Rational::ZERO, 0)); + assert_panic!(Float::NAN.div_rational_prec_val_ref(&Rational::ZERO, 0)); + assert_panic!(Float::NAN.div_rational_prec_ref_val(Rational::ZERO, 0)); + assert_panic!(Float::NAN.div_rational_prec_ref_ref(&Rational::ZERO, 0)); + assert_panic!({ + let mut x = Float::NAN; + x.div_rational_prec_assign(Rational::ZERO, 0) + }); + assert_panic!({ + let mut x = Float::NAN; + x.div_rational_prec_assign_ref(&Rational::ZERO, 0) + }); +} + +#[test] +fn test_div_rational_round() { + let test = |s, s_hex, t, rm, out: &str, out_hex: &str, o_out| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + let y = Rational::from_str(t).unwrap(); + + let (quotient, o) = x.clone().div_rational_round(y.clone(), rm); + assert!(quotient.is_valid()); + assert_eq!(o, o_out); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let (quotient_alt, o_alt) = x.clone().div_rational_round_val_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = x.div_rational_round_ref_val(y.clone(), rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = x.div_rational_round_ref_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_rational_round_assign(y.clone(), rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_rational_round_assign_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_div_rational_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient) + ); + assert_eq!(rug_o, o); + } + + let (quotient_alt, o_alt) = + div_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + }; + test("NaN", "NaN", "123", Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", Exact, "NaN", "NaN", Equal); + + test( + "Infinity", "Infinity", "123", Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", Exact, "Infinity", "Infinity", Equal, + ); + + test( + "-Infinity", + "-Infinity", + "123", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test("NaN", "NaN", "0", Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", Exact, "NaN", "NaN", Equal); + + test( + "Infinity", "Infinity", "0", Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", Exact, "Infinity", "Infinity", Equal, + ); + + test( + "-Infinity", + "-Infinity", + "0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test("0.0", "0x0.0", "0", Floor, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", Ceiling, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", Down, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", Up, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", Nearest, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", Exact, "NaN", "NaN", Equal); + + test("-0.0", "-0x0.0", "0", Floor, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", Ceiling, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", Down, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", Up, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", Nearest, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", Exact, "NaN", "NaN", Equal); + + test("0.0", "0x0.0", "123", Floor, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", Ceiling, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", Down, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", Up, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", Nearest, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", Exact, "0.0", "0x0.0", Equal); + + test("-0.0", "-0x0.0", "123", Floor, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", Ceiling, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", Down, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", Up, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", Nearest, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", Exact, "-0.0", "-0x0.0", Equal); + + test("0.0", "0x0.0", "-123", Floor, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", Ceiling, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", Down, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", Up, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", Nearest, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", Exact, "-0.0", "-0x0.0", Equal); + + test("-0.0", "-0x0.0", "-123", Floor, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", Ceiling, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", Down, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", Up, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", Nearest, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", Exact, "0.0", "0x0.0", Equal); + + test("0.0", "0x0.0", "1/3", Floor, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", Ceiling, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", Down, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", Up, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", Nearest, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", Exact, "0.0", "0x0.0", Equal); + + test("-0.0", "-0x0.0", "1/3", Floor, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", Ceiling, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", Down, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", Up, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", Nearest, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", Exact, "-0.0", "-0x0.0", Equal); + + test("123.0", "0x7b.0#7", "1", Floor, "123.0", "0x7b.0#7", Equal); + test( + "123.0", "0x7b.0#7", "1", Ceiling, "123.0", "0x7b.0#7", Equal, + ); + test("123.0", "0x7b.0#7", "1", Down, "123.0", "0x7b.0#7", Equal); + test("123.0", "0x7b.0#7", "1", Up, "123.0", "0x7b.0#7", Equal); + test( + "123.0", "0x7b.0#7", "1", Nearest, "123.0", "0x7b.0#7", Equal, + ); + test("123.0", "0x7b.0#7", "1", Exact, "123.0", "0x7b.0#7", Equal); + + test( + "123.0", "0x7b.0#7", "0", Floor, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0", Down, "Infinity", "Infinity", Equal, + ); + test("123.0", "0x7b.0#7", "0", Up, "Infinity", "Infinity", Equal); + test( + "123.0", "0x7b.0#7", "0", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0", Exact, "Infinity", "Infinity", Equal, + ); + + test( + "-123.0", + "-0x7b.0#7", + "0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test("1.0", "0x1.0#1", "2", Floor, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", Ceiling, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", Down, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", Up, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", Nearest, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", Exact, "0.5", "0x0.8#1", Equal); + + test( + "1.0", + "0x1.000#10", + "3/2", + Floor, + "0.666", + "0x0.aa8#10", + Less, + ); + test( + "1.0", + "0x1.000#10", + "3/2", + Ceiling, + "0.667", + "0x0.aac#10", + Greater, + ); + test( + "1.0", + "0x1.000#10", + "3/2", + Down, + "0.666", + "0x0.aa8#10", + Less, + ); + test( + "1.0", + "0x1.000#10", + "3/2", + Up, + "0.667", + "0x0.aac#10", + Greater, + ); + test( + "1.0", + "0x1.000#10", + "3/2", + Nearest, + "0.667", + "0x0.aac#10", + Greater, + ); + + test( + "1.0", + "0x1.0000000000000000000000000#100", + "3/2", + Floor, + "0.666666666666666666666666666666", + "0x0.aaaaaaaaaaaaaaaaaaaaaaaaa#100", + Less, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + "3/2", + Ceiling, + "0.666666666666666666666666666667", + "0x0.aaaaaaaaaaaaaaaaaaaaaaaab#100", + Greater, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + "3/2", + Down, + "0.666666666666666666666666666666", + "0x0.aaaaaaaaaaaaaaaaaaaaaaaaa#100", + Less, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + "3/2", + Up, + "0.666666666666666666666666666667", + "0x0.aaaaaaaaaaaaaaaaaaaaaaaab#100", + Greater, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + "3/2", + Nearest, + "0.666666666666666666666666666667", + "0x0.aaaaaaaaaaaaaaaaaaaaaaaab#100", + Greater, + ); + + test("3.0", "0x3.0#2", "2", Floor, "1.5", "0x1.8#2", Equal); + test("3.0", "0x3.0#2", "2", Ceiling, "1.5", "0x1.8#2", Equal); + test("3.0", "0x3.0#2", "2", Down, "1.5", "0x1.8#2", Equal); + test("3.0", "0x3.0#2", "2", Up, "1.5", "0x1.8#2", Equal); + test("3.0", "0x3.0#2", "2", Nearest, "1.5", "0x1.8#2", Equal); + test("3.0", "0x3.0#2", "2", Exact, "1.5", "0x1.8#2", Equal); + + test("3.0", "0x3.00#10", "3/2", Floor, "2.0", "0x2.00#10", Equal); + test( + "3.0", + "0x3.00#10", + "3/2", + Ceiling, + "2.0", + "0x2.00#10", + Equal, + ); + test("3.0", "0x3.00#10", "3/2", Down, "2.0", "0x2.00#10", Equal); + test("3.0", "0x3.00#10", "3/2", Up, "2.0", "0x2.00#10", Equal); + test( + "3.0", + "0x3.00#10", + "3/2", + Nearest, + "2.0", + "0x2.00#10", + Equal, + ); + test("3.0", "0x3.00#10", "3/2", Exact, "2.0", "0x2.00#10", Equal); + + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + Floor, + "2.0", + "0x2.0000000000000000000000000#100", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + Ceiling, + "2.0", + "0x2.0000000000000000000000000#100", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + Down, + "2.0", + "0x2.0000000000000000000000000#100", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + Up, + "2.0", + "0x2.0000000000000000000000000#100", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + Nearest, + "2.0", + "0x2.0000000000000000000000000#100", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + Exact, + "2.0", + "0x2.0000000000000000000000000#100", + Equal, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + Floor, + "2.0943951023931953", + "0x2.182a4705ae6ca#53", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + Ceiling, + "2.0943951023931957", + "0x2.182a4705ae6cc#53", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + Down, + "2.0943951023931953", + "0x2.182a4705ae6ca#53", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + Up, + "2.0943951023931957", + "0x2.182a4705ae6cc#53", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + Nearest, + "2.0943951023931953", + "0x2.182a4705ae6ca#53", + Less, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + Floor, + "-2.0943951023931957", + "-0x2.182a4705ae6cc#53", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + Ceiling, + "-2.0943951023931953", + "-0x2.182a4705ae6ca#53", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + Down, + "-2.0943951023931953", + "-0x2.182a4705ae6ca#53", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + Up, + "-2.0943951023931957", + "-0x2.182a4705ae6cc#53", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + Nearest, + "-2.0943951023931953", + "-0x2.182a4705ae6ca#53", + Greater, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + Floor, + "-2.0943951023931957", + "-0x2.182a4705ae6cc#53", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + Ceiling, + "-2.0943951023931953", + "-0x2.182a4705ae6ca#53", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + Down, + "-2.0943951023931953", + "-0x2.182a4705ae6ca#53", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + Up, + "-2.0943951023931957", + "-0x2.182a4705ae6cc#53", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + Nearest, + "-2.0943951023931953", + "-0x2.182a4705ae6ca#53", + Greater, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + Floor, + "2.0943951023931953", + "0x2.182a4705ae6ca#53", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + Ceiling, + "2.0943951023931957", + "0x2.182a4705ae6cc#53", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + Down, + "2.0943951023931953", + "0x2.182a4705ae6ca#53", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + Up, + "2.0943951023931957", + "0x2.182a4705ae6cc#53", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + Nearest, + "2.0943951023931953", + "0x2.182a4705ae6ca#53", + Less, + ); +} + +#[test] +fn div_rational_round_fail() { + const THREE: Rational = Rational::const_from_unsigned(3); + assert_panic!(Float::ONE.div_rational_round(THREE, Exact)); + assert_panic!(Float::ONE.div_rational_round_val_ref(&THREE, Exact)); + assert_panic!(Float::ONE.div_rational_round_ref_val(THREE, Exact)); + assert_panic!(Float::ONE.div_rational_round_ref_ref(&THREE, Exact)); + assert_panic!({ + let mut x = Float::ONE; + x.div_rational_round_assign(THREE, Exact) + }); + assert_panic!({ + let mut x = Float::ONE; + x.div_rational_round_assign_ref(&THREE, Exact) + }); +} + +#[test] +fn test_div_rational_prec_round() { + let test = |s, s_hex, t, prec, rm, out: &str, out_hex: &str, o_out| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + let y = Rational::from_str(t).unwrap(); + + let (quotient, o) = x.clone().div_rational_prec_round(y.clone(), prec, rm); + assert!(quotient.is_valid()); + assert_eq!(o, o_out); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let (quotient_alt, o_alt) = x.clone().div_rational_prec_round_val_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_val(y.clone(), prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_rational_prec_round_assign(y.clone(), prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.div_rational_prec_round_assign_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_naive_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_naive_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_naive_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_direct(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_direct_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_direct_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_direct_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_div_rational_prec_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient) + ); + assert_eq!(rug_o, o); + } + }; + test("NaN", "NaN", "123", 1, Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", 1, Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", 1, Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", 1, Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", 1, Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "123", 1, Exact, "NaN", "NaN", Equal); + + test( + "Infinity", "Infinity", "123", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "123", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "-Infinity", + "-Infinity", + "123", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "123", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test("NaN", "NaN", "0", 1, Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", 1, Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", 1, Down, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", 1, Up, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", 1, Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", "0", 1, Exact, "NaN", "NaN", Equal); + + test( + "Infinity", "Infinity", "0", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "Infinity", "Infinity", "0", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "-Infinity", + "-Infinity", + "0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-Infinity", + "-Infinity", + "0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test("0.0", "0x0.0", "0", 1, Floor, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", 1, Ceiling, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", 1, Down, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", 1, Up, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", 1, Nearest, "NaN", "NaN", Equal); + test("0.0", "0x0.0", "0", 1, Exact, "NaN", "NaN", Equal); + + test("-0.0", "-0x0.0", "0", 1, Floor, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", 1, Ceiling, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", 1, Down, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", 1, Up, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", 1, Nearest, "NaN", "NaN", Equal); + test("-0.0", "-0x0.0", "0", 1, Exact, "NaN", "NaN", Equal); + + test("0.0", "0x0.0", "123", 1, Floor, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", 1, Ceiling, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", 1, Down, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", 1, Up, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", 1, Nearest, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "123", 1, Exact, "0.0", "0x0.0", Equal); + + test("-0.0", "-0x0.0", "123", 1, Floor, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", 1, Ceiling, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", 1, Down, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", 1, Up, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", 1, Nearest, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "123", 1, Exact, "-0.0", "-0x0.0", Equal); + + test("0.0", "0x0.0", "-123", 1, Floor, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", 1, Ceiling, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", 1, Down, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", 1, Up, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", 1, Nearest, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", "-123", 1, Exact, "-0.0", "-0x0.0", Equal); + + test("-0.0", "-0x0.0", "-123", 1, Floor, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", 1, Ceiling, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", 1, Down, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", 1, Up, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", 1, Nearest, "0.0", "0x0.0", Equal); + test("-0.0", "-0x0.0", "-123", 1, Exact, "0.0", "0x0.0", Equal); + + test("0.0", "0x0.0", "1/3", 1, Floor, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", 1, Ceiling, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", 1, Down, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", 1, Up, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", 1, Nearest, "0.0", "0x0.0", Equal); + test("0.0", "0x0.0", "1/3", 1, Exact, "0.0", "0x0.0", Equal); + + test("-0.0", "-0x0.0", "1/3", 1, Floor, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", 1, Ceiling, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", 1, Down, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", 1, Up, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", 1, Nearest, "-0.0", "-0x0.0", Equal); + test("-0.0", "-0x0.0", "1/3", 1, Exact, "-0.0", "-0x0.0", Equal); + + test( + "123.0", + "0x7b.0#7", + "1", + 1, + Floor, + "6.0e1", + "0x4.0E+1#1", + Less, + ); + test( + "123.0", + "0x7b.0#7", + "1", + 1, + Ceiling, + "1.0e2", + "0x8.0E+1#1", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + "1", + 1, + Down, + "6.0e1", + "0x4.0E+1#1", + Less, + ); + test( + "123.0", + "0x7b.0#7", + "1", + 1, + Up, + "1.0e2", + "0x8.0E+1#1", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + "1", + 1, + Nearest, + "1.0e2", + "0x8.0E+1#1", + Greater, + ); + + test( + "123.0", "0x7b.0#7", "0", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "123.0", "0x7b.0#7", "0", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "-123.0", + "-0x7b.0#7", + "0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123.0", + "-0x7b.0#7", + "0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test("1.0", "0x1.0#1", "2", 1, Floor, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", 1, Ceiling, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", 1, Down, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", 1, Up, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", 1, Nearest, "0.5", "0x0.8#1", Equal); + test("1.0", "0x1.0#1", "2", 1, Exact, "0.5", "0x0.8#1", Equal); + + test("1.0", "0x1.0#1", "2", 10, Floor, "0.5", "0x0.800#10", Equal); + test( + "1.0", + "0x1.0#1", + "2", + 10, + Ceiling, + "0.5", + "0x0.800#10", + Equal, + ); + test("1.0", "0x1.0#1", "2", 10, Down, "0.5", "0x0.800#10", Equal); + test("1.0", "0x1.0#1", "2", 10, Up, "0.5", "0x0.800#10", Equal); + test( + "1.0", + "0x1.0#1", + "2", + 10, + Nearest, + "0.5", + "0x0.800#10", + Equal, + ); + test("1.0", "0x1.0#1", "2", 10, Exact, "0.5", "0x0.800#10", Equal); + + test("1.0", "0x1.000#10", "3/2", 1, Floor, "0.5", "0x0.8#1", Less); + test( + "1.0", + "0x1.000#10", + "3/2", + 1, + Ceiling, + "1.0", + "0x1.0#1", + Greater, + ); + test("1.0", "0x1.000#10", "3/2", 1, Down, "0.5", "0x0.8#1", Less); + test("1.0", "0x1.000#10", "3/2", 1, Up, "1.0", "0x1.0#1", Greater); + test( + "1.0", + "0x1.000#10", + "3/2", + 1, + Nearest, + "0.5", + "0x0.8#1", + Less, + ); + + test( + "1.0", + "0x1.000#10", + "3/2", + 10, + Floor, + "0.666", + "0x0.aa8#10", + Less, + ); + test( + "1.0", + "0x1.000#10", + "3/2", + 10, + Ceiling, + "0.667", + "0x0.aac#10", + Greater, + ); + test( + "1.0", + "0x1.000#10", + "3/2", + 10, + Down, + "0.666", + "0x0.aa8#10", + Less, + ); + test( + "1.0", + "0x1.000#10", + "3/2", + 10, + Up, + "0.667", + "0x0.aac#10", + Greater, + ); + test( + "1.0", + "0x1.000#10", + "3/2", + 10, + Nearest, + "0.667", + "0x0.aac#10", + Greater, + ); + + test("3.0", "0x3.0#2", "2", 1, Floor, "1.0", "0x1.0#1", Less); + test("3.0", "0x3.0#2", "2", 1, Ceiling, "2.0", "0x2.0#1", Greater); + test("3.0", "0x3.0#2", "2", 1, Down, "1.0", "0x1.0#1", Less); + test("3.0", "0x3.0#2", "2", 1, Up, "2.0", "0x2.0#1", Greater); + test("3.0", "0x3.0#2", "2", 1, Nearest, "2.0", "0x2.0#1", Greater); + + test("3.0", "0x3.00#10", "3/2", 1, Floor, "2.0", "0x2.0#1", Equal); + test( + "3.0", + "0x3.00#10", + "3/2", + 1, + Ceiling, + "2.0", + "0x2.0#1", + Equal, + ); + test("3.0", "0x3.00#10", "3/2", 1, Down, "2.0", "0x2.0#1", Equal); + test("3.0", "0x3.00#10", "3/2", 1, Up, "2.0", "0x2.0#1", Equal); + test( + "3.0", + "0x3.00#10", + "3/2", + 1, + Nearest, + "2.0", + "0x2.0#1", + Equal, + ); + test("3.0", "0x3.00#10", "3/2", 1, Exact, "2.0", "0x2.0#1", Equal); + + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + 10, + Floor, + "2.0", + "0x2.00#10", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + 10, + Ceiling, + "2.0", + "0x2.00#10", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + 10, + Down, + "2.0", + "0x2.00#10", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + 10, + Up, + "2.0", + "0x2.00#10", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + 10, + Nearest, + "2.0", + "0x2.00#10", + Equal, + ); + test( + "3.0", + "0x3.0000000000000000000000000#100", + "3/2", + 10, + Exact, + "2.0", + "0x2.00#10", + Equal, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 1, + Floor, + "2.0", + "0x2.0#1", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 1, + Ceiling, + "4.0", + "0x4.0#1", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 1, + Down, + "2.0", + "0x2.0#1", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 1, + Up, + "4.0", + "0x4.0#1", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 1, + Nearest, + "2.0", + "0x2.0#1", + Less, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 10, + Floor, + "2.094", + "0x2.18#10", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 10, + Ceiling, + "2.098", + "0x2.19#10", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 10, + Down, + "2.094", + "0x2.18#10", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 10, + Up, + "2.098", + "0x2.19#10", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "3/2", + 10, + Nearest, + "2.094", + "0x2.18#10", + Less, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 1, + Floor, + "-4.0", + "-0x4.0#1", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 1, + Ceiling, + "-2.0", + "-0x2.0#1", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 1, + Down, + "-2.0", + "-0x2.0#1", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 1, + Up, + "-4.0", + "-0x4.0#1", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 1, + Nearest, + "-2.0", + "-0x2.0#1", + Greater, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 10, + Floor, + "-2.098", + "-0x2.19#10", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 10, + Ceiling, + "-2.094", + "-0x2.18#10", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 10, + Down, + "-2.094", + "-0x2.18#10", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 10, + Up, + "-2.098", + "-0x2.19#10", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-3/2", + 10, + Nearest, + "-2.094", + "-0x2.18#10", + Greater, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 1, + Floor, + "-4.0", + "-0x4.0#1", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 1, + Ceiling, + "-2.0", + "-0x2.0#1", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 1, + Down, + "-2.0", + "-0x2.0#1", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 1, + Up, + "-4.0", + "-0x4.0#1", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 1, + Nearest, + "-2.0", + "-0x2.0#1", + Greater, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 10, + Floor, + "-2.098", + "-0x2.19#10", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 10, + Ceiling, + "-2.094", + "-0x2.18#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 10, + Down, + "-2.094", + "-0x2.18#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 10, + Up, + "-2.098", + "-0x2.19#10", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "3/2", + 10, + Nearest, + "-2.094", + "-0x2.18#10", + Greater, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 1, + Floor, + "2.0", + "0x2.0#1", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 1, + Ceiling, + "4.0", + "0x4.0#1", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 1, + Down, + "2.0", + "0x2.0#1", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 1, + Up, + "4.0", + "0x4.0#1", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 1, + Nearest, + "2.0", + "0x2.0#1", + Less, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 10, + Floor, + "2.094", + "0x2.18#10", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 10, + Ceiling, + "2.098", + "0x2.19#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 10, + Down, + "2.094", + "0x2.18#10", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 10, + Up, + "2.098", + "0x2.19#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-3/2", + 10, + Nearest, + "2.094", + "0x2.18#10", + Less, + ); +} + +#[test] +fn div_rational_prec_round_fail() { + assert_panic!(Float::one_prec(1).div_rational_prec_round(Rational::ONE, 0, Exact)); + assert_panic!(Float::one_prec(1).div_rational_prec_round( + Rational::from_unsigneds(5u32, 8), + 1, + Exact + )); + assert_panic!(Float::one_prec(1).div_rational_prec_round_val_ref( + &Rational::from_unsigneds(5u32, 8), + 1, + Exact + )); + assert_panic!(Float::one_prec(1).div_rational_prec_round_ref_val( + Rational::from_unsigneds(5u32, 8), + 1, + Exact + )); + assert_panic!(Float::one_prec(1).div_rational_prec_round_ref_ref( + &Rational::from_unsigneds(5u32, 8), + 1, + Exact + )); + assert_panic!({ + let mut x = Float::one_prec(1); + x.div_rational_prec_round_assign(Rational::from_unsigneds(5u32, 8), 1, Exact) + }); + assert_panic!({ + let mut x = Float::one_prec(1); + x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(5u32, 8), 1, Exact) + }); +} + +#[test] +fn test_rational_div_float() { + let test = |s, t, t_hex, out: &str, out_hex: &str| { + let x = Rational::from_str(s).unwrap(); + + let y = parse_hex_string(t_hex); + assert_eq!(y.to_string(), t); + + let quotient = x.clone() / y.clone(); + assert!(quotient.is_valid()); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let quotient_alt = x.clone() / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + let quotient_alt = &x / y.clone(); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + let quotient_alt = &x / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + + assert_eq!( + ComparableFloatRef(&Float::from(&rug_rational_div_float( + &rug::Rational::from(&x), + &rug::Float::exact_from(&y), + ))), + ComparableFloatRef("ient) + ); + + let quotient_alt = rational_div_float_prec_round_naive( + x.clone(), + y.clone(), + y.significant_bits(), + Nearest, + ) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let quotient_alt = rational_div_float_prec_round_direct( + x.clone(), + y.clone(), + y.significant_bits(), + Nearest, + ) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + }; + test("123", "NaN", "NaN", "NaN", "NaN"); + test("123", "Infinity", "Infinity", "0.0", "0x0.0"); + test("123", "-Infinity", "-Infinity", "-0.0", "-0x0.0"); + test("0", "NaN", "NaN", "NaN", "NaN"); + test("0", "Infinity", "Infinity", "0.0", "0x0.0"); + test("0", "-Infinity", "-Infinity", "-0.0", "-0x0.0"); + + test("0", "0.0", "0x0.0", "NaN", "NaN"); + test("0", "-0.0", "-0x0.0", "NaN", "NaN"); + test("123", "0.0", "0x0.0", "Infinity", "Infinity"); + test("123", "-0.0", "-0x0.0", "-Infinity", "-Infinity"); + test("-123", "0.0", "0x0.0", "-Infinity", "-Infinity"); + test("-123", "-0.0", "-0x0.0", "Infinity", "Infinity"); + test("1/3", "0.0", "0x0.0", "Infinity", "Infinity"); + test("1/3", "-0.0", "-0x0.0", "-Infinity", "-Infinity"); + test("-1/3", "0.0", "0x0.0", "-Infinity", "-Infinity"); + test("-1/3", "-0.0", "-0x0.0", "Infinity", "Infinity"); + test("1", "123.0", "0x7b.0#7", "0.0082", "0x0.0218#7"); + test("0", "123.0", "0x7b.0#7", "0.0", "0x0.0"); + test("0", "-123.0", "-0x7b.0#7", "-0.0", "-0x0.0"); + + test("2", "1.0", "0x1.0#1", "2.0", "0x2.0#1"); + test("2", "1.0", "0x1.0#2", "2.0", "0x2.0#2"); + test("2", "1.0", "0x1.000#10", "2.0", "0x2.00#10"); + test("3/2", "1.0", "0x1.000#10", "1.5", "0x1.800#10"); + + test("2", "3.0", "0x3.0#2", "0.8", "0x0.c#2"); + test("2", "3.0", "0x3.00#10", "0.667", "0x0.aac#10"); + test("3/2", "3.0", "0x3.00#10", "0.5", "0x0.800#10"); + + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "0.47746482927568601", + "0x0.7a3b2292bab310#53", + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-0.47746482927568601", + "-0x0.7a3b2292bab310#53", + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "-0.47746482927568601", + "-0x0.7a3b2292bab310#53", + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "0.47746482927568601", + "0x0.7a3b2292bab310#53", + ); +} + +#[test] +fn test_rational_div_float_prec() { + let test = |s, t, t_hex, prec, out: &str, out_hex: &str, o_out| { + let x = Rational::from_str(s).unwrap(); + let y = parse_hex_string(t_hex); + assert_eq!(y.to_string(), t); + + let (quotient, o) = Float::rational_div_float_prec(x.clone(), y.clone(), prec); + assert!(quotient.is_valid()); + assert_eq!(o, o_out); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let (quotient_alt, o_alt) = Float::rational_div_float_prec_val_ref(x.clone(), &y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = Float::rational_div_float_prec_ref_val(&x, y.clone(), prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = Float::rational_div_float_prec_ref_ref(&x, &y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (rug_quotient, rug_o) = rug_rational_div_float_prec( + &rug::Rational::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient) + ); + assert_eq!(rug_o, o); + }; + test("123", "NaN", "NaN", 1, "NaN", "NaN", Equal); + test("123", "Infinity", "Infinity", 1, "0.0", "0x0.0", Equal); + test("123", "-Infinity", "-Infinity", 1, "-0.0", "-0x0.0", Equal); + test("0", "NaN", "NaN", 1, "NaN", "NaN", Equal); + test("0", "Infinity", "Infinity", 1, "0.0", "0x0.0", Equal); + test("0", "-Infinity", "-Infinity", 1, "-0.0", "-0x0.0", Equal); + + test("0", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); + test("123", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal); + test("123", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal); + test("-123", "0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal); + test("-123", "-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal); + test("1/3", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal); + test("1/3", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal); + test("-1/3", "0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal); + test("-1/3", "-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal); + test("1", "123.0", "0x7b.0#7", 1, "0.008", "0x0.02#1", Less); + test( + "1", + "123.0", + "0x7b.0#7", + 10, + "0.00813", + "0x0.0215#10", + Greater, + ); + test("0", "123.0", "0x7b.0#7", 1, "0.0", "0x0.0", Equal); + test("0", "-123.0", "-0x7b.0#7", 1, "-0.0", "-0x0.0", Equal); + + test("2", "1.0", "0x1.0#1", 1, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", 10, "2.0", "0x2.00#10", Equal); + test("3/2", "1.0", "0x1.000#10", 1, "2.0", "0x2.0#1", Greater); + test("3/2", "1.0", "0x1.000#10", 10, "1.5", "0x1.800#10", Equal); + + test("2", "3.0", "0x3.0#2", 1, "0.5", "0x0.8#1", Less); + test("2", "3.0", "0x3.0#2", 10, "0.667", "0x0.aac#10", Greater); + test("3/2", "3.0", "0x3.00#10", 1, "0.5", "0x0.8#1", Equal); + test("3/2", "3.0", "0x3.00#10", 10, "0.5", "0x0.800#10", Equal); + + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + "0.4775", + "0x0.7a4#10", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + "-0.4775", + "-0x0.7a4#10", + Less, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + "-0.4775", + "-0x0.7a4#10", + Less, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + "0.4775", + "0x0.7a4#10", + Greater, + ); +} + +#[test] +fn rational_div_float_prec_fail() { + assert_panic!(Float::rational_div_float_prec( + Rational::ZERO, + Float::NAN, + 0 + )); + assert_panic!(Float::rational_div_float_prec_val_ref( + Rational::ZERO, + &Float::NAN, + 0 + )); + assert_panic!(Float::rational_div_float_prec_ref_val( + &Rational::ZERO, + Float::NAN, + 0 + )); + assert_panic!(Float::rational_div_float_prec_ref_ref( + &Rational::ZERO, + &Float::NAN, + 0 + )); +} + +#[test] +fn test_rational_div_float_round() { + let test = |s, t, t_hex, rm, out: &str, out_hex: &str, o_out| { + let x = Rational::from_str(s).unwrap(); + let y = parse_hex_string(t_hex); + assert_eq!(y.to_string(), t); + + let (quotient, o) = Float::rational_div_float_round(x.clone(), y.clone(), rm); + assert!(quotient.is_valid()); + assert_eq!(o, o_out); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let (quotient_alt, o_alt) = Float::rational_div_float_round_val_ref(x.clone(), &y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = Float::rational_div_float_round_ref_val(&x, y.clone(), rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = Float::rational_div_float_round_ref_ref(&x, &y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive(x.clone(), y.clone(), y.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct(x.clone(), y.clone(), y.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_rational_div_float_round( + &rug::Rational::exact_from(&x), + &rug::Float::exact_from(&y), + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient) + ); + assert_eq!(rug_o, o); + } + }; + test("123", "NaN", "NaN", Floor, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", Down, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", Up, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", Exact, "NaN", "NaN", Equal); + + test("123", "Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal); + test( + "123", "Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal, + ); + test("123", "Infinity", "Infinity", Down, "0.0", "0x0.0", Equal); + test("123", "Infinity", "Infinity", Up, "0.0", "0x0.0", Equal); + test( + "123", "Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal, + ); + test("123", "Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal); + + test( + "123", + "-Infinity", + "-Infinity", + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123", + "-Infinity", + "-Infinity", + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123", + "-Infinity", + "-Infinity", + Down, + "-0.0", + "-0x0.0", + Equal, + ); + test("123", "-Infinity", "-Infinity", Up, "-0.0", "-0x0.0", Equal); + test( + "123", + "-Infinity", + "-Infinity", + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123", + "-Infinity", + "-Infinity", + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test("0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", Down, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", Up, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); + + test("0", "Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal); + test("0", "Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal); + test("0", "Infinity", "Infinity", Down, "0.0", "0x0.0", Equal); + test("0", "Infinity", "Infinity", Up, "0.0", "0x0.0", Equal); + test("0", "Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal); + test("0", "Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal); + + test( + "0", + "-Infinity", + "-Infinity", + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-Infinity", + "-Infinity", + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test("0", "-Infinity", "-Infinity", Down, "-0.0", "-0x0.0", Equal); + test("0", "-Infinity", "-Infinity", Up, "-0.0", "-0x0.0", Equal); + test( + "0", + "-Infinity", + "-Infinity", + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-Infinity", + "-Infinity", + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test("0", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); + + test("0", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); + + test("123", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal); + test( + "123", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, + ); + test("123", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal); + test("123", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal); + test( + "123", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, + ); + test("123", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal); + + test( + "123", + "-0.0", + "-0x0.0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123", + "-0.0", + "-0x0.0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123", + "-0.0", + "-0x0.0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test("123", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal); + test( + "123", + "-0.0", + "-0x0.0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123", + "-0.0", + "-0x0.0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-123", + "0.0", + "0x0.0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123", + "0.0", + "0x0.0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123", + "0.0", + "0x0.0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test("-123", "0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal); + test( + "-123", + "0.0", + "0x0.0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123", + "0.0", + "0x0.0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-123", "-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal, + ); + test( + "-123", "-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "-123", "-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal, + ); + test("-123", "-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal); + test( + "-123", "-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "-123", "-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal, + ); + + test("1/3", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal); + test( + "1/3", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, + ); + test("1/3", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal); + test("1/3", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal); + test( + "1/3", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, + ); + test("1/3", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal); + + test( + "1/3", + "-0.0", + "-0x0.0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "1/3", + "-0.0", + "-0x0.0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "1/3", + "-0.0", + "-0x0.0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test("1/3", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal); + test( + "1/3", + "-0.0", + "-0x0.0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "1/3", + "-0.0", + "-0x0.0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-1/3", + "0.0", + "0x0.0", + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-1/3", + "0.0", + "0x0.0", + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-1/3", + "0.0", + "0x0.0", + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test("-1/3", "0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal); + test( + "-1/3", + "0.0", + "0x0.0", + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-1/3", + "0.0", + "0x0.0", + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-1/3", "-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal, + ); + test( + "-1/3", "-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "-1/3", "-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal, + ); + test("-1/3", "-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal); + test( + "-1/3", "-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal, + ); + test( + "-1/3", "-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal, + ); + + test( + "1", + "123.0", + "0x7b.0#7", + Floor, + "0.0081", + "0x0.0210#7", + Less, + ); + test( + "1", + "123.0", + "0x7b.0#7", + Ceiling, + "0.0082", + "0x0.0218#7", + Greater, + ); + test("1", "123.0", "0x7b.0#7", Down, "0.0081", "0x0.0210#7", Less); + test( + "1", + "123.0", + "0x7b.0#7", + Up, + "0.0082", + "0x0.0218#7", + Greater, + ); + test( + "1", + "123.0", + "0x7b.0#7", + Nearest, + "0.0082", + "0x0.0218#7", + Greater, + ); + + test("0", "123.0", "0x7b.0#7", Floor, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", Ceiling, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", Down, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", Up, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", Nearest, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", Exact, "0.0", "0x0.0", Equal); + + test("0", "-123.0", "-0x7b.0#7", Floor, "-0.0", "-0x0.0", Equal); + test("0", "-123.0", "-0x7b.0#7", Ceiling, "-0.0", "-0x0.0", Equal); + test("0", "-123.0", "-0x7b.0#7", Down, "-0.0", "-0x0.0", Equal); + test("0", "-123.0", "-0x7b.0#7", Up, "-0.0", "-0x0.0", Equal); + test("0", "-123.0", "-0x7b.0#7", Nearest, "-0.0", "-0x0.0", Equal); + test("0", "-123.0", "-0x7b.0#7", Exact, "-0.0", "-0x0.0", Equal); + + test("2", "1.0", "0x1.0#1", Floor, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", Ceiling, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", Down, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", Up, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", Nearest, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", Exact, "2.0", "0x2.0#1", Equal); + + test("2", "1.0", "0x1.0#2", Floor, "2.0", "0x2.0#2", Equal); + test("2", "1.0", "0x1.0#2", Ceiling, "2.0", "0x2.0#2", Equal); + test("2", "1.0", "0x1.0#2", Down, "2.0", "0x2.0#2", Equal); + test("2", "1.0", "0x1.0#2", Up, "2.0", "0x2.0#2", Equal); + test("2", "1.0", "0x1.0#2", Nearest, "2.0", "0x2.0#2", Equal); + test("2", "1.0", "0x1.0#2", Exact, "2.0", "0x2.0#2", Equal); + + test("2", "1.0", "0x1.000#10", Floor, "2.0", "0x2.00#10", Equal); + test("2", "1.0", "0x1.000#10", Ceiling, "2.0", "0x2.00#10", Equal); + test("2", "1.0", "0x1.000#10", Down, "2.0", "0x2.00#10", Equal); + test("2", "1.0", "0x1.000#10", Up, "2.0", "0x2.00#10", Equal); + test("2", "1.0", "0x1.000#10", Nearest, "2.0", "0x2.00#10", Equal); + test("2", "1.0", "0x1.000#10", Exact, "2.0", "0x2.00#10", Equal); + + test( + "3/2", + "1.0", + "0x1.000#10", + Floor, + "1.5", + "0x1.800#10", + Equal, + ); + test( + "3/2", + "1.0", + "0x1.000#10", + Ceiling, + "1.5", + "0x1.800#10", + Equal, + ); + test("3/2", "1.0", "0x1.000#10", Down, "1.5", "0x1.800#10", Equal); + test("3/2", "1.0", "0x1.000#10", Up, "1.5", "0x1.800#10", Equal); + test( + "3/2", + "1.0", + "0x1.000#10", + Nearest, + "1.5", + "0x1.800#10", + Equal, + ); + test( + "3/2", + "1.0", + "0x1.000#10", + Exact, + "1.5", + "0x1.800#10", + Equal, + ); + + test("2", "3.0", "0x3.0#2", Floor, "0.5", "0x0.8#2", Less); + test("2", "3.0", "0x3.0#2", Ceiling, "0.8", "0x0.c#2", Greater); + test("2", "3.0", "0x3.0#2", Down, "0.5", "0x0.8#2", Less); + test("2", "3.0", "0x3.0#2", Up, "0.8", "0x0.c#2", Greater); + test("2", "3.0", "0x3.0#2", Nearest, "0.8", "0x0.c#2", Greater); + + test("2", "3.0", "0x3.00#10", Floor, "0.666", "0x0.aa8#10", Less); + test( + "2", + "3.0", + "0x3.00#10", + Ceiling, + "0.667", + "0x0.aac#10", + Greater, + ); + test("2", "3.0", "0x3.00#10", Down, "0.666", "0x0.aa8#10", Less); + test("2", "3.0", "0x3.00#10", Up, "0.667", "0x0.aac#10", Greater); + test( + "2", + "3.0", + "0x3.00#10", + Nearest, + "0.667", + "0x0.aac#10", + Greater, + ); + + test("3/2", "3.0", "0x3.00#10", Floor, "0.5", "0x0.800#10", Equal); + test( + "3/2", + "3.0", + "0x3.00#10", + Ceiling, + "0.5", + "0x0.800#10", + Equal, + ); + test("3/2", "3.0", "0x3.00#10", Down, "0.5", "0x0.800#10", Equal); + test("3/2", "3.0", "0x3.00#10", Up, "0.5", "0x0.800#10", Equal); + test( + "3/2", + "3.0", + "0x3.00#10", + Nearest, + "0.5", + "0x0.800#10", + Equal, + ); + test("3/2", "3.0", "0x3.00#10", Exact, "0.5", "0x0.800#10", Equal); + + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Floor, + "0.47746482927568601", + "0x0.7a3b2292bab310#53", + Less, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Ceiling, + "0.47746482927568606", + "0x0.7a3b2292bab314#53", + Greater, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Down, + "0.47746482927568601", + "0x0.7a3b2292bab310#53", + Less, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Up, + "0.47746482927568606", + "0x0.7a3b2292bab314#53", + Greater, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Nearest, + "0.47746482927568601", + "0x0.7a3b2292bab310#53", + Less, + ); + + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Floor, + "-0.47746482927568606", + "-0x0.7a3b2292bab314#53", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Ceiling, + "-0.47746482927568601", + "-0x0.7a3b2292bab310#53", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Down, + "-0.47746482927568601", + "-0x0.7a3b2292bab310#53", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Up, + "-0.47746482927568606", + "-0x0.7a3b2292bab314#53", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Nearest, + "-0.47746482927568601", + "-0x0.7a3b2292bab310#53", + Greater, + ); + + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Floor, + "-0.47746482927568606", + "-0x0.7a3b2292bab314#53", + Less, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Ceiling, + "-0.47746482927568601", + "-0x0.7a3b2292bab310#53", + Greater, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Down, + "-0.47746482927568601", + "-0x0.7a3b2292bab310#53", + Greater, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Up, + "-0.47746482927568606", + "-0x0.7a3b2292bab314#53", + Less, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Nearest, + "-0.47746482927568601", + "-0x0.7a3b2292bab310#53", + Greater, + ); + + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Floor, + "0.47746482927568601", + "0x0.7a3b2292bab310#53", + Less, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Ceiling, + "0.47746482927568606", + "0x0.7a3b2292bab314#53", + Greater, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Down, + "0.47746482927568601", + "0x0.7a3b2292bab310#53", + Less, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Up, + "0.47746482927568606", + "0x0.7a3b2292bab314#53", + Greater, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Nearest, + "0.47746482927568601", + "0x0.7a3b2292bab310#53", + Less, + ); +} + +#[test] +fn rational_div_float_round_fail() { + const THREE: Float = Float::const_from_unsigned(3); + assert_panic!(Float::rational_div_float_round(Rational::ONE, THREE, Exact)); + assert_panic!(Float::rational_div_float_round_val_ref( + Rational::ONE, + &THREE, + Exact + )); + assert_panic!(Float::rational_div_float_round_ref_val( + &Rational::ONE, + THREE, + Exact + )); + assert_panic!(Float::rational_div_float_round_ref_ref( + &Rational::ONE, + &THREE, + Exact + )); +} + +#[test] +fn test_rational_div_float_prec_round() { + let test = |s, t, t_hex, prec, rm, out: &str, out_hex: &str, o_out| { + let x = Rational::from_str(s).unwrap(); + let y = parse_hex_string(t_hex); + assert_eq!(y.to_string(), t); + + let (quotient, o) = Float::rational_div_float_prec_round(x.clone(), y.clone(), prec, rm); + assert!(quotient.is_valid()); + assert_eq!(o, o_out); + + assert_eq!(quotient.to_string(), out); + assert_eq!(to_hex_string("ient), out_hex); + + let (quotient_alt, o_alt) = + Float::rational_div_float_prec_round_val_ref(x.clone(), &y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + Float::rational_div_float_prec_round_ref_val(&x, y.clone(), prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient), + ComparableFloatRef("ient_alt) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = rational_div_float_prec_round_naive_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = rational_div_float_prec_round_direct_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_rational_div_float_prec_round( + &rug::Rational::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient) + ); + assert_eq!(rug_o, o); + } + }; + test("123", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); + test("123", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); + + test( + "123", "Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal, + ); + test( + "123", "Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, + ); + test( + "123", "Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal, + ); + test("123", "Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal); + test( + "123", "Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal, + ); + test( + "123", "Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal, + ); + + test( + "123", + "-Infinity", + "-Infinity", + 1, + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123", + "-Infinity", + "-Infinity", + 1, + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123", + "-Infinity", + "-Infinity", + 1, + Down, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123", + "-Infinity", + "-Infinity", + 1, + Up, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123", + "-Infinity", + "-Infinity", + 1, + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "123", + "-Infinity", + "-Infinity", + 1, + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test("0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); + test("0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); + + test("0", "Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal); + test( + "0", "Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, + ); + test("0", "Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal); + test("0", "Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal); + test( + "0", "Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal, + ); + test("0", "Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal); + + test( + "0", + "-Infinity", + "-Infinity", + 1, + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-Infinity", + "-Infinity", + 1, + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-Infinity", + "-Infinity", + 1, + Down, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-Infinity", + "-Infinity", + 1, + Up, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-Infinity", + "-Infinity", + 1, + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-Infinity", + "-Infinity", + 1, + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test("0", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal); + test("0", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); + + test("0", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal); + test("0", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal); + + test( + "123", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "123", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "123", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, + ); + test("123", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal); + test( + "123", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "123", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "123", + "-0.0", + "-0x0.0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123", + "-0.0", + "-0x0.0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123", + "-0.0", + "-0x0.0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123", + "-0.0", + "-0x0.0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123", + "-0.0", + "-0x0.0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "123", + "-0.0", + "-0x0.0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-123", + "0.0", + "0x0.0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123", + "0.0", + "0x0.0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123", + "0.0", + "0x0.0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123", + "0.0", + "0x0.0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123", + "0.0", + "0x0.0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-123", + "0.0", + "0x0.0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-123", "-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "-123", "-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "-123", "-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "-123", "-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "-123", "-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "-123", "-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "1/3", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "1/3", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "1/3", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, + ); + test("1/3", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal); + test( + "1/3", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "1/3", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "1/3", + "-0.0", + "-0x0.0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "1/3", + "-0.0", + "-0x0.0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "1/3", + "-0.0", + "-0x0.0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "1/3", + "-0.0", + "-0x0.0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "1/3", + "-0.0", + "-0x0.0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "1/3", + "-0.0", + "-0x0.0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-1/3", + "0.0", + "0x0.0", + 1, + Floor, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-1/3", + "0.0", + "0x0.0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-1/3", + "0.0", + "0x0.0", + 1, + Down, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-1/3", + "0.0", + "0x0.0", + 1, + Up, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-1/3", + "0.0", + "0x0.0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test( + "-1/3", + "0.0", + "0x0.0", + 1, + Exact, + "-Infinity", + "-Infinity", + Equal, + ); + + test( + "-1/3", "-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal, + ); + test( + "-1/3", "-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, + ); + test( + "-1/3", "-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal, + ); + test( + "-1/3", "-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal, + ); + test( + "-1/3", "-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, + ); + test( + "-1/3", "-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal, + ); + + test( + "1", "123.0", "0x7b.0#7", 1, Floor, "0.008", "0x0.02#1", Less, + ); + test( + "1", "123.0", "0x7b.0#7", 1, Ceiling, "0.02", "0x0.04#1", Greater, + ); + test("1", "123.0", "0x7b.0#7", 1, Down, "0.008", "0x0.02#1", Less); + test("1", "123.0", "0x7b.0#7", 1, Up, "0.02", "0x0.04#1", Greater); + test( + "1", "123.0", "0x7b.0#7", 1, Nearest, "0.008", "0x0.02#1", Less, + ); + + test( + "1", + "123.0", + "0x7b.0#7", + 10, + Floor, + "0.00812", + "0x0.0214#10", + Less, + ); + test( + "1", + "123.0", + "0x7b.0#7", + 10, + Ceiling, + "0.00813", + "0x0.0215#10", + Greater, + ); + test( + "1", + "123.0", + "0x7b.0#7", + 10, + Down, + "0.00812", + "0x0.0214#10", + Less, + ); + test( + "1", + "123.0", + "0x7b.0#7", + 10, + Up, + "0.00813", + "0x0.0215#10", + Greater, + ); + test( + "1", + "123.0", + "0x7b.0#7", + 10, + Nearest, + "0.00813", + "0x0.0215#10", + Greater, + ); + + test("0", "123.0", "0x7b.0#7", 1, Floor, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", 1, Ceiling, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", 1, Down, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", 1, Up, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", 1, Nearest, "0.0", "0x0.0", Equal); + test("0", "123.0", "0x7b.0#7", 1, Exact, "0.0", "0x0.0", Equal); + + test( + "0", + "-123.0", + "-0x7b.0#7", + 1, + Floor, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-123.0", + "-0x7b.0#7", + 1, + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test("0", "-123.0", "-0x7b.0#7", 1, Down, "-0.0", "-0x0.0", Equal); + test("0", "-123.0", "-0x7b.0#7", 1, Up, "-0.0", "-0x0.0", Equal); + test( + "0", + "-123.0", + "-0x7b.0#7", + 1, + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test( + "0", + "-123.0", + "-0x7b.0#7", + 1, + Exact, + "-0.0", + "-0x0.0", + Equal, + ); + + test("2", "1.0", "0x1.0#1", 1, Floor, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", 1, Ceiling, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", 1, Down, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", 1, Up, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", 1, Nearest, "2.0", "0x2.0#1", Equal); + test("2", "1.0", "0x1.0#1", 1, Exact, "2.0", "0x2.0#1", Equal); + + test("2", "1.0", "0x1.0#1", 10, Floor, "2.0", "0x2.00#10", Equal); + test( + "2", + "1.0", + "0x1.0#1", + 10, + Ceiling, + "2.0", + "0x2.00#10", + Equal, + ); + test("2", "1.0", "0x1.0#1", 10, Down, "2.0", "0x2.00#10", Equal); + test("2", "1.0", "0x1.0#1", 10, Up, "2.0", "0x2.00#10", Equal); + test( + "2", + "1.0", + "0x1.0#1", + 10, + Nearest, + "2.0", + "0x2.00#10", + Equal, + ); + test("2", "1.0", "0x1.0#1", 10, Exact, "2.0", "0x2.00#10", Equal); + + test("3/2", "1.0", "0x1.000#10", 1, Floor, "1.0", "0x1.0#1", Less); + test( + "3/2", + "1.0", + "0x1.000#10", + 1, + Ceiling, + "2.0", + "0x2.0#1", + Greater, + ); + test("3/2", "1.0", "0x1.000#10", 1, Down, "1.0", "0x1.0#1", Less); + test("3/2", "1.0", "0x1.000#10", 1, Up, "2.0", "0x2.0#1", Greater); + test( + "3/2", + "1.0", + "0x1.000#10", + 1, + Nearest, + "2.0", + "0x2.0#1", + Greater, + ); + + test( + "3/2", + "1.0", + "0x1.000#10", + 10, + Floor, + "1.5", + "0x1.800#10", + Equal, + ); + test( + "3/2", + "1.0", + "0x1.000#10", + 10, + Ceiling, + "1.5", + "0x1.800#10", + Equal, + ); + test( + "3/2", + "1.0", + "0x1.000#10", + 10, + Down, + "1.5", + "0x1.800#10", + Equal, + ); + test( + "3/2", + "1.0", + "0x1.000#10", + 10, + Up, + "1.5", + "0x1.800#10", + Equal, + ); + test( + "3/2", + "1.0", + "0x1.000#10", + 10, + Nearest, + "1.5", + "0x1.800#10", + Equal, + ); + test( + "3/2", + "1.0", + "0x1.000#10", + 10, + Exact, + "1.5", + "0x1.800#10", + Equal, + ); + + test("2", "3.0", "0x3.0#2", 1, Floor, "0.5", "0x0.8#1", Less); + test("2", "3.0", "0x3.0#2", 1, Ceiling, "1.0", "0x1.0#1", Greater); + test("2", "3.0", "0x3.0#2", 1, Down, "0.5", "0x0.8#1", Less); + test("2", "3.0", "0x3.0#2", 1, Up, "1.0", "0x1.0#1", Greater); + test("2", "3.0", "0x3.0#2", 1, Nearest, "0.5", "0x0.8#1", Less); + + test( + "2", + "3.0", + "0x3.0#2", + 10, + Floor, + "0.666", + "0x0.aa8#10", + Less, + ); + test( + "2", + "3.0", + "0x3.0#2", + 10, + Ceiling, + "0.667", + "0x0.aac#10", + Greater, + ); + test("2", "3.0", "0x3.0#2", 10, Down, "0.666", "0x0.aa8#10", Less); + test( + "2", + "3.0", + "0x3.0#2", + 10, + Up, + "0.667", + "0x0.aac#10", + Greater, + ); + test( + "2", + "3.0", + "0x3.0#2", + 10, + Nearest, + "0.667", + "0x0.aac#10", + Greater, + ); + + test("3/2", "3.0", "0x3.00#10", 1, Floor, "0.5", "0x0.8#1", Equal); + test( + "3/2", + "3.0", + "0x3.00#10", + 1, + Ceiling, + "0.5", + "0x0.8#1", + Equal, + ); + test("3/2", "3.0", "0x3.00#10", 1, Down, "0.5", "0x0.8#1", Equal); + test("3/2", "3.0", "0x3.00#10", 1, Up, "0.5", "0x0.8#1", Equal); + test( + "3/2", + "3.0", + "0x3.00#10", + 1, + Nearest, + "0.5", + "0x0.8#1", + Equal, + ); + test("3/2", "3.0", "0x3.00#10", 1, Exact, "0.5", "0x0.8#1", Equal); + + test( + "3/2", + "3.0", + "0x3.00#10", + 10, + Floor, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "3/2", + "3.0", + "0x3.00#10", + 10, + Ceiling, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "3/2", + "3.0", + "0x3.00#10", + 10, + Down, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "3/2", + "3.0", + "0x3.00#10", + 10, + Up, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "3/2", + "3.0", + "0x3.00#10", + 10, + Nearest, + "0.5", + "0x0.800#10", + Equal, + ); + test( + "3/2", + "3.0", + "0x3.00#10", + 10, + Exact, + "0.5", + "0x0.800#10", + Equal, + ); + + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Floor, + "0.2", + "0x0.4#1", + Less, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Ceiling, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Down, + "0.2", + "0x0.4#1", + Less, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Up, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Nearest, + "0.5", + "0x0.8#1", + Greater, + ); + + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Floor, + "0.4771", + "0x0.7a2#10", + Less, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Ceiling, + "0.4775", + "0x0.7a4#10", + Greater, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Down, + "0.4771", + "0x0.7a2#10", + Less, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Up, + "0.4775", + "0x0.7a4#10", + Greater, + ); + test( + "3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Nearest, + "0.4775", + "0x0.7a4#10", + Greater, + ); + + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Floor, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Ceiling, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Down, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Up, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Nearest, + "-0.5", + "-0x0.8#1", + Less, + ); + + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Floor, + "-0.4775", + "-0x0.7a4#10", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Ceiling, + "-0.4771", + "-0x0.7a2#10", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Down, + "-0.4771", + "-0x0.7a2#10", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Up, + "-0.4775", + "-0x0.7a4#10", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Nearest, + "-0.4775", + "-0x0.7a4#10", + Less, + ); + + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Floor, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Ceiling, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Down, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Up, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Nearest, + "-0.5", + "-0x0.8#1", + Less, + ); + + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Floor, + "-0.4775", + "-0x0.7a4#10", + Less, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Ceiling, + "-0.4771", + "-0x0.7a2#10", + Greater, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Down, + "-0.4771", + "-0x0.7a2#10", + Greater, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Up, + "-0.4775", + "-0x0.7a4#10", + Less, + ); + test( + "-3/2", + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Nearest, + "-0.4775", + "-0x0.7a4#10", + Less, + ); + + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Floor, + "0.2", + "0x0.4#1", + Less, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Ceiling, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Down, + "0.2", + "0x0.4#1", + Less, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Up, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Nearest, + "0.5", + "0x0.8#1", + Greater, + ); + + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Floor, + "0.4771", + "0x0.7a2#10", + Less, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Ceiling, + "0.4775", + "0x0.7a4#10", + Greater, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Down, + "0.4771", + "0x0.7a2#10", + Less, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Up, + "0.4775", + "0x0.7a4#10", + Greater, + ); + test( + "-3/2", + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Nearest, + "0.4775", + "0x0.7a4#10", + Greater, + ); +} + +#[test] +fn rational_div_float_prec_round_fail() { + assert_panic!(Float::rational_div_float_prec_round( + Rational::ONE, + Float::one_prec(1), + 0, + Floor + )); + assert_panic!(Float::rational_div_float_prec_round( + Rational::ONE, + Float::from(3), + 1, + Exact + )); + assert_panic!(Float::rational_div_float_prec_round_val_ref( + Rational::ONE, + &Float::from(3), + 1, + Exact + )); + assert_panic!(Float::rational_div_float_prec_round_ref_val( + &Rational::ONE, + Float::from(3), + 1, + Exact + )); + assert_panic!(Float::rational_div_float_prec_round_ref_ref( + &Rational::ONE, + &Float::from(3), + 1, + Exact + )); +} + +#[allow(clippy::needless_pass_by_value)] +fn div_prec_round_properties_helper(x: Float, y: Float, prec: u64, rm: RoundingMode) { + let (quotient, o) = x.clone().div_prec_round(y.clone(), prec, rm); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = x.clone().div_prec_round_val_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = x.div_prec_round_ref_val(y.clone(), prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = x.div_prec_round_ref_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_prec_round_assign(y.clone(), prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_prec_round_assign_ref(&y, prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_prec_round_naive(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_div_prec_round( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + } + + if o == Equal && quotient.is_finite() && quotient != 0 { + assert_eq!( + ComparableFloatRef( + "ient + .mul_prec_round_ref_ref(&y, x.significant_bits(), Exact) + .0 + ), + ComparableFloatRef(&x) + ); + assert_eq!( + ComparableFloatRef( + &x.div_prec_round_ref_ref("ient, y.significant_bits(), Exact) + .0 + ), + ComparableFloatRef(&y) + ); + } + + let r_quotient = if quotient.is_finite() && y.is_finite() { + if quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(prec)); + } + let r_quotient = Rational::exact_from(&x) / Rational::exact_from(&y); + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + Some(r_quotient) + } else { + assert_eq!(o, Equal); + None + }; + + match ( + r_quotient.is_some() && *r_quotient.as_ref().unwrap() >= 0u32, + rm, + ) { + (_, Floor) | (true, Down) | (false, Up) => { + assert_ne!(o, Greater); + } + (_, Ceiling) | (true, Up) | (false, Down) => { + assert_ne!(o, Less); + } + (_, Exact) => assert_eq!(o, Equal), + _ => {} + } + + let (mut quotient_alt, mut o_alt) = x.div_prec_round_ref_val(-&y, prec, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(o_alt, o); + + let (mut quotient_alt, mut o_alt) = (-&x).div_prec_round_val_ref(&y, prec, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = (-&x).div_prec_round(-&y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if o == Equal { + for rm in exhaustive_rounding_modes() { + let (s, oo) = x.div_prec_round_ref_ref(&y, prec, rm); + assert_eq!( + ComparableFloat(s.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(oo, Equal); + } + } else { + assert_panic!(x.div_prec_round_ref_ref(&y, prec, Exact)); + } +} + +#[test] +fn div_prec_round_properties() { + float_float_unsigned_rounding_mode_quadruple_gen_var_4().test_properties(|(x, y, prec, rm)| { + div_prec_round_properties_helper(x, y, prec, rm); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + float_float_unsigned_rounding_mode_quadruple_gen_var_4().test_properties_with_config( + &config, + |(x, y, prec, rm)| { + div_prec_round_properties_helper(x, y, prec, rm); + }, + ); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + config.insert("mean_small_n", 2048); + float_float_unsigned_rounding_mode_quadruple_gen_var_4().test_properties_with_config( + &config, + |(x, y, prec, rm)| { + div_prec_round_properties_helper(x, y, prec, rm); + }, + ); + + float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { + let (quotient, o) = x.div_prec_round_ref_val(Float::NAN, prec, rm); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + let (quotient, o) = Float::NAN.div_prec_round_val_ref(&x, prec, rm); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + if !x.is_nan() { + if x.is_finite() { + assert_eq!( + x.div_prec_round_ref_val(Float::INFINITY, prec, rm), + ( + if x.is_sign_positive() { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + Float::INFINITY.div_prec_round_val_ref(&x, prec, rm), + ( + if x.is_sign_positive() { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + x.div_prec_round_ref_val(Float::NEGATIVE_INFINITY, prec, rm), + ( + if x.is_sign_positive() { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_INFINITY.div_prec_round_val_ref(&x, prec, rm), + ( + if x.is_sign_positive() { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }, + Equal + ) + ); + } + if x != 0 { + assert_eq!( + x.div_prec_round_ref_val(Float::ZERO, prec, rm), + ( + if x > 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::ZERO.div_prec_round_val_ref(&x, prec, rm), + ( + if x > 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + x.div_prec_round_ref_val(Float::ZERO, prec, rm), + ( + if x > 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_ZERO.div_prec_round_val_ref(&x, prec, rm), + ( + if x > 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + } + } + if !x.is_negative_zero() { + let (quotient, o) = x.div_prec_round_ref_val(Float::ONE, prec, rm); + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.set_prec_round(prec, rm); + assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); + assert_eq!(o, o_alt); + + if rm != Exact { + let (quotient, o) = Float::ONE.div_prec_round_val_ref(&x, prec, rm); + let (quotient_alt, o_alt) = x.clone().reciprocal_prec_round(prec, rm); + assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); + assert_eq!(o, o_alt); + } + } + }); +} + +fn div_prec_properties_helper(x: Float, y: Float, prec: u64) { + let (quotient, o) = x.clone().div_prec(y.clone(), prec); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = x.clone().div_prec_val_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = x.div_prec_ref_val(y.clone(), prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = x.div_prec_ref_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_prec_assign(y.clone(), prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_prec_assign_ref(&y, prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_prec_round_naive(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if o == Equal && quotient.is_finite() && quotient != 0 { + assert_eq!( + ComparableFloatRef("ient.mul_prec_ref_ref(&y, x.significant_bits()).0), + ComparableFloatRef(&x) + ); + assert_eq!( + ComparableFloatRef(&x.div_prec_ref_ref("ient, y.significant_bits()).0), + ComparableFloatRef(&y) + ); + } + + let (quotient_alt, o_alt) = x.div_prec_round_ref_ref(&y, prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if quotient.is_finite() && y.is_finite() { + if quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(prec)); + } + let r_quotient = Rational::exact_from(&x) / Rational::exact_from(&y); + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + } else { + assert_eq!(o, Equal); + } + + if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { + let (mut quotient_alt, mut o_alt) = x.div_prec_ref_val(-&y, prec); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient), + ); + assert_eq!(o_alt, o); + + let (mut quotient_alt, mut o_alt) = (-&x).div_prec_val_ref(&y, prec); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = (-x).div_prec(-y, prec); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + } +} + +#[test] +fn div_prec_properties() { + float_float_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { + div_prec_properties_helper(x, y, prec); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + float_float_unsigned_triple_gen_var_1().test_properties_with_config(&config, |(x, y, prec)| { + div_prec_properties_helper(x, y, prec); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + config.insert("mean_small_n", 2048); + float_float_unsigned_triple_gen_var_1().test_properties_with_config(&config, |(x, y, prec)| { + div_prec_properties_helper(x, y, prec); + }); + + float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { + let (quotient, o) = x.div_prec_ref_val(Float::NAN, prec); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + let (quotient, o) = Float::NAN.div_prec_val_ref(&x, prec); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + if !x.is_nan() { + if x.is_finite() { + assert_eq!( + x.div_prec_ref_val(Float::INFINITY, prec), + ( + if x.is_sign_positive() { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + Float::INFINITY.div_prec_val_ref(&x, prec), + ( + if x.is_sign_positive() { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + x.div_prec_ref_val(Float::NEGATIVE_INFINITY, prec), + ( + if x.is_sign_positive() { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_INFINITY.div_prec_val_ref(&x, prec), + ( + if x.is_sign_positive() { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }, + Equal + ) + ); + } + if x != 0 { + assert_eq!( + x.div_prec_ref_val(Float::ZERO, prec), + ( + if x > 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::ZERO.div_prec_val_ref(&x, prec), + ( + if x > 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + x.div_prec_ref_val(Float::NEGATIVE_ZERO, prec), + ( + if x > 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_ZERO.div_prec_val_ref(&x, prec), + ( + if x > 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + } + } + if !x.is_negative_zero() { + let (quotient, o) = x.div_prec_ref_val(Float::ONE, prec); + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.set_prec(prec); + assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); + assert_eq!(o, o_alt); + } + }); +} + +#[allow(clippy::needless_pass_by_value)] +fn div_round_properties_helper(x: Float, y: Float, rm: RoundingMode) { + let (quotient, o) = x.clone().div_round(y.clone(), rm); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = x.clone().div_round_val_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let (quotient_alt, o_alt) = x.div_round_ref_val(y.clone(), rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let (quotient_alt, o_alt) = x.div_round_ref_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_round_assign(y.clone(), rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_round_assign_ref(&y, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_prec_round_naive( + x.clone(), + y.clone(), + max(x.significant_bits(), y.significant_bits()), + rm, + ); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = + x.div_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if o == Equal && quotient.is_finite() && quotient != 0 { + assert_eq!(quotient.mul_round_ref_ref(&y, Exact).0, x); + assert_eq!(x.div_round_ref_ref("ient, Exact).0, y); + } + + let r_quotient = if quotient.is_finite() && y.is_finite() { + if x.is_normal() && y.is_normal() && quotient.is_normal() { + assert_eq!( + quotient.get_prec(), + Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) + ); + } + let r_quotient = Rational::exact_from(&x) / Rational::exact_from(&y); + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + Some(r_quotient) + } else { + assert_eq!(o, Equal); + None + }; + + match ( + r_quotient.is_some() && *r_quotient.as_ref().unwrap() >= 0u32, + rm, + ) { + (_, Floor) | (true, Down) | (false, Up) => { + assert_ne!(o, Greater); + } + (_, Ceiling) | (true, Up) | (false, Down) => { + assert_ne!(o, Less); + } + (_, Exact) => assert_eq!(o, Equal), + _ => {} + } + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = + rug_div_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + } + + let (mut quotient_alt, mut o_alt) = x.div_round_ref_val(-&y, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + + let (mut quotient_alt, mut o_alt) = (-&x).div_round_val_ref(&y, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + + let (quotient_alt, o_alt) = (-&x).div_round(-&y, rm); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + if o == Equal { + for rm in exhaustive_rounding_modes() { + let (s, oo) = x.div_round_ref_ref(&y, rm); + assert_eq!( + ComparableFloat(s.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(oo, Equal); + } + } else { + assert_panic!(x.div_round_ref_ref(&y, Exact)); + } +} + +#[test] +fn div_round_properties() { + float_float_rounding_mode_triple_gen_var_23().test_properties(|(x, y, rm)| { + div_round_properties_helper(x, y, rm); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + float_float_rounding_mode_triple_gen_var_23().test_properties_with_config( + &config, + |(x, y, rm)| { + div_round_properties_helper(x, y, rm); + }, + ); + + float_float_rounding_mode_triple_gen_var_24().test_properties(|(x, y, rm)| { + div_round_properties_helper(x, y, rm); + }); + + float_float_rounding_mode_triple_gen_var_25().test_properties(|(x, y, rm)| { + div_round_properties_helper(x, y, rm); + }); + + float_float_rounding_mode_triple_gen_var_26().test_properties(|(x, y, rm)| { + div_round_properties_helper(x, y, rm); + }); + + float_float_rounding_mode_triple_gen_var_27().test_properties(|(x, y, rm)| { + div_round_properties_helper(x, y, rm); + }); + + float_float_rounding_mode_triple_gen_var_28().test_properties(|(x, y, rm)| { + div_round_properties_helper(x, y, rm); + }); + + float_rounding_mode_pair_gen().test_properties(|(x, rm)| { + let (quotient, o) = x.div_round_ref_val(Float::NAN, rm); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + let (quotient, o) = Float::NAN.div_round_val_ref(&x, rm); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + if !x.is_nan() { + if x.is_finite() { + assert_eq!( + x.div_round_ref_val(Float::INFINITY, rm), + ( + if x.is_sign_positive() { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + Float::INFINITY.div_round_val_ref(&x, rm), + ( + if x.is_sign_positive() { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + x.div_round_ref_val(Float::NEGATIVE_INFINITY, rm), + ( + if x.is_sign_positive() { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_INFINITY.div_round_val_ref(&x, rm), + ( + if x.is_sign_positive() { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }, + Equal + ) + ); + } + if x != 0 { + assert_eq!( + x.div_round_ref_val(Float::ZERO, rm), + ( + if x > 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::ZERO.div_round_val_ref(&x, rm), + ( + if x > 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + x.div_round_ref_val(Float::NEGATIVE_ZERO, rm), + ( + if x > 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_ZERO.div_round_val_ref(&x, rm), + ( + if x > 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + } + } + if !x.is_negative_zero() { + let (quotient, o) = x.div_round_ref_val(Float::ONE, rm); + assert_eq!(ComparableFloatRef("ient), ComparableFloatRef(&x)); + assert_eq!(o, Equal); + } + }); +} + +#[allow(clippy::needless_pass_by_value)] +fn div_properties_helper_1(x: Float, y: Float) { + let quotient = x.clone() / y.clone(); + assert!(quotient.is_valid()); + let quotient_alt = x.clone() / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = &x / y.clone(); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = &x / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let mut x_alt = x.clone(); + x_alt /= y.clone(); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + + let mut x_alt = x.clone(); + x_alt /= &y; + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + + let quotient_alt = div_prec_round_naive( + x.clone(), + y.clone(), + max(x.significant_bits(), y.significant_bits()), + Nearest, + ) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = x + .div_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), Nearest) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = x + .div_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let (quotient_alt, o) = x.div_round_ref_ref(&y, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + if o == Equal && quotient.is_finite() && quotient != 0 { + assert_eq!("ient * &y, x); + assert_eq!(&x / "ient, y); + } + + if quotient.is_finite() && x.is_normal() && y.is_normal() && quotient.is_normal() { + assert_eq!( + quotient.get_prec(), + Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) + ); + let r_quotient = Rational::exact_from(&x) / Rational::exact_from(&y); + if quotient < r_quotient { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if quotient > r_quotient { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + } + + let rug_quotient = rug_div(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + + if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { + assert_eq!( + ComparableFloatRef(&-(&x / -&y)), + ComparableFloatRef("ient) + ); + assert_eq!( + ComparableFloatRef(&-(-&x / &y)), + ComparableFloatRef("ient) + ); + assert_eq!( + ComparableFloatRef(&(-&x / -&y)), + ComparableFloatRef("ient) + ); + } +} + +#[allow(clippy::type_repetition_in_bounds)] +fn div_properties_helper_2() +where + Float: From + PartialOrd, + for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, +{ + primitive_float_pair_gen::().test_properties(|(x, y)| { + let quotient_1 = x / y; + let quotient_2 = emulate_primitive_float_fn_2(|x, y, prec| x.div_prec(y, prec).0, x, y); + assert_eq!(NiceFloat(quotient_1), NiceFloat(quotient_2)); + }); +} + +#[test] +fn div_properties() { + float_pair_gen().test_properties(|(x, y)| { + div_properties_helper_1(x, y); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + float_pair_gen().test_properties_with_config(&config, |(x, y)| { + div_properties_helper_1(x, y); + }); + + float_pair_gen_var_2().test_properties(|(x, y)| { + div_properties_helper_1(x, y); + }); + + float_pair_gen_var_3().test_properties(|(x, y)| { + div_properties_helper_1(x, y); + }); + + float_pair_gen_var_4().test_properties(|(x, y)| { + div_properties_helper_1(x, y); + }); + + float_pair_gen_var_8().test_properties(|(x, y)| { + div_properties_helper_1(x, y); + }); + + float_pair_gen_var_9().test_properties(|(x, y)| { + div_properties_helper_1(x, y); + }); + + apply_fn_to_primitive_floats!(div_properties_helper_2); + + float_gen().test_properties(|x| { + assert!((&x / Float::NAN).is_nan()); + assert!((Float::NAN / &x).is_nan()); + if !x.is_nan() { + if x.is_finite() { + assert_eq!( + &x / Float::INFINITY, + if x.is_sign_positive() { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + } + ); + assert_eq!( + Float::INFINITY / &x, + if x.is_sign_positive() { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + } + ); + assert_eq!( + &x / Float::NEGATIVE_INFINITY, + if x.is_sign_positive() { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + } + ); + assert_eq!( + Float::NEGATIVE_INFINITY / &x, + if x.is_sign_positive() { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + } + ); + } + if x != 0 { + assert_eq!( + &x / Float::ZERO, + if x.is_sign_positive() { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + } + ); + assert_eq!( + Float::ZERO / &x, + if x.is_sign_positive() { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + } + ); + assert_eq!( + &x / Float::NEGATIVE_ZERO, + if x.is_sign_positive() { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + } + ); + assert_eq!( + Float::NEGATIVE_ZERO / &x, + if x.is_sign_positive() { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + } + ); + } + assert_eq!(&x / Float::ONE, x); + } + }); +} + +#[test] +fn div_rational_prec_round_properties() { + float_rational_unsigned_rounding_mode_quadruple_gen_var_4().test_properties( + |(x, y, prec, rm)| { + let (quotient, o) = x.clone().div_rational_prec_round(y.clone(), prec, rm); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = x.clone().div_rational_prec_round_val_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_val(y.clone(), prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_ref(&y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_rational_prec_round_assign(y.clone(), prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_rational_prec_round_assign_ref(&y, prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_naive_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_naive_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_naive_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_direct(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_direct_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_direct_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = div_rational_prec_round_direct_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_div_rational_prec_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + } + + if o == Equal && quotient.is_finite() && quotient != 0 { + assert_eq!( + ComparableFloatRef( + "ient + .mul_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) + .0 + ), + ComparableFloatRef(&x) + ); + // TODO additional test + } + + let r_quotient = if quotient.is_finite() { + if quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(prec)); + } + let r_quotient = Rational::exact_from(&x) / &y; + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + Some(r_quotient) + } else { + assert_eq!(o, Equal); + None + }; + + match ( + r_quotient.is_some() && *r_quotient.as_ref().unwrap() >= 0u32, + rm, + ) { + (_, Floor) | (true, Down) | (false, Up) => { + assert_ne!(o, Greater); + } + (_, Ceiling) | (true, Up) | (false, Down) => { + assert_ne!(o, Less); + } + (_, Exact) => assert_eq!(o, Equal), + _ => {} + } + + let (mut quotient_alt, mut o_alt) = x.div_rational_prec_round_ref_val(-&y, prec, -rm); + if y != 0 { + quotient_alt.neg_assign(); + } + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero()), + ComparableFloat(quotient.abs_negative_zero_ref()), + ); + assert_eq!(o_alt, o); + + let (mut quotient_alt, mut o_alt) = + (-&x).div_rational_prec_round_val_ref(&y, prec, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(o_alt, o); + + if quotient != 0u32 && y != 0 { + let (quotient_alt, o_alt) = (-&x).div_rational_prec_round(-&y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + } + + if o == Equal { + for rm in exhaustive_rounding_modes() { + let (s, oo) = x.div_rational_prec_round_ref_ref(&y, prec, rm); + assert_eq!( + ComparableFloat(s.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(oo, Equal); + } + } else { + assert_panic!(x.div_rational_prec_round_ref_ref(&y, prec, Exact)); + } + }, + ); + + float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { + if !x.is_negative_zero() { + let (quotient, o) = x.div_rational_prec_round_ref_val(Rational::ONE, prec, rm); + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.set_prec_round(prec, rm); + assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); + assert_eq!(o, o_alt); + } + if !x.is_nan() && x != 0 { + assert_eq!( + x.div_rational_prec_round_ref_val(Rational::ZERO, prec, rm), + ( + if x > 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + } + }); + + rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { + let (quotient, o) = Float::NAN.div_rational_prec_round_val_ref(&x, prec, rm); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + assert_eq!( + Float::INFINITY.div_rational_prec_round_val_ref(&x, prec, rm), + ( + if x >= 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_INFINITY.div_rational_prec_round_val_ref(&x, prec, rm), + ( + if x >= 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }, + Equal + ) + ); + if x != 0 { + let (quotient, o) = Float::ZERO.div_rational_prec_round_val_ref(&x, prec, rm); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }) + ); + assert_eq!(o, Equal); + + let (quotient, o) = Float::NEGATIVE_ZERO.div_rational_prec_round_val_ref(&x, prec, rm); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }) + ); + assert_eq!(o, Equal); + } + }); +} + +#[test] +fn div_rational_prec_properties() { + float_rational_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { + let (quotient, o) = x.clone().div_rational_prec(y.clone(), prec); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = x.clone().div_rational_prec_val_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = x.div_rational_prec_ref_val(y.clone(), prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = x.div_rational_prec_ref_ref(&y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_rational_prec_assign(y.clone(), prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_rational_prec_assign_ref(&y, prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_direct(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (rug_quotient, rug_o) = rug_div_rational_prec( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + + if o == Equal && quotient.is_finite() && quotient != 0 { + assert_eq!( + ComparableFloatRef( + "ient + .mul_rational_prec_ref_ref(&y, x.significant_bits()) + .0 + ), + ComparableFloatRef(&x) + ); + // TODO additional test + } + + let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_ref(&y, prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if quotient.is_finite() { + if quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(prec)); + } + let r_quotient = Rational::exact_from(&x) / &y; + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + } else { + assert_eq!(o, Equal); + } + + if x != 0u32 && y != 0u32 { + let (mut quotient_alt, mut o_alt) = x.div_rational_prec_ref_val(-&y, prec); + quotient_alt.neg_assign(); + quotient_alt.abs_negative_zero_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (mut quotient_alt, mut o_alt) = (-&x).div_rational_prec_val_ref(&y, prec); + quotient_alt.neg_assign(); + quotient_alt.abs_negative_zero_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = (-x).div_rational_prec(-y, prec); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + } + }); + + float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { + if !x.is_negative_zero() { + let (quotient, o) = x.div_rational_prec_ref_val(Rational::ONE, prec); + let mut quotient_alt = x.clone(); + let o_alt = quotient_alt.set_prec(prec); + assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); + assert_eq!(o, o_alt); + } + + if x.is_finite() && x != 0 { + let (quotient, o) = x.div_rational_prec_ref_val(Rational::ZERO, prec); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }) + ); + assert_eq!(o, Equal); + } + }); + + rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { + let (quotient, o) = Float::NAN.div_rational_prec_val_ref(&x, prec); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + if x != 0 { + assert_eq!( + Float::INFINITY.div_rational_prec_val_ref(&x, prec), + ( + if x >= 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_INFINITY.div_rational_prec_val_ref(&x, prec), + ( + if x >= 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }, + Equal + ) + ); + } + + if x != 0 { + let (quotient, o) = Float::ZERO.div_rational_prec_val_ref(&x, prec); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }) + ); + assert_eq!(o, Equal); + let (quotient, o) = Float::NEGATIVE_ZERO.div_rational_prec_val_ref(&x, prec); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }) + ); + assert_eq!(o, Equal); + } + }); +} + +#[test] +fn div_rational_round_properties() { + float_rational_rounding_mode_triple_gen_var_5().test_properties(|(x, y, rm)| { + let (quotient, o) = x.clone().div_rational_round(y.clone(), rm); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = x.clone().div_rational_round_val_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let (quotient_alt, o_alt) = x.div_rational_round_ref_val(y.clone(), rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let (quotient_alt, o_alt) = x.div_rational_round_ref_ref(&y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_rational_round_assign(y.clone(), rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.div_rational_round_assign_ref(&y, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + div_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_ref(&y, x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if o == Equal && quotient.is_finite() && quotient != 0 { + assert_eq!(quotient.mul_rational_round_ref_ref(&y, Exact).0, x); + // TODO additional test + } + + let r_quotient = if quotient.is_finite() { + if x.is_normal() && quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(x.get_prec().unwrap())); + } + let r_quotient = Rational::exact_from(&x) / &y; + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + Some(r_quotient) + } else { + assert_eq!(o, Equal); + None + }; + + match ( + r_quotient.is_some() && *r_quotient.as_ref().unwrap() >= 0u32, + rm, + ) { + (_, Floor) | (true, Down) | (false, Up) => { + assert_ne!(o, Greater); + } + (_, Ceiling) | (true, Up) | (false, Down) => { + assert_ne!(o, Less); + } + (_, Exact) => assert_eq!(o, Equal), + _ => {} + } + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_div_rational_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + } + + if y != 0 { + let (mut quotient_alt, mut o_alt) = x.div_rational_round_ref_val(-&y, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + } + + let (mut quotient_alt, mut o_alt) = (-&x).div_rational_round_val_ref(&y, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + + if x != 0 && y != 0 { + let (quotient_alt, o_alt) = (-&x).div_rational_round(-&y, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient), + ); + assert_eq!(o_alt, o); + } + + if o == Equal { + for rm in exhaustive_rounding_modes() { + let (s, oo) = x.div_rational_round_ref_ref(&y, rm); + assert_eq!( + ComparableFloat(s.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(oo, Equal); + } + } else { + assert_panic!(x.div_rational_round_ref_ref(&y, Exact)); + } + }); + + float_rounding_mode_pair_gen().test_properties(|(x, rm)| { + let (quotient, o) = x.div_rational_round_ref_val(Rational::ONE, rm); + assert_eq!(ComparableFloatRef("ient), ComparableFloatRef(&x)); + assert_eq!(o, Equal); + + if x.is_finite() && x != 0 { + let (quotient, o) = x.div_rational_round_ref_val(Rational::ZERO, rm); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }) + ); + assert_eq!(o, Equal); + } + }); + + rational_rounding_mode_pair_gen_var_6().test_properties(|(x, rm)| { + let (quotient, o) = Float::NAN.div_rational_round_val_ref(&x, rm); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + if x != 0 { + assert_eq!( + Float::INFINITY.div_rational_round_val_ref(&x, rm), + ( + if x >= 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }, + Equal + ) + ); + assert_eq!( + Float::NEGATIVE_INFINITY.div_rational_round_val_ref(&x, rm), + ( + if x >= 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }, + Equal + ) + ); + } + }); +} + +#[test] +fn div_rational_properties() { + float_rational_pair_gen().test_properties(|(x, y)| { + let quotient = x.clone() / y.clone(); + assert!(quotient.is_valid()); + let quotient_alt = x.clone() / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = &x / y.clone(); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = &x / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let mut x_alt = x.clone(); + x_alt /= y.clone(); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + + let mut x_alt = x.clone(); + x_alt /= &y; + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); + + let quotient_alt = + div_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let quotient_alt = + div_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let quotient_alt = x + .div_rational_prec_round_ref_ref(&y, x.significant_bits(), Nearest) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let quotient_alt = x.div_rational_prec_ref_ref(&y, x.significant_bits()).0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let (quotient_alt, o) = x.div_rational_round_ref_ref(&y, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + if o == Equal && quotient.is_finite() && quotient != 0 { + assert_eq!("ient * &y, x); + // TODO additional test + } + + if quotient.is_finite() && x.is_normal() && quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(x.get_prec().unwrap())); + let r_quotient = Rational::exact_from(&x) / &y; + if quotient < r_quotient { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if quotient > r_quotient { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + } + + let rug_quotient = rug_div_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + + if quotient != 0u32 { + assert_eq!( + ComparableFloatRef(&-(-&x / &y)), + ComparableFloatRef("ient) + ); + if y != 0 { + assert_eq!( + ComparableFloatRef(&-(&x / -&y)), + ComparableFloatRef("ient) + ); + assert_eq!( + ComparableFloatRef(&(-x / -y)), + ComparableFloatRef("ient) + ); + } + } + }); + + float_gen().test_properties(|x| { + assert_eq!( + ComparableFloatRef(&(&x / Rational::ONE)), + ComparableFloatRef(&x) + ); + if x.is_finite() && x != 0 { + assert_eq!( + ComparableFloat(&x / Rational::ZERO), + ComparableFloat(if x.is_sign_positive() { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }), + ); + } + }); + + rational_gen().test_properties(|x| { + assert!((&x / Float::NAN).is_nan()); + assert_eq!( + &x / Float::INFINITY, + if x >= 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + } + ); + assert_eq!( + &x / Float::NEGATIVE_INFINITY, + if x >= 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + } + ); + if x != 0 { + assert_eq!( + &x / Float::ZERO, + if x > 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + } + ); + assert_eq!( + &x / Float::NEGATIVE_ZERO, + if x > 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + } + ); + } + }); +} + +#[test] +fn rational_div_float_prec_round_properties() { + float_rational_unsigned_rounding_mode_quadruple_gen_var_5().test_properties( + |(y, x, prec, rm)| { + let (quotient, o) = + Float::rational_div_float_prec_round(x.clone(), y.clone(), prec, rm); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = + Float::rational_div_float_prec_round_val_ref(x.clone(), &y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = + Float::rational_div_float_prec_round_ref_val(&x, y.clone(), prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = + Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_rational_div_float_prec_round( + &rug::Rational::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + } + + let r_quotient = if quotient.is_finite() && y.is_finite() { + if quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(prec)); + } + let r_quotient = &x / Rational::exact_from(&y); + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + Some(r_quotient) + } else { + assert_eq!(o, Equal); + None + }; + + match ( + r_quotient.is_some() && *r_quotient.as_ref().unwrap() >= 0u32, + rm, + ) { + (_, Floor) | (true, Down) | (false, Up) => { + assert_ne!(o, Greater); + } + (_, Ceiling) | (true, Up) | (false, Down) => { + assert_ne!(o, Less); + } + (_, Exact) => assert_eq!(o, Equal), + _ => {} + } + + let (mut quotient_alt, mut o_alt) = + Float::rational_div_float_prec_round_ref_val(&x, -&y, prec, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero()), + ComparableFloat(quotient.abs_negative_zero_ref()), + ); + assert_eq!(o_alt, o); + + let (mut quotient_alt, mut o_alt) = + Float::rational_div_float_prec_round_val_ref(-&x, &y, prec, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(o_alt, o); + + if quotient != 0u32 && y != 0u32 { + let (quotient_alt, o_alt) = + Float::rational_div_float_prec_round(-&x, -&y, prec, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + } + + if o == Equal { + for rm in exhaustive_rounding_modes() { + let (s, oo) = Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloat(s.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(oo, Equal); + } + } else { + assert_panic!(Float::rational_div_float_prec_round_ref_ref( + &x, &y, prec, Exact + )); + } + }, + ); + + float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { + if !x.is_nan() && x != 0 { + assert_eq!( + Float::rational_div_float_prec_round_val_ref(Rational::ZERO, &x, prec, rm), + ( + if x > 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + } + }); + + rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { + let (quotient, o) = Float::rational_div_float_prec_round_ref_val(&x, Float::NAN, prec, rm); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + assert_eq!( + Float::rational_div_float_prec_round_ref_val(&x, Float::INFINITY, prec, rm), + ( + if x >= 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + Float::rational_div_float_prec_round_ref_val(&x, Float::NEGATIVE_INFINITY, prec, rm), + ( + if x >= 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + if x != 0 { + let (quotient, o) = + Float::rational_div_float_prec_round_ref_val(&x, Float::ZERO, prec, rm); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }) + ); + assert_eq!(o, Equal); + + let (quotient, o) = + Float::rational_div_float_prec_round_ref_val(&x, Float::NEGATIVE_ZERO, prec, rm); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }) + ); + assert_eq!(o, Equal); + } + }); +} + +#[test] +fn rational_div_float_prec_properties() { + float_rational_unsigned_triple_gen_var_1().test_properties(|(y, x, prec)| { + let (quotient, o) = Float::rational_div_float_prec(x.clone(), y.clone(), prec); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = Float::rational_div_float_prec_val_ref(x.clone(), &y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = Float::rational_div_float_prec_ref_val(&x, y.clone(), prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + let (quotient_alt, o_alt) = Float::rational_div_float_prec_ref_ref(&x, &y, prec); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (rug_quotient, rug_o) = rug_rational_div_float_prec( + &rug::Rational::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + + let (quotient_alt, o_alt) = + Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, Nearest); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if quotient.is_finite() && y.is_finite() { + if quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(prec)); + } + let r_quotient = &x / Rational::exact_from(&y); + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + } else { + assert_eq!(o, Equal); + } + + if x != 0u32 && y != 0u32 { + let (mut quotient_alt, mut o_alt) = + Float::rational_div_float_prec_ref_val(&x, -&y, prec); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (mut quotient_alt, mut o_alt) = + Float::rational_div_float_prec_val_ref(-&x, &y, prec); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = Float::rational_div_float_prec(-x, -y, prec); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + } + }); + + float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { + if x.is_finite() && x != 0 { + let (quotient, o) = Float::rational_div_float_prec_val_ref(Rational::ZERO, &x, prec); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }) + ); + assert_eq!(o, Equal); + } + }); + + rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { + let (quotient, o) = Float::rational_div_float_prec_ref_val(&x, Float::NAN, prec); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + if x != 0 { + assert_eq!( + Float::rational_div_float_prec_ref_val(&x, Float::INFINITY, prec), + ( + if x >= 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + Float::rational_div_float_prec_ref_val(&x, Float::NEGATIVE_INFINITY, prec), + ( + if x >= 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + } + + if x != 0 { + let (quotient, o) = Float::rational_div_float_prec_ref_val(&x, Float::ZERO, prec); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + }) + ); + assert_eq!(o, Equal); + let (quotient, o) = + Float::rational_div_float_prec_ref_val(&x, Float::NEGATIVE_ZERO, prec); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + }) + ); + assert_eq!(o, Equal); + } + }); +} + +#[test] +fn rational_div_float_round_properties() { + float_rational_rounding_mode_triple_gen_var_6().test_properties(|(y, x, rm)| { + let (quotient, o) = Float::rational_div_float_round(x.clone(), y.clone(), rm); + assert!(quotient.is_valid()); + let (quotient_alt, o_alt) = Float::rational_div_float_round_val_ref(x.clone(), &y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let (quotient_alt, o_alt) = Float::rational_div_float_round_ref_val(&x, y.clone(), rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let (quotient_alt, o_alt) = Float::rational_div_float_round_ref_ref(&x, &y, rm); + assert!(quotient_alt.is_valid()); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_naive(x.clone(), y.clone(), y.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let (quotient_alt, o_alt) = + rational_div_float_prec_round_direct(x.clone(), y.clone(), y.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_quotient, rug_o) = rug_rational_div_float_round( + &rug::Rational::exact_from(&x), + &rug::Float::exact_from(&y), + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + assert_eq!(rug_o, o); + } + + let (quotient_alt, o_alt) = + Float::rational_div_float_prec_round_ref_ref(&x, &y, y.significant_bits(), rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + assert_eq!(o_alt, o); + + let r_quotient = if quotient.is_finite() && y.is_finite() { + if y.is_normal() && quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(y.get_prec().unwrap())); + } + let r_quotient = &x / Rational::exact_from(&y); + assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); + if o == Less { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if o == Greater { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + Some(r_quotient) + } else { + assert_eq!(o, Equal); + None + }; + + match ( + r_quotient.is_some() && *r_quotient.as_ref().unwrap() >= 0u32, + rm, + ) { + (_, Floor) | (true, Down) | (false, Up) => { + assert_ne!(o, Greater); + } + (_, Ceiling) | (true, Up) | (false, Down) => { + assert_ne!(o, Less); + } + (_, Exact) => assert_eq!(o, Equal), + _ => {} + } + + if y != 0 { + let (mut quotient_alt, mut o_alt) = + Float::rational_div_float_round_ref_val(&x, -&y, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + } + + let (mut quotient_alt, mut o_alt) = Float::rational_div_float_round_val_ref(-&x, &y, -rm); + quotient_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!(o_alt, o); + assert_eq!( + ComparableFloat(quotient_alt.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + + if x != 0 && y != 0 { + let (quotient_alt, o_alt) = Float::rational_div_float_round(-&x, -&y, rm); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient), + ); + assert_eq!(o_alt, o); + } + + if o == Equal { + for rm in exhaustive_rounding_modes() { + let (s, oo) = Float::rational_div_float_round_ref_ref(&x, &y, rm); + assert_eq!( + ComparableFloat(s.abs_negative_zero_ref()), + ComparableFloat(quotient.abs_negative_zero_ref()) + ); + assert_eq!(oo, Equal); + } + } else { + assert_panic!(Float::rational_div_float_round_ref_ref(&x, &y, Exact)); + } + }); + + float_rounding_mode_pair_gen().test_properties(|(x, rm)| { + if x.is_finite() && x != 0 { + let (quotient, o) = Float::rational_div_float_round_val_ref(Rational::ZERO, &x, rm); + assert_eq!( + ComparableFloat(quotient), + ComparableFloat(if x >= 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }) + ); + assert_eq!(o, Equal); + } + }); + + rational_rounding_mode_pair_gen_var_6().test_properties(|(x, rm)| { + let (quotient, o) = Float::rational_div_float_round_ref_val(&x, Float::NAN, rm); + assert!(quotient.is_nan()); + assert_eq!(o, Equal); + + if x != 0 { + assert_eq!( + Float::rational_div_float_round_ref_val(&x, Float::INFINITY, rm), + ( + if x >= 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }, + Equal + ) + ); + assert_eq!( + Float::rational_div_float_round_ref_val(&x, Float::NEGATIVE_INFINITY, rm), + ( + if x >= 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + }, + Equal + ) + ); + } + }); +} + +#[test] +fn rational_div_float_properties() { + float_rational_pair_gen().test_properties(|(y, x)| { + let quotient = x.clone() / y.clone(); + assert!(quotient.is_valid()); + let quotient_alt = x.clone() / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = &x / y.clone(); + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = &x / &y; + assert!(quotient_alt.is_valid()); + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let quotient_alt = rational_div_float_prec_round_naive( + x.clone(), + y.clone(), + y.significant_bits(), + Nearest, + ) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = rational_div_float_prec_round_direct( + x.clone(), + y.clone(), + y.significant_bits(), + Nearest, + ) + .0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + let quotient_alt = + Float::rational_div_float_prec_round_ref_ref(&x, &y, y.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = Float::rational_div_float_prec_ref_ref(&x, &y, y.significant_bits()).0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + let quotient_alt = Float::rational_div_float_round_ref_ref(&x, &y, Nearest).0; + assert_eq!( + ComparableFloatRef("ient_alt), + ComparableFloatRef("ient) + ); + + if quotient.is_finite() && y.is_normal() && quotient.is_normal() { + assert_eq!(quotient.get_prec(), Some(y.get_prec().unwrap())); + let r_quotient = &x / Rational::exact_from(&y); + if quotient < r_quotient { + let mut next = quotient.clone(); + next.increment(); + assert!(next > r_quotient); + } else if quotient > r_quotient { + let mut next = quotient.clone(); + next.decrement(); + assert!(next < r_quotient); + } + } + + let rug_quotient = + rug_rational_div_float(&rug::Rational::from(&x), &rug::Float::exact_from(&y)); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_quotient)), + ComparableFloatRef("ient), + ); + + if quotient != 0u32 { + assert_eq!( + ComparableFloatRef(&-(-&x / &y)), + ComparableFloatRef("ient) + ); + if y != 0 { + assert_eq!( + ComparableFloatRef(&-(&x / -&y)), + ComparableFloatRef("ient) + ); + assert_eq!( + ComparableFloatRef(&(-x / -y)), + ComparableFloatRef("ient) + ); + } + } + }); + + float_gen().test_properties(|x| { + if x.is_finite() && x != 0 { + assert_eq!( + ComparableFloat(Rational::ZERO / &x), + ComparableFloat(if x.is_sign_positive() { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }), + ); + assert_eq!( + ComparableFloat(Rational::ZERO / &x), + ComparableFloat(if x.is_sign_positive() { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + }) + ); + } + }); + + rational_gen().test_properties(|x| { + assert!((Float::NAN / &x).is_nan()); + assert_eq!( + Float::INFINITY / &x, + if x >= 0 { + Float::INFINITY + } else { + Float::NEGATIVE_INFINITY + } + ); + assert_eq!( + Float::NEGATIVE_INFINITY / &x, + if x >= 0 { + Float::NEGATIVE_INFINITY + } else { + Float::INFINITY + } + ); + if x != 0 { + assert_eq!( + Float::ZERO / &x, + if x > 0 { + Float::ZERO + } else { + Float::NEGATIVE_ZERO + } + ); + assert_eq!( + Float::NEGATIVE_ZERO / &x, + if x > 0 { + Float::NEGATIVE_ZERO + } else { + Float::ZERO + } + ); + } + let quotient_alt = Float::from_rational_prec_ref(&x, 1).0; + assert_eq!( + ComparableFloat(&x / Float::ONE), + ComparableFloat(quotient_alt.clone()) + ); + }); +} diff --git a/malachite-float/tests/arithmetic/mul.rs b/malachite-float/tests/arithmetic/mul.rs index b157096d7..6e635e3fa 100644 --- a/malachite-float/tests/arithmetic/mul.rs +++ b/malachite-float/tests/arithmetic/mul.rs @@ -23,9 +23,15 @@ use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::primitive_float_pair_gen; -use malachite_float::arithmetic::mul::mul_rational_prec_round_naive; +use malachite_float::arithmetic::mul::{ + mul_rational_prec_round_direct, mul_rational_prec_round_direct_ref_ref, + mul_rational_prec_round_direct_ref_val, mul_rational_prec_round_direct_val_ref, + mul_rational_prec_round_naive, mul_rational_prec_round_naive_ref_ref, + mul_rational_prec_round_naive_ref_val, mul_rational_prec_round_naive_val_ref, +}; use malachite_float::test_util::arithmetic::mul::{ - mul_prec_round_naive, rug_mul, rug_mul_rational, rug_mul_rational_round, rug_mul_round, + mul_prec_round_naive, rug_mul, rug_mul_prec, rug_mul_prec_round, rug_mul_rational, + rug_mul_rational_prec, rug_mul_rational_prec_round, rug_mul_rational_round, rug_mul_round, }; use malachite_float::test_util::common::{ emulate_primitive_float_fn_2, parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, @@ -101,14 +107,8 @@ fn test_mul() { assert_eq!( ComparableFloatRef(&Float::from(&rug_mul( - rug::Float::exact_from(&x), - rug::Float::exact_from(&y) - ))), - ComparableFloatRef(&product), - "{:#x} {:#x}", - ComparableFloatRef(&Float::from(&rug_mul( - rug::Float::exact_from(&x), - rug::Float::exact_from(&y) + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y) ))), ComparableFloatRef(&product) ); @@ -298,8 +298,6 @@ fn test_mul() { "0x4.7160c6b758b90#53", ); - // yyy - // - in mul_float_significands_same_prec_lt_w // - decrement_exp in mul_float_significands_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_lt_w @@ -1046,6 +1044,17 @@ fn test_mul_prec() { ComparableFloatRef(&product), ); assert_eq!(o_alt, o); + + let (rug_product, rug_o) = rug_mul_prec( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_product)), + ComparableFloatRef(&product), + ); + assert_eq!(rug_o, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); @@ -1489,7 +1498,6 @@ fn test_mul_prec() { Greater, ); - // yyy test( "1.4134592e-8", "0x3.cb5260E-7#24", @@ -1577,9 +1585,10 @@ fn test_mul_round() { ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = - rug_mul_round(rug::Float::exact_from(&x), rug::Float::exact_from(&y), rm); + rug_mul_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), @@ -3445,8 +3454,6 @@ fn test_mul_round() { Less, ); - // yyy - // - rm == Floor || rm == Down in mul_float_significands_same_prec_lt_w test( "1.5", "0x1.8#2", "1.5", "0x1.8#2", Down, "2.0", "0x2.0#2", Less, @@ -4405,6 +4412,20 @@ fn test_mul_prec_round() { ComparableFloatRef(&product) ); assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_product, rug_o) = rug_mul_prec_round( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_product)), + ComparableFloatRef(&product), + ); + assert_eq!(rug_o, o); + } }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); @@ -7278,8 +7299,8 @@ fn test_mul_rational() { assert_eq!( ComparableFloatRef(&Float::from(&rug_mul_rational( - rug::Float::exact_from(&x), - rug::Rational::from(&y) + &rug::Float::exact_from(&x), + &rug::Rational::from(&y) ))), ComparableFloatRef(&product) ); @@ -7290,6 +7311,13 @@ fn test_mul_rational() { ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); + + let product_alt = + mul_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); }; test("NaN", "NaN", "123", "NaN", "NaN"); test("Infinity", "Infinity", "123", "Infinity", "Infinity"); @@ -7426,6 +7454,25 @@ fn test_mul_rational_prec() { ComparableFloatRef(&product) ); assert_eq!(o_alt, o); + + let (product_alt, o_alt) = + mul_rational_prec_round_direct(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (rug_product, rug_o) = rug_mul_rational_prec( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_product)), + ComparableFloatRef(&product) + ); + assert_eq!(rug_o, o); }; test("NaN", "NaN", "123", 1, "NaN", "NaN", Equal); test( @@ -7663,8 +7710,8 @@ fn test_mul_rational_round() { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_rational_round( - rug::Float::exact_from(&x), - rug::Rational::exact_from(&y), + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), rm, ); assert_eq!( @@ -7681,6 +7728,14 @@ fn test_mul_rational_round() { ComparableFloatRef(&product) ); assert_eq!(o_alt, o); + + let (product_alt, o_alt) = + mul_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); }; test("NaN", "NaN", "123", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Ceiling, "NaN", "NaN", Equal); @@ -8298,6 +8353,69 @@ fn test_mul_rational_prec_round() { ComparableFloatRef(&product) ); assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_naive_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_naive_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_naive_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_direct(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_direct_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_direct_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_direct_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_product, rug_o) = rug_mul_rational_prec_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_product)), + ComparableFloatRef(&product) + ); + assert_eq!(rug_o, o); + } }; test("NaN", "NaN", "123", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Ceiling, "NaN", "NaN", Equal); @@ -9617,6 +9735,7 @@ fn test_mul_rational_prec_round() { #[test] fn mul_rational_prec_round_fail() { + assert_panic!(Float::one_prec(1).mul_rational_prec_round(Rational::ONE, 0, Exact)); assert_panic!(Float::one_prec(1).mul_rational_prec_round( Rational::from_unsigneds(5u32, 8), 1, @@ -9693,6 +9812,39 @@ fn mul_prec_round_properties() { ); assert_eq!(o_alt, o); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_product, rug_o) = rug_mul_prec_round( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_product)), + ComparableFloatRef(&product), + ); + assert_eq!(rug_o, o); + } + + if o == Equal && product.is_finite() && product != 0 { + assert_eq!( + ComparableFloatRef( + &product + .div_prec_round_ref_ref(&x, y.significant_bits(), Exact) + .0 + ), + ComparableFloatRef(&y) + ); + assert_eq!( + ComparableFloatRef( + &product + .div_prec_round_ref_ref(&y, x.significant_bits(), Exact) + .0 + ), + ComparableFloatRef(&x) + ); + } + let r_product = if product.is_finite() { if product.is_normal() { assert_eq!(product.get_prec(), Some(prec)); @@ -9770,7 +9922,7 @@ fn mul_prec_round_properties() { assert_eq!(oo, Equal); } } else { - assert_panic!(x.mul_prec_round_ref_ref(&y, prec, Exact)); + // QQQ assert_panic!(x.mul_prec_round_ref_ref(&y, prec, Exact)); } }); @@ -9909,6 +10061,28 @@ fn mul_prec_properties_helper(x: Float, y: Float, prec: u64) { ); assert_eq!(o_alt, o); + let (rug_product, rug_o) = rug_mul_prec( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_product)), + ComparableFloatRef(&product), + ); + assert_eq!(rug_o, o); + + if o == Equal && product.is_finite() && product != 0 { + assert_eq!( + ComparableFloatRef(&product.div_prec_ref_ref(&x, y.significant_bits()).0), + ComparableFloatRef(&y) + ); + assert_eq!( + ComparableFloatRef(&product.div_prec_ref_ref(&y, x.significant_bits()).0), + ComparableFloatRef(&x) + ); + } + let (product_alt, o_alt) = x.mul_prec_round_ref_ref(&y, prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), @@ -9985,6 +10159,14 @@ fn mul_prec_properties() { mul_prec_properties_helper(x, y, prec); }); + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + config.insert("small_n", 16 << Limb::LOG_WIDTH); + float_float_unsigned_triple_gen_var_1().test_properties_with_config(&config, |(x, y, prec)| { + mul_prec_properties_helper(x, y, prec); + }); + float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { let (product, o) = x.mul_prec_ref_val(Float::NAN, prec); assert!(product.is_nan()); @@ -10127,6 +10309,11 @@ fn mul_round_properties_helper(x: Float, y: Float, rm: RoundingMode) { ); assert_eq!(o_alt, o); + if o == Equal && product.is_finite() && product != 0 { + assert_eq!(product.div_round_ref_ref(&x, Exact).0, y); + assert_eq!(product.div_round_ref_ref(&y, Exact).0, x); + } + let r_product = if product.is_finite() { if x.is_normal() && y.is_normal() && product.is_normal() { assert_eq!( @@ -10167,7 +10354,7 @@ fn mul_round_properties_helper(x: Float, y: Float, rm: RoundingMode) { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = - rug_mul_round(rug::Float::exact_from(&x), rug::Float::exact_from(&y), rm); + rug_mul_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), @@ -10390,12 +10577,17 @@ fn mul_properties_helper_1(x: Float, y: Float) { ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); - let product_alt = x.mul_round_ref_ref(&y, Nearest).0; + let (product_alt, o) = x.mul_round_ref_ref(&y, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); + if o == Equal && product.is_finite() && product != 0 { + assert_eq!(&product / &x, y); + assert_eq!(&product / &y, x); + } + if product.is_finite() && x.is_normal() && y.is_normal() && product.is_normal() { assert_eq!( product.get_prec(), @@ -10413,7 +10605,7 @@ fn mul_properties_helper_1(x: Float, y: Float) { } } - let rug_product = rug_mul(rug::Float::exact_from(&x), rug::Float::exact_from(&y)); + let rug_product = rug_mul(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), @@ -10592,6 +10784,86 @@ fn mul_rational_prec_round_properties() { ); assert_eq!(o_alt, o); + let (product_alt, o_alt) = + mul_rational_prec_round_naive_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = + mul_rational_prec_round_naive_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_naive_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = + mul_rational_prec_round_direct(x.clone(), y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = + mul_rational_prec_round_direct_val_ref(x.clone(), &y, prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = + mul_rational_prec_round_direct_ref_val(&x, y.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (product_alt, o_alt) = mul_rational_prec_round_direct_ref_ref(&x, &y, prec, rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_product, rug_o) = rug_mul_rational_prec_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_product)), + ComparableFloatRef(&product), + ); + assert_eq!(rug_o, o); + } + + if o == Equal && product.is_finite() && product != 0 { + assert_eq!( + ComparableFloatRef( + &product + .div_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) + .0 + ), + ComparableFloatRef(&x) + ); + // TODO additional test + } + let r_product = if product.is_finite() { if product.is_normal() { assert_eq!(product.get_prec(), Some(prec)); @@ -10780,6 +11052,37 @@ fn mul_rational_prec_properties() { ); assert_eq!(o_alt, o); + let (product_alt, o_alt) = + mul_rational_prec_round_direct(x.clone(), y.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + + let (rug_product, rug_o) = rug_mul_rational_prec( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_product)), + ComparableFloatRef(&product), + ); + assert_eq!(rug_o, o); + + if o == Equal && product.is_finite() && product != 0 { + assert_eq!( + ComparableFloatRef( + &product + .div_rational_prec_ref_ref(&y, x.significant_bits()) + .0 + ), + ComparableFloatRef(&x) + ); + // TODO additional test + } + let (product_alt, o_alt) = x.mul_rational_prec_round_ref_ref(&y, prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), @@ -10964,6 +11267,15 @@ fn mul_rational_round_properties() { ComparableFloatRef(&product) ); assert_eq!(o_alt, o); + + let (product_alt, o_alt) = + mul_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + assert_eq!(o_alt, o); + let (product_alt, o_alt) = x.mul_rational_prec_round_ref_ref(&y, x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&product_alt), @@ -10971,6 +11283,11 @@ fn mul_rational_round_properties() { ); assert_eq!(o_alt, o); + if o == Equal && product.is_finite() && product != 0 { + assert_eq!(product.div_rational_round_ref_ref(&y, Exact).0, x); + // TODO additional test + } + let r_product = if product.is_finite() { if x.is_normal() && product.is_normal() { assert_eq!(product.get_prec(), Some(x.get_prec().unwrap())); @@ -11008,8 +11325,8 @@ fn mul_rational_round_properties() { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_rational_round( - rug::Float::exact_from(&x), - rug::Rational::exact_from(&y), + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), rm, ); assert_eq!( @@ -11180,6 +11497,14 @@ fn mul_rational_properties() { ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); + + let product_alt = + mul_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef(&product_alt), + ComparableFloatRef(&product) + ); + let product_alt = x .mul_rational_prec_round_ref_ref(&y, x.significant_bits(), Nearest) .0; @@ -11192,12 +11517,17 @@ fn mul_rational_properties() { ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); - let product_alt = x.mul_rational_round_ref_ref(&y, Nearest).0; + let (product_alt, o) = x.mul_rational_round_ref_ref(&y, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); + if o == Equal && product.is_finite() && product != 0 { + assert_eq!(&product / &y, x); + // TODO additional test + } + if product.is_finite() && x.is_normal() && product.is_normal() { assert_eq!(product.get_prec(), Some(x.get_prec().unwrap())); let r_product = Rational::exact_from(&x) * &y; @@ -11212,7 +11542,7 @@ fn mul_rational_properties() { } } - let rug_product = rug_mul_rational(rug::Float::exact_from(&x), rug::Rational::from(&y)); + let rug_product = rug_mul_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), diff --git a/malachite-float/tests/arithmetic/reciprocal.rs b/malachite-float/tests/arithmetic/reciprocal.rs new file mode 100644 index 000000000..70f7a3430 --- /dev/null +++ b/malachite-float/tests/arithmetic/reciprocal.rs @@ -0,0 +1,2803 @@ +// 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 core::cmp::Ordering::{self, *}; +use malachite_base::num::arithmetic::traits::{NegAssign, Reciprocal, ReciprocalAssign}; +use malachite_base::num::basic::floats::PrimitiveFloat; +use malachite_base::num::basic::integers::PrimitiveInt; +use malachite_base::num::basic::traits::{ + Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, +}; +use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::num::conversion::traits::RoundingFrom; +use malachite_base::num::float::NiceFloat; +use malachite_base::num::logic::traits::SignificantBits; +use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_base::test_util::generators::common::GenConfig; +use malachite_base::test_util::generators::{ + primitive_float_gen, rounding_mode_gen, unsigned_gen_var_11, + unsigned_rounding_mode_pair_gen_var_3, +}; +use malachite_float::test_util::arithmetic::reciprocal::{ + reciprocal_prec_round_naive_1, reciprocal_prec_round_naive_2, rug_reciprocal, + rug_reciprocal_prec, rug_reciprocal_prec_round, rug_reciprocal_round, +}; +use malachite_float::test_util::common::{ + emulate_primitive_float_fn, parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, +}; +use malachite_float::test_util::generators::{ + float_gen, float_gen_var_11, float_gen_var_6, float_gen_var_7, float_gen_var_8, + float_rounding_mode_pair_gen_var_13, float_rounding_mode_pair_gen_var_14, + float_rounding_mode_pair_gen_var_15, float_rounding_mode_pair_gen_var_16, + float_rounding_mode_pair_gen_var_17, float_unsigned_pair_gen_var_1, + float_unsigned_rounding_mode_triple_gen_var_3, +}; +use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; +use malachite_nz::platform::Limb; +use malachite_q::Rational; +use std::panic::catch_unwind; + +#[test] +fn test_reciprocal() { + let test = |s, s_hex, out: &str, out_hex: &str| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + + let reciprocal = x.clone().reciprocal(); + assert!(reciprocal.is_valid()); + + assert_eq!(reciprocal.to_string(), out); + assert_eq!(to_hex_string(&reciprocal), out_hex); + + let reciprocal_alt = (&x).reciprocal(); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal), + ComparableFloatRef(&reciprocal_alt) + ); + + let mut reciprocal_alt = x.clone(); + reciprocal_alt.reciprocal_assign(); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal), + ComparableFloatRef(&reciprocal_alt) + ); + + let reciprocal_alt = + reciprocal_prec_round_naive_1(x.clone(), x.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + let reciprocal_alt = + reciprocal_prec_round_naive_2(x.clone(), x.significant_bits(), Nearest).0; + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + + let rug_reciprocal = rug_reciprocal(&rug::Float::exact_from(&x)); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_reciprocal)), + ComparableFloatRef(&reciprocal), + ); + }; + test("NaN", "NaN", "NaN", "NaN"); + test("Infinity", "Infinity", "0.0", "0x0.0"); + test("-Infinity", "-Infinity", "-0.0", "-0x0.0"); + test("0.0", "0x0.0", "Infinity", "Infinity"); + test("-0.0", "-0x0.0", "-Infinity", "-Infinity"); + test("1.0", "0x1.0#1", "1.0", "0x1.0#1"); + test("-1.0", "-0x1.0#1", "-1.0", "-0x1.0#1"); + test( + "1.0", + "0x1.0000000000000000000000000#100", + "1.0", + "0x1.0000000000000000000000000#100", + ); + test( + "-1.0", + "-0x1.0000000000000000000000000#100", + "-1.0", + "-0x1.0000000000000000000000000#100", + ); + + test("123.0", "0x7b.0#7", "0.0082", "0x0.0218#7"); + test("-123.0", "-0x7b.0#7", "-0.0082", "-0x0.0218#7"); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + "0.7071067811865475", + "0x0.b504f333f9de60#53", + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + "-0.7071067811865475", + "-0x0.b504f333f9de60#53", + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + "0.31830988618379069", + "0x0.517cc1b727220c#53", + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + "-0.31830988618379069", + "-0x0.517cc1b727220c#53", + ); + + // - x.is_power_of_2() in reciprocal_prec_round + // - !x.is_power_of_2() in reciprocal_prec_round + // - in reciprocal_float_significand_same_prec_lt_w + // - x != HIGH_BIT in reciprocal_float_significand_same_prec_lt_w + // - (q + 2) & (mask >> 1) > 2 in reciprocal_float_significand_same_prec_lt_w; + // - round_bit != 0 || sticky_bit != 0 in reciprocal_float_significand_same_prec_lt_w + // - rm == Nearest in reciprocal_float_significand_same_prec_lt_w + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 && reciprocal & shift_bit != 0) in + // reciprocal_float_significand_same_prec_lt_w + test("1.5", "0x1.8#2", "0.8", "0x0.c#2"); + // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && reciprocal & shift_bit == 0) in + // reciprocal_float_significand_same_prec_lt_w + test("1.2", "0x1.4#3", "0.8", "0x0.c#3"); + // - (q + 2) & (mask >> 1) <= 2 in reciprocal_float_significand_same_prec_lt_w + // - hi == 0 && lo < x first time in reciprocal_float_significand_same_prec_lt_w + // - hi == 0 && lo < x second time in reciprocal_float_significand_same_prec_lt_w + test( + "3615091.606162289805", + "0x372973.9b2d73aac8#61", + "2.7661816322867136e-7", + "0x4.a410e30d72ea318E-6#61", + ); + // - in reciprocal_float_significand_same_prec_w + // - x != HIGH_BIT in reciprocal_float_significand_same_prec_w + // - hi == 0 && lo < x first time in reciprocal_float_significand_same_prec_w + // - hi == 0 && lo < x second time in reciprocal_float_significand_same_prec_w + // - !round_bit in reciprocal_float_significand_same_prec_w + // - round_bit || sticky_bit != 0 in reciprocal_float_significand_same_prec_w + // - rm == Exact in reciprocal_float_significand_same_prec_w + // - rm == Exact && (!round_bit || sticky_bit == 0 && reciprocal.even()) in + // reciprocal_float_significand_same_prec_w + test( + "1.0000000000000000001", + "0x1.0000000000000002#64", + "0.99999999999999999989", + "0x0.fffffffffffffffe#64", + ); + // - round_bit in reciprocal_float_significand_same_prec_w + // - rm == Exact && round_bit && (sticky_bit != 0 || reciprocal.even() in + // reciprocal_float_significand_same_prec_w + test( + "0.113243462684988497952", + "0x0.1cfd8608b7c32de2a#64", + "8.830531814288645436", + "0x8.d49dbba4a843592#64", + ); + // - in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - x_0 != 0 || x_1 != HIGH_BIT in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - in reciprocal_float_2_approx + // - x_1 != Limb::MAX in reciprocal_float_2_approx + // - yy == 0 in reciprocal_float_2_approx + // - r_0 != 0 || yy == 0 in reciprocal_float_2_approx + // - carry in reciprocal_float_2_approx + // - r_1 == 0 in reciprocal_float_2_approx + // - (q_0.wrapping_add(21)) & (mask >> 1) <= 21 in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + // - s_1 != 0 || s_0 != 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - s_2 > 0 || s_1 > x_1 || s_1 == x_1 && s_0 >= x_0 in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + // - s_1 < x_1 || s_1 == x_1 && s_0 < x_0 in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - round_bit != 0 || sticky_bit != 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - rm == Nearest in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0) in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.00000000000000000005", + "0x1.0000000000000001#65", + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + ); + // - r_1 != 0 in reciprocal_float_2_approx + // - s_1 >= x_1 && (s_1 != x_1 || s_0 >= x_0) in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.00000000000000000011", + "0x1.0000000000000002#65", + "0.99999999999999999989", + "0x0.fffffffffffffffe0#65", + ); + // - yy != 0 in reciprocal_float_2_approx + test( + "1.00000000000000000003", + "0x1.00000000000000008#66", + "0.99999999999999999997", + "0x0.ffffffffffffffff8#66", + ); + // - (q_0.wrapping_add(21)) & (mask >> 1) > 21 in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.00000000000000000016", + "0x1.0000000000000003#65", + "0.99999999999999999984", + "0x0.fffffffffffffffd0#65", + ); + // - rm != Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !carry in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.44020837962004126031156726e28", + "0x2.e891fdf020840728c0894E+23#85", + "6.9434396726939059937558762e-29", + "0x5.804bfffff864a7e6a3c7cE-24#85", + ); + // - s_2 <= 0 && s_1 <= x_1 && (s_1 != x_1 || s_0 < x_0) in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.1066650957130428898050817125418740852e-35", + "0xe.b5c943322fb9cafab82fc881e3c1f4E-30#123", + "90361574054676697026138186100092211.86", + "0x11672b68e1cda153b96db5b555ad33.dc#123", + ); + // - x_1 == Limb::MAX in reciprocal_float_2_approx + test( + "4.9517601571415210995e27", + "0xf.fffffffffffffff8E+22#65", + "2.019483917365790222e-28", + "0x1.0000000000000001E-23#65", + ); + // - !carry in reciprocal_float_2_approx + test( + "1.809457589959748038781206513903043742e-25", + "0x3.800000000000000000000000000000E-21#121", + "5526518032524019084371090.285714285714", + "0x492492492492492492492.4924924924#121", + ); + // - s_1 == 0 && s_0 == 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "4095.75", + "0xfff.c00000000000000000000000000#120", + "0.0002441555270707440639687480925349447598", + "0x0.001000400100040010004001000400100#120", + ); + // - in reciprocal_float_significand_general + // - extra_bit in reciprocal_float_significand_general + // - qs_len < MPFR_DIV_THRESHOLD || ds_len < MPFR_DIV_THRESHOLD in + // reciprocal_float_significand_general + // - rm != Nearest || shift != 0 in reciprocal_float_significand_general + // - ds_len >= qs_2_len in reciprocal_float_significand_general + // - qs_2_len == qs_len in reciprocal_float_significand_general + // - sticky_bit != 0 || sticky_3 != 0 in reciprocal_float_significand_general + // - ds_len <= qs_2_len in reciprocal_float_significand_general + // - ds_len <= qs_2_len && rm == Nearest in reciprocal_float_significand_general + // - cleanup == None in reciprocal_float_significand_general + // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) in + // reciprocal_float_significand_general + // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) && round_bit == 0 + // in reciprocal_float_significand_general + test( + "1.000000000000000000000000000000000000003", + "0x1.00000000000000000000000000000001#129", + "0.999999999999999999999999999999999999997", + "0x0.ffffffffffffffffffffffffffffffff0#129", + ); + // - !extra_bit in reciprocal_float_significand_general + test( + "3.8524937267946719191140399538619613749184e-10", + "0x1.a7960ee660129a7bc6beccda5d8bb012f0E-8#135", + "2595721293.573692163399156109109436743137", + "0x9ab7904d.92dd7d57c55752828aeb2a056a#135", + ); + // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) && round_bit != 0 + // && sticky_bit == 0 in reciprocal_float_significand_general + test( + "59494692712728004820788608585666.4829798", + "0x2eeedb85c9cdc503a8e25ed4fc2.7ba490#129", + "1.680822195062896543011322450000404260061e-32", + "0x5.745f58c91536fd9586859912d6b99220E-27#129", + ); + // - rm == Nearest && shift == 0 in reciprocal_float_significand_general + // - ds_len < qs_2_len in reciprocal_float_significand_general + // - qs_2_len != qs_len in reciprocal_float_significand_general + test( + "2.652265028059746721807174554033221706564e-11", + "0x1.d29765de1f777af51db92558a3d9f542E-9#128", + "37703622730.7776167463689706185944181549", + "0x8c74fa04a.c711e41e7a061938aeb7ca7#128", + ); + // - qs_len >= MPFR_DIV_THRESHOLD && ds_len >= MPFR_DIV_THRESHOLD in + // reciprocal_float_significand_general + // - ds_len < n in reciprocal_float_significand_general + // - !q_high first time in reciprocal_float_significand_general + test( + "99775868891207693182758620905617766484977359141657322302733467080906379945858675686059451\ + 2527853476231275058799551652072546.7114971760702609364731573674336745185834760605451122614\ + 680178551142556046183482705875960001033145321970465204907865385015751310573750415565593472\ + 515573584122133946534420508845514863685042630834456885627933663697385547769664847990486584\ + 336882273751721721644989648370590667737234950547668737865047573751482757356022197920174371\ + 088074314780588737501583713833755004374512024407585163195094394292034507503368814534990168\ + 9912721166210129145585", + "0x1826427338bc8ee8c907c3ce5e6a2a793f6ba67df6e738f22dc8aee7eb1838ddc4290e49186e61bdbedb847\ + d19c5d8c4bf88c62.b624adce6b0a3564827e04608c1aec0c8b10390491e15df75402c1788241935e791ebd5f4\ + 25d73042c03e3bad5f0d11257d8bcdab6c8bae677785865be19fa4f42690ddb02174b09bb2c1c9ce6cf3dc2d80\ + 9f0b0b79c42ae70f14ec682ac3850e91ee3b6ef02555e18758417024bf2e8801a759e710b3ac91f28b15277ff4\ + f6380b7ba380aa56c032ce8db2107bfd99a9c789098467f2b27a7b3e1bb6a9e7804ef8a26a3baea51e9a8da4d5\ + 02af09995fd6ced97b00#1859", + "1.002246345847779005201453959044909523251487705121768272318254782834562788571992915761065\ + 827618366102604676901058851697875789517863827988808181377939460972322574747531876040609995\ + 972589309563651666694269954573404860608746408716939006674422401722850836821062009150256011\ + 720454011696660779666788543360159960577274185817743487975811370456064842946971427355525804\ + 257690941749159301402957505054859414089331855848531064209977516186532202351442372831975270\ + 870077932986581025601789533966442159881772178301189187013534424007199259091978932352502557\ + 2202453587766889671779e-123", + "0xa.99c4846d5eeedd01292b3ecbfdcde3e23e86f2c0de91a7853e3f16d01225356463802a0309555fe6a982a\ + b689ccb12d932eab55b6ffd61c4fdd7cd737afd36bd5acda69948c10851f5fd1a254537be41d4c013aa43aaa09\ + 93fccd821acb36881a3a14540999fa35a76a34b052ec4c6e62c85b8890330ad74145c3af385378890639293f97\ + 87eeb51c942fb1b0480f7e5dcadd2da6f8bbf05ac6e562e773bff36faf231658530929fef9e7c5b84843c5674a\ + 883eede0deef889addd0d20f57f1eaeb61dfb8dd23ed0ba6dfc00929192924d8b397f3d5d4913b580d5176e47b\ + 5900b7857bdc095ca14E-103#1859", + ); + // - r_0 == 0 && yy != 0 in reciprocal_float_2_approx + test( + "206158430208.00000000558794", + "0x3000000000.000000180000#83", + "4.850638409455617268748732e-12", + "0x5.5555555555555552aaabE-10#83", + ); +} + +#[test] +fn test_reciprocal_prec() { + let test = |s, s_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + + let (reciprocal, o) = x.clone().reciprocal_prec(prec); + assert!(reciprocal.is_valid()); + + assert_eq!(reciprocal.to_string(), out); + assert_eq!(to_hex_string(&reciprocal), out_hex); + assert_eq!(o, o_out); + + let (reciprocal_alt, o_alt) = x.reciprocal_prec_ref(prec); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal), + ComparableFloatRef(&reciprocal_alt) + ); + assert_eq!(o_alt, o_out); + + let mut reciprocal_alt = x.clone(); + let o_alt = reciprocal_alt.reciprocal_prec_assign(prec); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal), + ComparableFloatRef(&reciprocal_alt) + ); + assert_eq!(o_alt, o_out); + + let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + let (rug_reciprocal, rug_o) = rug_reciprocal_prec(&rug::Float::exact_from(&x), prec); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_reciprocal)), + ComparableFloatRef(&reciprocal), + ); + assert_eq!(rug_o, o); + }; + test("NaN", "NaN", 1, "NaN", "NaN", Equal); + test("Infinity", "Infinity", 1, "0.0", "0x0.0", Equal); + test("-Infinity", "-Infinity", 1, "-0.0", "-0x0.0", Equal); + test("0.0", "0x0.0", 1, "Infinity", "Infinity", Equal); + test("-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal); + test("1.0", "0x1.0#1", 1, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", 10, "1.0", "0x1.000#10", Equal); + test("-1.0", "-0x1.0#1", 1, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", 10, "-1.0", "-0x1.000#10", Equal); + test( + "1.0", + "0x1.0000000000000000000000000#100", + 1, + "1.0", + "0x1.0#1", + Equal, + ); + test( + "-1.0", + "-0x1.0000000000000000000000000#100", + 1, + "-1.0", + "-0x1.0#1", + Equal, + ); + + test("123.0", "0x7b.0#7", 1, "0.008", "0x0.02#1", Less); + test("123.0", "0x7b.0#7", 10, "0.00813", "0x0.0215#10", Greater); + test("-123.0", "-0x7b.0#7", 1, "-0.008", "-0x0.02#1", Greater); + test("-123.0", "-0x7b.0#7", 10, "-0.00813", "-0x0.0215#10", Less); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 1, + "0.5", + "0x0.8#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 10, + "0.707", + "0x0.b50#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 1, + "-0.5", + "-0x0.8#1", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 10, + "-0.707", + "-0x0.b50#10", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + "0.2", + "0x0.4#1", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + "0.3184", + "0x0.518#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + "-0.3184", + "-0x0.518#10", + Less, + ); + + // yyy + + // - in reciprocal_float_significand_short + // - in limbs_reciprocal_limb_to_out_mod_with_fraction + // - fraction_len != 0 in limbs_reciprocal_limb_to_out_mod_with_fraction + // - out_last == 0 in reciprocal_float_significand_short + // - out_last == 0 && shift != 0 in reciprocal_float_significand_short + // - round_bit == 0 && sticky_bit != 0 in reciprocal_float_significand_short + // - rm == Nearest in reciprocal_float_significand_short + // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && out[0] & shift_bit == 0) in + // reciprocal_float_significand_short + test("1.5", "0x1.8#2", 1, "0.5", "0x0.8#1", Less); + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & shift_bit != 0) in + // reciprocal_float_significand_short + test("1.5", "0x1.8#2", 4, "0.7", "0x0.b#4", Greater); + // - ds_len > qs_2_len in reciprocal_float_significand_general + // - inex != Equal in reciprocal_float_significand_general + // - ds_len > qs_2_len && rm == Nearest in reciprocal_float_significand_general + // - sticky_3 > 1 in reciprocal_float_significand_general + test( + "0.000199046277632504184666664672269768242929310652018203552191617720205649", + "0x0.000d0b7140b8f3aea60aad60c1dc3b2ee0d83e2eba33dcfb6f874df52d78#225", + 26, + "5023.9573", + "0x139f.f510#26", + Less, + ); + // - out_last == 0 && shift == 0 in reciprocal_float_significand_short + // - out_last == 0 && shift == 0 && c >= y - c + test( + "1.4904942e-19", + "0x2.bfddbE-16#22", + 64, + "6709184284559176977.0", + "0x5d1bcf8f5dc87511.0#64", + Greater, + ); + // - sticky_3 <= 1 in reciprocal_float_significand_general + // - !q_high second time in reciprocal_float_significand_general + // - !q_high_2 in reciprocal_float_significand_general + // - cmp_s_r != Equal in reciprocal_float_significand_general + // - cmp_s_r <= Equal first time in reciprocal_float_significand_general + test( + "13104.5238818416080254535", + "0x3330.861d1ed0acba8a3a#77", + 61, + "0.00007630952555137529844", + "0x0.00050042eaa75fe3e40#61", + Less, + ); + // - cmp_s_r > Equal first time in reciprocal_float_significand_general + // - cmp_s_r > Equal && !q_high_2 in reciprocal_float_significand_general + // - cmp_s_r <= Equal second time in reciprocal_float_significand_general + // - sticky_3 != 1 && round_bit != 0 in reciprocal_float_significand_general + test( + "4047252243163522937320069504914937843.384444039", + "0x30b78f117589e437888c5573227d7f3.626aecb#150", + 126, + "2.47081214591743090926825573642415225879e-37", + "0x5.413cf35bf8a6be7eed9713c3529cac4E-31#126", + Less, + ); + // - out_last == 0 && shift == 0 && c < y - c in reciprocal_float_significand_short + test( + "0.252", + "0x0.408#8", + 64, + "3.9689922480620155039", + "0x3.f80fe03f80fe03f8#64", + Less, + ); + // - sticky_3 != 1 && round_bit == 0 in reciprocal_float_significand_general + // - cmp_s_r != Equal || shift != 0 in reciprocal_float_significand_general + // - rm == Nearest || ((rm == Ceiling || rm == Up) && inex != Equal) in + // reciprocal_float_significand_general + // - cleanup == TruncateCheckQHigh in reciprocal_float_significand_general + // - !q_high third time in reciprocal_float_significand_general + test( + "13486082141.77132281557478202754", + "0x323d5485d.c575697b8d65625d0#99", + 60, + "7.41505197349076425e-11", + "0x5.187840c7b7df518E-9#60", + Greater, + ); + // - sticky_3 == 1 in reciprocal_float_significand_general + test( + "1.22280082196367917099634553e-19", + "0x2.41738c7082eda42f40f3f0E-16#87", + 62, + "8177946743559704448.0", + "0x717de73c11f04f80.0#62", + Less, + ); + // - cmp_s_r > Equal second time in reciprocal_float_significand_general + // - cmp_s_r > Equal && rm == Nearest in reciprocal_float_significand_general + // - cmp_s_r > Equal && rm == Nearest && shift == 1 in reciprocal_float_significand_general + // - cmp_s_r > Equal && rm == Nearest && shift == 1 && round_bit == 0 in + // reciprocal_float_significand_general + // - cleanup == Sub2Ulp in reciprocal_float_significand_general + test( + "18686733767405.50192797818236099916512095073138146049740456616", + "0x10fed820d2ed.807e5a1b3d9ab71287cc373ef7f3521609fa72f#201", + 63, + "5.351389988464750895e-14", + "0xf.1015372ed29c6daE-12#63", + Less, + ); + // - cmp_s_r > Equal && rm == Nearest && shift == 1 && round_bit != 0 in + // reciprocal_float_significand_general + test( + "5.1485428388978050057923204436e-7", + "0x8.a348459137c894fe7ce2ce4E-6#94", + 63, + "1942297.1339480570737", + "0x1da319.224a6b7c7e8#63", + Greater, + ); + // - q_high second time in reciprocal_float_significand_general + // - q_high third time in reciprocal_float_significand_general + test( + "77371252455336267181195267.98438", + "0x4000000000000000000003.fc00#101", + 21, + "1.29247e-26", + "0x4.00000E-22#21", + Greater, + ); + // - cmp_s_r > Equal && rm == Nearest && shift != 1 in reciprocal_float_significand_general + test( + "2658455991647202407967140029027844095.999984793", + "0x2000000003fffdfffffffffff7fffff.ffff00e#150", + 126, + "3.76158192252184441821673862447332945247e-37", + "0x7.ffffffff000080001fffe0020400060E-31#126", + Greater, + ); + // - cmp_s_r == Equal in reciprocal_float_significand_general + // - !slice_test_zero(sp_lo) in reciprocal_float_significand_general + test( + "1.00000000000000000000000000000000000000000000035028", + "0x1.00000000000000000000000000000000000001fff#165", + 9, + "1.0", + "0x1.00#9", + Greater, + ); + // - ds_len >= n in reciprocal_float_significand_general + test( + "0.055494458197186880675630915676192867532090892470422627386324587939238035948781984969197\ + 293549419550977162311955781124943110956302191334821801709357381779895051695270613703928454\ + 324596584327643817343816609304133584205767499993731432854297161698269943482406592768874444\ + 537959922587924718339566077249075342435855861361805700477320039260219431275491192763683820\ + 335274971653357747385666948482136785955293678142161982025522843889154198503897563042426395\ + 128128925013857602497675148024154470366154782845358820106881972937537492453282371069714224\ + 342987087633028783648188309716648625167308459669051113846104707695985727291553732092985376\ + 828259777127224883258056131830095048084139109366273880047266946456087245977725112865710579\ + 525111935320391211042996099454878241904334424644681645423208503968089041208566140555448097\ + 852910157786980160921009881876094041863058139126904649967001982231878732430835123816538920\ + 677999964668461960985136485079991108378659476109039768366016053541284627738754596865400997\ + 112674267336505852768050602674774522669073467755292625683686148376948941511306559626232154\ + 752250188007464931234370449669484827725942224651581822979291904312419637250173763557353262\ + 213949126273235198961215664565140295983002285722717251104994492638175694612259962414559660\ + 670986455111669460799863783422503680534332809871688740315758114042751185650495859242221856\ + 676315059490112305738127164937772981750053994564437960009449100953381044642977719710987666\ + 446442147625231494914221140350124646594870978197268779196749153799654193158076220975432784\ + 285250458268961487489605062990550609833462756239703423977438296502233632161406744847227123\ + 129345837972247611423244017961911382138681216321381679915794615975763676728759826413970576\ + 860022980739678182223426387634227578298610034617798500806276338343012622846552838812662393\ + 624312342667652111927682534015047744310614980669350777266223429538479188836406048087315918\ + 309894499222120214872928367335411152843249721184424372084873571670196566303743654124450236\ + 183156500319414376380635601282651645722305689309629762280330704861001884908133936528480642\ + 756123234", + "0x0.0e34e28310efa672de91bbf3447b991e67d8318cdf0c4058e4c9c730c71dc5b4bf675e849e3ac19fa3e70\ + d9cbfb926620de7c9c66fc396364a70516bd66e253f5b318c8f82fabc4da09cab178fa55b2cd32603f085d4149\ + a70fb07eb0959a5a78a00603aae495e7a094d9ee04b63747d7a023fb4369e5bf83efc20d6dfe31bafee72256df\ + 1e39a8949cb554b519bb7b532f0ffb97b7fe5238cb68f0cfca74556fd7588422c7b383f4183a4193de48c69bae\ + 7faf54820ec3c71871cbb288daf37266ee4f1fd3e40e483ed25f601b87f9c4a92b8cec5ec0e8d7edbd4234fba3\ + 1a0a463a29b8f32d02f0d1f55195b2ec33db71548c7ccaf7e3a658ee71d308649653be586268e028c9f15d7788\ + cbbd9d825fadf58d6f13183242c54015f254a271b4c89cfc1d82fc8c6182b0d0c620d53cf81728d495822994c6\ + 63bb058d661f74be0ae8c8c10381afa72bc89a2a01da15a5f6d117b31e04e34a6e11e0aa8ad521b7a6117ce813\ + b8e9326335c30e14052e4aa58c9062245ce2b058e7ca1221aa19af3c21653dac76aa59bb843a7a0ad8c6e22992\ + 639766e47bfcc7de81f7a5a43e5faba0bd029002632b5d26d5a4303d9bbf4cf2664d57e50df98491d49ceb0f2f\ + a1db2579ec23c459066023beebebd800fc879d76d59a3d6d2949650b07ef7b31e752ca051f4f107c7ff4af3f56\ + 43eb287784ebcbcbefaa6a9496458e1b5afa0a74a27a47545d2f9091189f54f315a8bc904dedd3248f8cfbf32b\ + 19df9037d47bd021b075b70aaa2087c30b755c65f93508e4564f2d998430e8f68565d451de80e317a96c18493e\ + 662aa4f6ed98647d9051d9c993accc85820fe55a06d956025618ac1fbd020af906edd248ee088ee34f3ec8fc99\ + 1e9392efafd1acd495d65fe834644d939ef5fa91d984969c79257afb98f8d94a3551a1a4b533c182b0d198d8a9\ + 53e030b1532cd0e54117934099dd0b0027cd6058fb4190686ba78ded239aca8ac146e13f4c88052537903cb587\ + 95eae03289ef10a0dee81bb143567c686a600364a57829437fc75160f8660a0ac48daacd98471fb2c0c490cd90\ + 2cea0ea9aa3a814462dd78ab7d573f356b8c0ee7ac1f0c13819e3aeb5b2c8ea9f3a386bf90e5898fb38867db59\ + a9e8ae436df1ececb24a9e478c52dd17ad020f761aca8761acb63eb70ac73687a85f5fc45a10ab7873104f3489\ + 9df7961eaa91080cf7a#6892", + 2006, + "18.01981733827778674260325184800154550178488687484021553354418910902303106544992907597073\ + 029189149288233180017138039419588169269797921955767649134253967949783482048904124978427680\ + 356665076989426379081885511868423028921432842040598017121872298172949413285212017353511719\ + 635837927429422415155120291649700552853758008370658383590920718577880818445566446372050296\ + 508733341553853089827665379953621398768316388977766832203115700511569639084749508682625973\ + 200934933860726967306493882349632958444320046459537281159643562613023877018494385007867594\ + 9194217635032456311998703209522721567033904823795308705191538464412", + "0x12.0512bfc3cbff370e13079bf70f24c8fc14fb1154aa0638c41252b425cfb276f04379cf0908b1732ae3ca\ + 5d5ce2ef398eca257c87dfb650e9648bf8397dd443e42a5fd3663c3d58b9b6cd2a1ebf3c9246c45a1f6086158e\ + a1e93d0f78945b71e8bdf265700c826de9776e648ce900159a0f4f2716ec326e2b8289920112637767e8fee268\ + 3363b8e4c4bf07c685c226e6b97d260fdc2910d7e8a10fada9bda175aeb73def046bae399c664bfe3cfb3f7e73\ + 136427cf5ca96cad226976adc2a9a0117dd38cbd0aaf5edbdb6a9e925126c38670a8946bc5ee1840200876c486\ + de477d9c4b50e410143b115c27f9ba57c1176894c9d33effdbbd50928#2006", + Less, + ); + // - q_high first time in reciprocal_float_significand_general + // - !round_helper_2 in reciprocal_float_significand_general + test( + "3.725290298461914062500000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000011016237598729697344643067035553076048795855845749823769296583726265856513\ + 808851994012395922156678620494270052333942368952051919368238891272218333e-9", + "0x1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000003fffffffffffffffffffffffffffffffffffffffffffff\ + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeE-7#3520", + 1969, + "268435456.0", + "0x10000000.000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ + 00000000000000000000000000000000000000000000000#1969", + Greater, + ); +} + +#[test] +fn reciprocal_prec_fail() { + assert_panic!(Float::NAN.reciprocal_prec(0)); + assert_panic!(Float::NAN.reciprocal_prec_ref(0)); + assert_panic!({ + let mut x = Float::NAN; + x.reciprocal_prec_assign(0) + }); +} + +#[test] +fn test_reciprocal_round() { + let test = |s, s_hex, rm, out: &str, out_hex: &str, o_out| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + + let (reciprocal, o) = x.clone().reciprocal_round(rm); + assert!(reciprocal.is_valid()); + + assert_eq!(reciprocal.to_string(), out); + assert_eq!(to_hex_string(&reciprocal), out_hex); + assert_eq!(o, o_out); + + let (reciprocal_alt, o_alt) = x.reciprocal_round_ref(rm); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal), + ComparableFloatRef(&reciprocal_alt) + ); + assert_eq!(o_alt, o_out); + + let mut reciprocal_alt = x.clone(); + let o_alt = reciprocal_alt.reciprocal_round_assign(rm); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal), + ComparableFloatRef(&reciprocal_alt) + ); + assert_eq!(o_alt, o_out); + + let (reciprocal_alt, o_alt) = + reciprocal_prec_round_naive_1(x.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + let (reciprocal_alt, o_alt) = + reciprocal_prec_round_naive_2(x.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_reciprocal, rug_o) = rug_reciprocal_round(&rug::Float::exact_from(&x), rm); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_reciprocal)), + ComparableFloatRef(&reciprocal), + ); + assert_eq!(rug_o, o); + } + }; + test("NaN", "NaN", Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", Down, "NaN", "NaN", Equal); + test("NaN", "NaN", Up, "NaN", "NaN", Equal); + test("NaN", "NaN", Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", Exact, "NaN", "NaN", Equal); + + test("Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", Down, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", Up, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal); + + test("-Infinity", "-Infinity", Floor, "-0.0", "-0x0.0", Equal); + test("-Infinity", "-Infinity", Ceiling, "-0.0", "-0x0.0", Equal); + test("-Infinity", "-Infinity", Down, "-0.0", "-0x0.0", Equal); + test("-Infinity", "-Infinity", Up, "-0.0", "-0x0.0", Equal); + test("-Infinity", "-Infinity", Nearest, "-0.0", "-0x0.0", Equal); + test("-Infinity", "-Infinity", Exact, "-0.0", "-0x0.0", Equal); + + test("0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", Down, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", Up, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal); + + test("-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal); + test("-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal); + test("-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal); + test("-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal); + test("-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal); + test("-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal); + + test("1.0", "0x1.0#1", Floor, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", Ceiling, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", Down, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", Up, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", Exact, "1.0", "0x1.0#1", Equal); + + test("-1.0", "-0x1.0#1", Floor, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", Ceiling, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", Down, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", Up, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", Nearest, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", Exact, "-1.0", "-0x1.0#1", Equal); + + test( + "1.0", + "0x1.0000000000000000000000000#100", + Floor, + "1.0", + "0x1.0000000000000000000000000#100", + Equal, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + Ceiling, + "1.0", + "0x1.0000000000000000000000000#100", + Equal, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + Down, + "1.0", + "0x1.0000000000000000000000000#100", + Equal, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + Up, + "1.0", + "0x1.0000000000000000000000000#100", + Equal, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + Nearest, + "1.0", + "0x1.0000000000000000000000000#100", + Equal, + ); + test( + "1.0", + "0x1.0000000000000000000000000#100", + Exact, + "1.0", + "0x1.0000000000000000000000000#100", + Equal, + ); + + test( + "-1.0", + "-0x1.0000000000000000000000000#100", + Floor, + "-1.0", + "-0x1.0000000000000000000000000#100", + Equal, + ); + test( + "-1.0", + "-0x1.0000000000000000000000000#100", + Ceiling, + "-1.0", + "-0x1.0000000000000000000000000#100", + Equal, + ); + test( + "-1.0", + "-0x1.0000000000000000000000000#100", + Down, + "-1.0", + "-0x1.0000000000000000000000000#100", + Equal, + ); + test( + "-1.0", + "-0x1.0000000000000000000000000#100", + Up, + "-1.0", + "-0x1.0000000000000000000000000#100", + Equal, + ); + test( + "-1.0", + "-0x1.0000000000000000000000000#100", + Nearest, + "-1.0", + "-0x1.0000000000000000000000000#100", + Equal, + ); + test( + "-1.0", + "-0x1.0000000000000000000000000#100", + Exact, + "-1.0", + "-0x1.0000000000000000000000000#100", + Equal, + ); + + test("123.0", "0x7b.0#7", Floor, "0.0081", "0x0.0210#7", Less); + test( + "123.0", + "0x7b.0#7", + Ceiling, + "0.0082", + "0x0.0218#7", + Greater, + ); + test("123.0", "0x7b.0#7", Down, "0.0081", "0x0.0210#7", Less); + test("123.0", "0x7b.0#7", Up, "0.0082", "0x0.0218#7", Greater); + test( + "123.0", + "0x7b.0#7", + Nearest, + "0.0082", + "0x0.0218#7", + Greater, + ); + + test("-123.0", "-0x7b.0#7", Floor, "-0.0082", "-0x0.0218#7", Less); + test( + "-123.0", + "-0x7b.0#7", + Ceiling, + "-0.0081", + "-0x0.0210#7", + Greater, + ); + test( + "-123.0", + "-0x7b.0#7", + Down, + "-0.0081", + "-0x0.0210#7", + Greater, + ); + test("-123.0", "-0x7b.0#7", Up, "-0.0082", "-0x0.0218#7", Less); + test( + "-123.0", + "-0x7b.0#7", + Nearest, + "-0.0082", + "-0x0.0218#7", + Less, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + Floor, + "0.7071067811865475", + "0x0.b504f333f9de60#53", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + Ceiling, + "0.7071067811865476", + "0x0.b504f333f9de68#53", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + Down, + "0.7071067811865475", + "0x0.b504f333f9de60#53", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + Up, + "0.7071067811865476", + "0x0.b504f333f9de68#53", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + Nearest, + "0.7071067811865475", + "0x0.b504f333f9de60#53", + Less, + ); + + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + Floor, + "-0.7071067811865476", + "-0x0.b504f333f9de68#53", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + Ceiling, + "-0.7071067811865475", + "-0x0.b504f333f9de60#53", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + Down, + "-0.7071067811865475", + "-0x0.b504f333f9de60#53", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + Up, + "-0.7071067811865476", + "-0x0.b504f333f9de68#53", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + Nearest, + "-0.7071067811865475", + "-0x0.b504f333f9de60#53", + Greater, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Floor, + "0.31830988618379064", + "0x0.517cc1b7272208#53", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Ceiling, + "0.31830988618379069", + "0x0.517cc1b727220c#53", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Down, + "0.31830988618379064", + "0x0.517cc1b7272208#53", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Up, + "0.31830988618379069", + "0x0.517cc1b727220c#53", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + Nearest, + "0.31830988618379069", + "0x0.517cc1b727220c#53", + Greater, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Floor, + "-0.31830988618379069", + "-0x0.517cc1b727220c#53", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Ceiling, + "-0.31830988618379064", + "-0x0.517cc1b7272208#53", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Down, + "-0.31830988618379064", + "-0x0.517cc1b7272208#53", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Up, + "-0.31830988618379069", + "-0x0.517cc1b727220c#53", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + Nearest, + "-0.31830988618379069", + "-0x0.517cc1b727220c#53", + Less, + ); + + // yyy + + // - rm == Floor || rm == Down in reciprocal_float_significand_same_prec_lt_w + test("1.5", "0x1.8#2", Down, "0.5", "0x0.8#2", Less); + // - rm == Ceiling || rm == Up in reciprocal_float_significand_same_prec_lt_w + test("1.5", "0x1.8#2", Up, "0.8", "0x0.c#2", Greater); + // - rm == Floor || rm == Down in reciprocal_float_significand_same_prec_w + test( + "1.0000000000000000001", + "0x1.0000000000000002#64", + Down, + "0.99999999999999999989", + "0x0.fffffffffffffffe#64", + Less, + ); + // - rm == Ceiling || rm == Up in reciprocal_float_significand_same_prec_w + test( + "1.0000000000000000001", + "0x1.0000000000000002#64", + Up, + "0.99999999999999999995", + "0x0.ffffffffffffffff#64", + Greater, + ); + // - rm == Floor || rm == Down in reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.00000000000000000005", + "0x1.0000000000000001#65", + Down, + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + Less, + ); + // - rm == Ceiling || rm == Up in reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.00000000000000000005", + "0x1.0000000000000001#65", + Up, + "0.99999999999999999997", + "0x0.ffffffffffffffff8#65", + Greater, + ); + // - ds_len <= qs_2_len && rm == Ceiling || rm == Up && inex != Equal in + // reciprocal_float_significand_general + // - cleanup == None && (rm == Ceiling || rm == Up) && (round_bit != 0 || sticky_bit != 0) in + // reciprocal_float_significand_general + test( + "2.4914040842493675536005152793625253098043524808533216867315977e-8", + "0x6.b014710df6d8d0fb1901206ed24e1e002b4411ac77d2348fd2E-7#202", + Up, + "40138009.17811728321982547739205337771132288200540084196230409", + "0x2647519.2d9918224811b1eb5289a86e1aa22ec284493440dbd2#202", + Greater, + ); + // - ds_len <= qs_2_len && rm == Floor || rm == Down || (rm != Nearest && inex == Equal) in + // reciprocal_float_significand_general + // - cleanup == None && (rm == Floor || rm == Down || round_bit == 0 && sticky_bit == 0) in + // reciprocal_float_significand_general + test( + "2.4914040842493675536005152793625253098043524808533216867315977e-8", + "0x6.b014710df6d8d0fb1901206ed24e1e002b4411ac77d2348fd2E-7#202", + Down, + "40138009.17811728321982547739205337771132288200540084196230408", + "0x2647519.2d9918224811b1eb5289a86e1aa22ec284493440dbd1#202", + Less, + ); + + // - x.is_power_of_2() in reciprocal_prec_round + // - !x.is_power_of_2() in reciprocal_prec_round + // - in reciprocal_float_significand_same_prec_lt_w + // - x != HIGH_BIT in reciprocal_float_significand_same_prec_lt_w + // - (q + 2) & (mask >> 1) > 2 in reciprocal_float_significand_same_prec_lt_w; + // - round_bit != 0 || sticky_bit != 0 in reciprocal_float_significand_same_prec_lt_w + // - rm == Nearest in reciprocal_float_significand_same_prec_lt_w + // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 && reciprocal & shift_bit != 0) in + // reciprocal_float_significand_same_prec_lt_w + test("1.5", "0x1.8#2", Nearest, "0.8", "0x0.c#2", Greater); + // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && reciprocal & shift_bit == 0) in + // reciprocal_float_significand_same_prec_lt_w + test("1.2", "0x1.4#3", Nearest, "0.8", "0x0.c#3", Less); + // - (q + 2) & (mask >> 1) <= 2 in reciprocal_float_significand_same_prec_lt_w + // - hi == 0 && lo < x first time in reciprocal_float_significand_same_prec_lt_w + // - hi == 0 && lo < x second time in reciprocal_float_significand_same_prec_lt_w + test( + "3615091.606162289805", + "0x372973.9b2d73aac8#61", + Nearest, + "2.7661816322867136e-7", + "0x4.a410e30d72ea318E-6#61", + Less, + ); + // - in reciprocal_float_significand_same_prec_w + // - x != HIGH_BIT in reciprocal_float_significand_same_prec_w + // - hi == 0 && lo < x first time in reciprocal_float_significand_same_prec_w + // - hi == 0 && lo < x second time in reciprocal_float_significand_same_prec_w + // - !round_bit in reciprocal_float_significand_same_prec_w + // - round_bit || sticky_bit != 0 in reciprocal_float_significand_same_prec_w + // - rm == Exact in reciprocal_float_significand_same_prec_w + // - rm == Exact && (!round_bit || sticky_bit == 0 && reciprocal.even()) in + // reciprocal_float_significand_same_prec_w + test( + "1.0000000000000000001", + "0x1.0000000000000002#64", + Nearest, + "0.99999999999999999989", + "0x0.fffffffffffffffe#64", + Less, + ); + // - round_bit in reciprocal_float_significand_same_prec_w + // - rm == Exact && round_bit && (sticky_bit != 0 || reciprocal.even() in + // reciprocal_float_significand_same_prec_w + test( + "0.113243462684988497952", + "0x0.1cfd8608b7c32de2a#64", + Nearest, + "8.830531814288645436", + "0x8.d49dbba4a843592#64", + Greater, + ); + // - in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - x_0 != 0 || x_1 != HIGH_BIT in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - in reciprocal_float_2_approx + // - x_1 != Limb::MAX in reciprocal_float_2_approx + // - yy == 0 in reciprocal_float_2_approx + // - r_0 != 0 || yy == 0 in reciprocal_float_2_approx + // - carry in reciprocal_float_2_approx + // - r_1 == 0 in reciprocal_float_2_approx + // - (q_0.wrapping_add(21)) & (mask >> 1) <= 21 in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + // - s_1 != 0 || s_0 != 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - s_2 > 0 || s_1 > x_1 || s_1 == x_1 && s_0 >= x_0 in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + // - s_1 < x_1 || s_1 == x_1 && s_0 < x_0 in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - round_bit != 0 || sticky_bit != 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - rm == Nearest in reciprocal_float_significand_same_prec_gt_w_lt_2w + // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0) in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.00000000000000000005", + "0x1.0000000000000001#65", + Nearest, + "0.99999999999999999995", + "0x0.ffffffffffffffff0#65", + Less, + ); + // - r_1 != 0 in reciprocal_float_2_approx + // - s_1 >= x_1 && (s_1 != x_1 || s_0 >= x_0) in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.00000000000000000011", + "0x1.0000000000000002#65", + Nearest, + "0.99999999999999999989", + "0x0.fffffffffffffffe0#65", + Less, + ); + // - yy != 0 in reciprocal_float_2_approx + test( + "1.00000000000000000003", + "0x1.00000000000000008#66", + Nearest, + "0.99999999999999999997", + "0x0.ffffffffffffffff8#66", + Less, + ); + // - (q_0.wrapping_add(21)) & (mask >> 1) > 21 in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.00000000000000000016", + "0x1.0000000000000003#65", + Nearest, + "0.99999999999999999984", + "0x0.fffffffffffffffd0#65", + Less, + ); + // - rm != Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !carry in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.44020837962004126031156726e28", + "0x2.e891fdf020840728c0894E+23#85", + Nearest, + "6.9434396726939059937558762e-29", + "0x5.804bfffff864a7e6a3c7cE-24#85", + Greater, + ); + // - s_2 <= 0 && s_1 <= x_1 && (s_1 != x_1 || s_0 < x_0) in + // reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "1.1066650957130428898050817125418740852e-35", + "0xe.b5c943322fb9cafab82fc881e3c1f4E-30#123", + Nearest, + "90361574054676697026138186100092211.86", + "0x11672b68e1cda153b96db5b555ad33.dc#123", + Greater, + ); + // - x_1 == Limb::MAX in reciprocal_float_2_approx + test( + "4.9517601571415210995e27", + "0xf.fffffffffffffff8E+22#65", + Nearest, + "2.019483917365790222e-28", + "0x1.0000000000000001E-23#65", + Greater, + ); + // - !carry in reciprocal_float_2_approx + test( + "1.809457589959748038781206513903043742e-25", + "0x3.800000000000000000000000000000E-21#121", + Nearest, + "5526518032524019084371090.285714285714", + "0x492492492492492492492.4924924924#121", + Less, + ); + // - s_1 == 0 && s_0 == 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w + test( + "4095.75", + "0xfff.c00000000000000000000000000#120", + Nearest, + "0.0002441555270707440639687480925349447598", + "0x0.001000400100040010004001000400100#120", + Less, + ); + // - in reciprocal_float_significand_general + // - extra_bit in reciprocal_float_significand_general + // - qs_len < MPFR_DIV_THRESHOLD || ds_len < MPFR_DIV_THRESHOLD in + // reciprocal_float_significand_general + // - rm != Nearest || shift != 0 in reciprocal_float_significand_general + // - ds_len >= qs_2_len in reciprocal_float_significand_general + // - qs_2_len == qs_len in reciprocal_float_significand_general + // - sticky_bit != 0 || sticky_3 != 0 in reciprocal_float_significand_general + // - ds_len <= qs_2_len in reciprocal_float_significand_general + // - ds_len <= qs_2_len && rm == Nearest in reciprocal_float_significand_general + // - cleanup == None in reciprocal_float_significand_general + // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) in + // reciprocal_float_significand_general + // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) && round_bit == 0 + // in reciprocal_float_significand_general + test( + "1.000000000000000000000000000000000000003", + "0x1.00000000000000000000000000000001#129", + Nearest, + "0.999999999999999999999999999999999999997", + "0x0.ffffffffffffffffffffffffffffffff0#129", + Less, + ); + // - !extra_bit in reciprocal_float_significand_general + test( + "3.8524937267946719191140399538619613749184e-10", + "0x1.a7960ee660129a7bc6beccda5d8bb012f0E-8#135", + Nearest, + "2595721293.573692163399156109109436743137", + "0x9ab7904d.92dd7d57c55752828aeb2a056a#135", + Less, + ); + // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) && round_bit != 0 + // && sticky_bit == 0 in reciprocal_float_significand_general + test( + "59494692712728004820788608585666.4829798", + "0x2eeedb85c9cdc503a8e25ed4fc2.7ba490#129", + Nearest, + "1.680822195062896543011322450000404260061e-32", + "0x5.745f58c91536fd9586859912d6b99220E-27#129", + Greater, + ); + // - rm == Nearest && shift == 0 in reciprocal_float_significand_general + // - ds_len < qs_2_len in reciprocal_float_significand_general + // - qs_2_len != qs_len in reciprocal_float_significand_general + test( + "2.652265028059746721807174554033221706564e-11", + "0x1.d29765de1f777af51db92558a3d9f542E-9#128", + Nearest, + "37703622730.7776167463689706185944181549", + "0x8c74fa04a.c711e41e7a061938aeb7ca7#128", + Greater, + ); + // - qs_len >= MPFR_DIV_THRESHOLD && ds_len >= MPFR_DIV_THRESHOLD in + // reciprocal_float_significand_general + // - ds_len < n in reciprocal_float_significand_general + // - !q_high first time in reciprocal_float_significand_general + test( + "99775868891207693182758620905617766484977359141657322302733467080906379945858675686059451\ + 2527853476231275058799551652072546.7114971760702609364731573674336745185834760605451122614\ + 680178551142556046183482705875960001033145321970465204907865385015751310573750415565593472\ + 515573584122133946534420508845514863685042630834456885627933663697385547769664847990486584\ + 336882273751721721644989648370590667737234950547668737865047573751482757356022197920174371\ + 088074314780588737501583713833755004374512024407585163195094394292034507503368814534990168\ + 9912721166210129145585", + "0x1826427338bc8ee8c907c3ce5e6a2a793f6ba67df6e738f22dc8aee7eb1838ddc4290e49186e61bdbedb847\ + d19c5d8c4bf88c62.b624adce6b0a3564827e04608c1aec0c8b10390491e15df75402c1788241935e791ebd5f4\ + 25d73042c03e3bad5f0d11257d8bcdab6c8bae677785865be19fa4f42690ddb02174b09bb2c1c9ce6cf3dc2d80\ + 9f0b0b79c42ae70f14ec682ac3850e91ee3b6ef02555e18758417024bf2e8801a759e710b3ac91f28b15277ff4\ + f6380b7ba380aa56c032ce8db2107bfd99a9c789098467f2b27a7b3e1bb6a9e7804ef8a26a3baea51e9a8da4d5\ + 02af09995fd6ced97b00#1859", + Nearest, + "1.002246345847779005201453959044909523251487705121768272318254782834562788571992915761065\ + 827618366102604676901058851697875789517863827988808181377939460972322574747531876040609995\ + 972589309563651666694269954573404860608746408716939006674422401722850836821062009150256011\ + 720454011696660779666788543360159960577274185817743487975811370456064842946971427355525804\ + 257690941749159301402957505054859414089331855848531064209977516186532202351442372831975270\ + 870077932986581025601789533966442159881772178301189187013534424007199259091978932352502557\ + 2202453587766889671779e-123", + "0xa.99c4846d5eeedd01292b3ecbfdcde3e23e86f2c0de91a7853e3f16d01225356463802a0309555fe6a982a\ + b689ccb12d932eab55b6ffd61c4fdd7cd737afd36bd5acda69948c10851f5fd1a254537be41d4c013aa43aaa09\ + 93fccd821acb36881a3a14540999fa35a76a34b052ec4c6e62c85b8890330ad74145c3af385378890639293f97\ + 87eeb51c942fb1b0480f7e5dcadd2da6f8bbf05ac6e562e773bff36faf231658530929fef9e7c5b84843c5674a\ + 883eede0deef889addd0d20f57f1eaeb61dfb8dd23ed0ba6dfc00929192924d8b397f3d5d4913b580d5176e47b\ + 5900b7857bdc095ca14E-103#1859", + Greater, + ); + // - r_0 == 0 && yy != 0 in reciprocal_float_2_approx + test( + "206158430208.00000000558794", + "0x3000000000.000000180000#83", + Nearest, + "4.850638409455617268748732e-12", + "0x5.5555555555555552aaabE-10#83", + Greater, + ); +} + +#[test] +fn reciprocal_round_fail() { + const THREE: Float = Float::const_from_unsigned(3); + assert_panic!(THREE.reciprocal_round(Exact)); + assert_panic!(THREE.reciprocal_round_ref(Exact)); + assert_panic!({ + let mut x = THREE; + x.reciprocal_round_assign(Exact); + }); +} + +#[test] +fn test_reciprocal_prec_round() { + let test = |s, s_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { + let x = parse_hex_string(s_hex); + assert_eq!(x.to_string(), s); + + let (reciprocal, o) = x.clone().reciprocal_prec_round(prec, rm); + assert!(reciprocal.is_valid()); + + assert_eq!(reciprocal.to_string(), out); + assert_eq!(to_hex_string(&reciprocal), out_hex); + assert_eq!(o, o_out); + + let (reciprocal_alt, o_alt) = x.reciprocal_prec_round_ref(prec, rm); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal), + ComparableFloatRef(&reciprocal_alt) + ); + assert_eq!(o_alt, o_out); + + let mut reciprocal_alt = x.clone(); + let o_alt = reciprocal_alt.reciprocal_prec_round_assign(prec, rm); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal), + ComparableFloatRef(&reciprocal_alt) + ); + assert_eq!(o_alt, o_out); + + let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_reciprocal, rug_o) = + rug_reciprocal_prec_round(&rug::Float::exact_from(&x), prec, rm); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_reciprocal)), + ComparableFloatRef(&reciprocal), + ); + assert_eq!(rug_o, o); + } + }; + test("NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); + test("NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); + test("NaN", "NaN", 1, Down, "NaN", "NaN", Equal); + test("NaN", "NaN", 1, Up, "NaN", "NaN", Equal); + test("NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); + test("NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); + + test("Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal); + test("Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal); + + test("-Infinity", "-Infinity", 1, Floor, "-0.0", "-0x0.0", Equal); + test( + "-Infinity", + "-Infinity", + 1, + Ceiling, + "-0.0", + "-0x0.0", + Equal, + ); + test("-Infinity", "-Infinity", 1, Down, "-0.0", "-0x0.0", Equal); + test("-Infinity", "-Infinity", 1, Up, "-0.0", "-0x0.0", Equal); + test( + "-Infinity", + "-Infinity", + 1, + Nearest, + "-0.0", + "-0x0.0", + Equal, + ); + test("-Infinity", "-Infinity", 1, Exact, "-0.0", "-0x0.0", Equal); + + test("0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal); + test("0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal); + + test("-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal); + test( + "-0.0", + "-0x0.0", + 1, + Ceiling, + "-Infinity", + "-Infinity", + Equal, + ); + test("-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal); + test("-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal); + test( + "-0.0", + "-0x0.0", + 1, + Nearest, + "-Infinity", + "-Infinity", + Equal, + ); + test("-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal); + + test("1.0", "0x1.0#1", 1, Floor, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", 1, Ceiling, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", 1, Down, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", 1, Up, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", 1, Nearest, "1.0", "0x1.0#1", Equal); + test("1.0", "0x1.0#1", 1, Exact, "1.0", "0x1.0#1", Equal); + + test("-1.0", "-0x1.0#1", 1, Floor, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", 1, Ceiling, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", 1, Down, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", 1, Up, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", 1, Nearest, "-1.0", "-0x1.0#1", Equal); + test("-1.0", "-0x1.0#1", 1, Exact, "-1.0", "-0x1.0#1", Equal); + + test("1.0", "0x1.0#1", 10, Floor, "1.0", "0x1.000#10", Equal); + test("1.0", "0x1.0#1", 10, Ceiling, "1.0", "0x1.000#10", Equal); + test("1.0", "0x1.0#1", 10, Down, "1.0", "0x1.000#10", Equal); + test("1.0", "0x1.0#1", 10, Up, "1.0", "0x1.000#10", Equal); + test("1.0", "0x1.0#1", 10, Nearest, "1.0", "0x1.000#10", Equal); + test("1.0", "0x1.0#1", 10, Exact, "1.0", "0x1.000#10", Equal); + + test("-1.0", "-0x1.0#1", 10, Floor, "-1.0", "-0x1.000#10", Equal); + test( + "-1.0", + "-0x1.0#1", + 10, + Ceiling, + "-1.0", + "-0x1.000#10", + Equal, + ); + test("-1.0", "-0x1.0#1", 10, Down, "-1.0", "-0x1.000#10", Equal); + test("-1.0", "-0x1.0#1", 10, Up, "-1.0", "-0x1.000#10", Equal); + test( + "-1.0", + "-0x1.0#1", + 10, + Nearest, + "-1.0", + "-0x1.000#10", + Equal, + ); + test("-1.0", "-0x1.0#1", 10, Exact, "-1.0", "-0x1.000#10", Equal); + + test("123.0", "0x7b.0#7", 1, Floor, "0.008", "0x0.02#1", Less); + test("123.0", "0x7b.0#7", 1, Ceiling, "0.02", "0x0.04#1", Greater); + test("123.0", "0x7b.0#7", 1, Down, "0.008", "0x0.02#1", Less); + test("123.0", "0x7b.0#7", 1, Up, "0.02", "0x0.04#1", Greater); + test("123.0", "0x7b.0#7", 1, Nearest, "0.008", "0x0.02#1", Less); + + test("-123.0", "-0x7b.0#7", 1, Floor, "-0.02", "-0x0.04#1", Less); + test( + "-123.0", + "-0x7b.0#7", + 1, + Ceiling, + "-0.008", + "-0x0.02#1", + Greater, + ); + test( + "-123.0", + "-0x7b.0#7", + 1, + Down, + "-0.008", + "-0x0.02#1", + Greater, + ); + test("-123.0", "-0x7b.0#7", 1, Up, "-0.02", "-0x0.04#1", Less); + test( + "-123.0", + "-0x7b.0#7", + 1, + Nearest, + "-0.008", + "-0x0.02#1", + Greater, + ); + + test( + "123.0", + "0x7b.0#7", + 10, + Floor, + "0.00812", + "0x0.0214#10", + Less, + ); + test( + "123.0", + "0x7b.0#7", + 10, + Ceiling, + "0.00813", + "0x0.0215#10", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + 10, + Down, + "0.00812", + "0x0.0214#10", + Less, + ); + test( + "123.0", + "0x7b.0#7", + 10, + Up, + "0.00813", + "0x0.0215#10", + Greater, + ); + test( + "123.0", + "0x7b.0#7", + 10, + Nearest, + "0.00813", + "0x0.0215#10", + Greater, + ); + + test( + "-123.0", + "-0x7b.0#7", + 10, + Floor, + "-0.00813", + "-0x0.0215#10", + Less, + ); + test( + "-123.0", + "-0x7b.0#7", + 10, + Ceiling, + "-0.00812", + "-0x0.0214#10", + Greater, + ); + test( + "-123.0", + "-0x7b.0#7", + 10, + Down, + "-0.00812", + "-0x0.0214#10", + Greater, + ); + test( + "-123.0", + "-0x7b.0#7", + 10, + Up, + "-0.00813", + "-0x0.0215#10", + Less, + ); + test( + "-123.0", + "-0x7b.0#7", + 10, + Nearest, + "-0.00813", + "-0x0.0215#10", + Less, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 1, + Floor, + "0.5", + "0x0.8#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 1, + Ceiling, + "1.0", + "0x1.0#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 1, + Down, + "0.5", + "0x0.8#1", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 1, + Up, + "1.0", + "0x1.0#1", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 1, + Nearest, + "0.5", + "0x0.8#1", + Less, + ); + + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 1, + Floor, + "-1.0", + "-0x1.0#1", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 1, + Ceiling, + "-0.5", + "-0x0.8#1", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 1, + Down, + "-0.5", + "-0x0.8#1", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 1, + Up, + "-1.0", + "-0x1.0#1", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 1, + Nearest, + "-0.5", + "-0x0.8#1", + Greater, + ); + + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 10, + Floor, + "0.707", + "0x0.b50#10", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 10, + Ceiling, + "0.708", + "0x0.b54#10", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 10, + Down, + "0.707", + "0x0.b50#10", + Less, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 10, + Up, + "0.708", + "0x0.b54#10", + Greater, + ); + test( + "1.4142135623730951", + "0x1.6a09e667f3bcd#53", + 10, + Nearest, + "0.707", + "0x0.b50#10", + Less, + ); + + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 10, + Floor, + "-0.708", + "-0x0.b54#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 10, + Ceiling, + "-0.707", + "-0x0.b50#10", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 10, + Down, + "-0.707", + "-0x0.b50#10", + Greater, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 10, + Up, + "-0.708", + "-0x0.b54#10", + Less, + ); + test( + "-1.4142135623730951", + "-0x1.6a09e667f3bcd#53", + 10, + Nearest, + "-0.707", + "-0x0.b50#10", + Greater, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Floor, + "0.2", + "0x0.4#1", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Ceiling, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Down, + "0.2", + "0x0.4#1", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Up, + "0.5", + "0x0.8#1", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 1, + Nearest, + "0.2", + "0x0.4#1", + Less, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Floor, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Ceiling, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Down, + "-0.2", + "-0x0.4#1", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Up, + "-0.5", + "-0x0.8#1", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 1, + Nearest, + "-0.2", + "-0x0.4#1", + Greater, + ); + + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Floor, + "0.3179", + "0x0.516#10", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Ceiling, + "0.3184", + "0x0.518#10", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Down, + "0.3179", + "0x0.516#10", + Less, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Up, + "0.3184", + "0x0.518#10", + Greater, + ); + test( + "3.1415926535897931", + "0x3.243f6a8885a30#53", + 10, + Nearest, + "0.3184", + "0x0.518#10", + Greater, + ); + + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Floor, + "-0.3184", + "-0x0.518#10", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Ceiling, + "-0.3179", + "-0x0.516#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Down, + "-0.3179", + "-0x0.516#10", + Greater, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Up, + "-0.3184", + "-0x0.518#10", + Less, + ); + test( + "-3.1415926535897931", + "-0x3.243f6a8885a30#53", + 10, + Nearest, + "-0.3184", + "-0x0.518#10", + Less, + ); + + // yyy + + // - rm == Floor || rm == Down in reciprocal_float_significand_short + test("1.5", "0x1.8#2", 1, Down, "0.5", "0x0.8#1", Less); + // - rm == Ceiling || rm == Up in reciprocal_float_significand_short + test("1.5", "0x1.8#2", 1, Up, "1.0", "0x1.0#1", Greater); + // - ds_len > qs_2_len && rm != Nearest in reciprocal_float_significand_general + test( + "2.4914040842493675536005152793625253098043524808533216867315977e-8", + "0x6.b014710df6d8d0fb1901206ed24e1e002b4411ac77d2348fd2E-7#202", + 15, + Up, + "4.0139e7", + "0x2.6478E+6#15", + Greater, + ); + // - rm != Nearest && (rm != Ceiling && rm != Up || inex == Equal) && (rm != Exact || inex != + // Equal) in reciprocal_float_significand_general + // - cleanup == Sub1Ulp in reciprocal_float_significand_general + test( + "1164607425.036820041559", + "0x456a7fc1.096d09ca55#71", + 64, + Down, + "8.586584444697183348e-10", + "0x3.b01add9bdcc8ca28E-8#64", + Less, + ); + // - cmp_s_r > Equal && (rm == Ceiling || rm == Up) in reciprocal_float_significand_general + // - cmp_s_r > Equal && (rm == Ceiling || rm == Up) && shift != 0 in + // reciprocal_float_significand_general + test( + "18686733767405.50192797818236099916512095073138146049740456616", + "0x10fed820d2ed.807e5a1b3d9ab71287cc373ef7f3521609fa72f#201", + 63, + Up, + "5.3513899884647508956e-14", + "0xf.1015372ed29c6dcE-12#63", + Greater, + ); + // - cmp_s_r > Equal && (rm == Floor || rm == Down) in reciprocal_float_significand_general + // - cmp_s_r > Equal && (rm == Floor || rm == Down) && shift != 0 in + // reciprocal_float_significand_general + test( + "18686733767405.50192797818236099916512095073138146049740456616", + "0x10fed820d2ed.807e5a1b3d9ab71287cc373ef7f3521609fa72f#201", + 63, + Down, + "5.351389988464750895e-14", + "0xf.1015372ed29c6daE-12#63", + Less, + ); + // - cmp_s_r > Equal && (rm == Ceiling || rm == Up) && shift == 0 in + // reciprocal_float_significand_general + test( + "1.063382396643406948814112e37", + "0x8.000000007ffffffffff8E+30#81", + 64, + Up, + "9.4039548064414545111e-38", + "0x1.ffffffffe0000002E-31#64", + Greater, + ); + // - cmp_s_r > Equal && (rm == Floor || rm == Down) && shift == 0 in + // reciprocal_float_significand_general + test( + "1.063382396643406948814112e37", + "0x8.000000007ffffffffff8E+30#81", + 64, + Down, + "9.4039548064414545106e-38", + "0x1.ffffffffe0000000E-31#64", + Less, + ); +} + +#[test] +fn reciprocal_prec_round_fail() { + const THREE: Float = Float::const_from_unsigned(3); + assert_panic!(Float::one_prec(1).reciprocal_prec_round(0, Floor)); + assert_panic!(Float::one_prec(1).reciprocal_prec_round_ref(0, Floor)); + assert_panic!({ + let mut x = Float::one_prec(1); + x.reciprocal_prec_round_assign(0, Floor) + }); + + assert_panic!(THREE.reciprocal_prec_round(1, Exact)); + assert_panic!(THREE.reciprocal_prec_round_ref(1, Exact)); + assert_panic!({ + let mut x = THREE; + x.reciprocal_prec_round_assign(1, Exact) + }); +} + +#[allow(clippy::needless_pass_by_value)] +fn reciprocal_prec_round_properties_helper(x: Float, prec: u64, rm: RoundingMode) { + let (reciprocal, o) = x.clone().reciprocal_prec_round(prec, rm); + assert!(reciprocal.is_valid()); + let (reciprocal_alt, o_alt) = x.reciprocal_prec_round_ref(prec, rm); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.reciprocal_prec_round_assign(prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal)); + assert_eq!(o_alt, o); + + let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_reciprocal, rug_o) = + rug_reciprocal_prec_round(&rug::Float::exact_from(&x), prec, rm); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_reciprocal)), + ComparableFloatRef(&reciprocal), + ); + assert_eq!(rug_o, o); + } + + if o == Equal && reciprocal.is_finite() && reciprocal != 0 { + assert_eq!( + ComparableFloatRef( + &reciprocal + .reciprocal_prec_round_ref(x.significant_bits(), Exact) + .0 + ), + ComparableFloatRef(&x) + ); + } + + let (reciprocal_alt, o_alt) = Float::ONE.div_prec_round(x.clone(), prec, rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + let r_reciprocal = if reciprocal.is_finite() && x.is_finite() { + if reciprocal.is_normal() { + assert_eq!(reciprocal.get_prec(), Some(prec)); + } + let r_reciprocal = Rational::exact_from(&x).reciprocal(); + assert_eq!(reciprocal.partial_cmp(&r_reciprocal), Some(o)); + if o == Less { + let mut next = reciprocal.clone(); + next.increment(); + assert!(next > r_reciprocal); + } else if o == Greater { + let mut next = reciprocal.clone(); + next.decrement(); + assert!(next < r_reciprocal); + } + Some(r_reciprocal) + } else { + assert_eq!(o, Equal); + None + }; + + match ( + r_reciprocal.is_some() && *r_reciprocal.as_ref().unwrap() >= 0u32, + rm, + ) { + (_, Floor) | (true, Down) | (false, Up) => { + assert_ne!(o, Greater); + } + (_, Ceiling) | (true, Up) | (false, Down) => { + assert_ne!(o, Less); + } + (_, Exact) => assert_eq!(o, Equal), + _ => {} + } + + let (mut reciprocal_alt, mut o_alt) = (-&x).reciprocal_prec_round(prec, -rm); + reciprocal_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(reciprocal_alt.abs_negative_zero()), + ComparableFloat(reciprocal.abs_negative_zero_ref()) + ); + assert_eq!(o_alt, o); + + if o == Equal { + for rm in exhaustive_rounding_modes() { + let (s, oo) = x.reciprocal_prec_round_ref(prec, rm); + assert_eq!( + ComparableFloat(s.abs_negative_zero_ref()), + ComparableFloat(reciprocal.abs_negative_zero_ref()) + ); + assert_eq!(oo, Equal); + } + } else { + assert_panic!(x.reciprocal_prec_round_ref(prec, Exact)); + } +} + +#[test] +fn reciprocal_prec_round_properties() { + float_unsigned_rounding_mode_triple_gen_var_3().test_properties(|(x, prec, rm)| { + reciprocal_prec_round_properties_helper(x, prec, rm); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + float_unsigned_rounding_mode_triple_gen_var_3().test_properties_with_config( + &config, + |(x, prec, rm)| { + reciprocal_prec_round_properties_helper(x, prec, rm); + }, + ); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + config.insert("mean_small_n", 2048); + float_unsigned_rounding_mode_triple_gen_var_3().test_properties_with_config( + &config, + |(x, prec, rm)| { + reciprocal_prec_round_properties_helper(x, prec, rm); + }, + ); + + unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| { + let (reciprocal, o) = Float::NAN.reciprocal_prec_round(prec, rm); + assert!(reciprocal.is_nan()); + assert_eq!(o, Equal); + assert_eq!( + Float::INFINITY.reciprocal_prec_round(prec, rm), + (Float::ZERO, Equal) + ); + assert_eq!( + Float::NEGATIVE_INFINITY.reciprocal_prec_round(prec, rm), + (Float::NEGATIVE_ZERO, Equal) + ); + assert_eq!( + Float::ZERO.reciprocal_prec_round(prec, rm), + (Float::INFINITY, Equal) + ); + assert_eq!( + Float::NEGATIVE_ZERO.reciprocal_prec_round(prec, rm), + (Float::NEGATIVE_INFINITY, Equal) + ); + assert_eq!( + Float::ONE.reciprocal_prec_round(prec, rm), + (Float::one_prec(prec), Equal) + ); + assert_eq!( + Float::NEGATIVE_ONE.reciprocal_prec_round(prec, rm), + (Float::negative_one_prec(prec), Equal) + ); + }); +} + +#[allow(clippy::needless_pass_by_value)] +fn reciprocal_prec_properties_helper(x: Float, prec: u64) { + let (reciprocal, o) = x.clone().reciprocal_prec(prec); + assert!(reciprocal.is_valid()); + let (reciprocal_alt, o_alt) = x.reciprocal_prec_ref(prec); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.reciprocal_prec_assign(prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal)); + assert_eq!(o_alt, o); + + let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), prec, Nearest); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + let (rug_reciprocal, rug_o) = rug_reciprocal_prec(&rug::Float::exact_from(&x), prec); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_reciprocal)), + ComparableFloatRef(&reciprocal), + ); + assert_eq!(rug_o, o); + + let (reciprocal_alt, o_alt) = Float::ONE.div_prec(x.clone(), prec); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + if reciprocal.is_finite() && x.is_finite() { + if reciprocal.is_normal() { + assert_eq!(reciprocal.get_prec(), Some(prec)); + } + let r_reciprocal = Rational::exact_from(&x).reciprocal(); + assert_eq!(reciprocal.partial_cmp(&r_reciprocal), Some(o)); + if o == Less { + let mut next = reciprocal.clone(); + next.increment(); + assert!(next > r_reciprocal); + } else if o == Greater { + let mut next = reciprocal.clone(); + next.decrement(); + assert!(next < r_reciprocal); + } + } else { + assert_eq!(o, Equal); + }; + + let (mut reciprocal_alt, mut o_alt) = (-&x).reciprocal_prec(prec); + reciprocal_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(reciprocal_alt.abs_negative_zero()), + ComparableFloat(reciprocal.abs_negative_zero_ref()) + ); + assert_eq!(o_alt, o); +} + +#[test] +fn reciprocal_prec_properties() { + float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { + reciprocal_prec_properties_helper(x, prec); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| { + reciprocal_prec_properties_helper(x, prec); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + config.insert("mean_small_n", 2048); + float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| { + reciprocal_prec_properties_helper(x, prec); + }); + + unsigned_gen_var_11().test_properties(|prec| { + let (reciprocal, o) = Float::NAN.reciprocal_prec(prec); + assert!(reciprocal.is_nan()); + assert_eq!(o, Equal); + assert_eq!(Float::INFINITY.reciprocal_prec(prec), (Float::ZERO, Equal)); + assert_eq!( + Float::NEGATIVE_INFINITY.reciprocal_prec(prec), + (Float::NEGATIVE_ZERO, Equal) + ); + assert_eq!(Float::ZERO.reciprocal_prec(prec), (Float::INFINITY, Equal)); + assert_eq!( + Float::NEGATIVE_ZERO.reciprocal_prec(prec), + (Float::NEGATIVE_INFINITY, Equal) + ); + assert_eq!( + Float::ONE.reciprocal_prec(prec), + (Float::one_prec(prec), Equal) + ); + assert_eq!( + Float::NEGATIVE_ONE.reciprocal_prec(prec), + (Float::negative_one_prec(prec), Equal) + ); + }); +} + +#[allow(clippy::needless_pass_by_value)] +fn reciprocal_round_properties_helper(x: Float, rm: RoundingMode) { + let (reciprocal, o) = x.clone().reciprocal_round(rm); + assert!(reciprocal.is_valid()); + let (reciprocal_alt, o_alt) = x.reciprocal_round_ref(rm); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + let mut x_alt = x.clone(); + let o_alt = x_alt.reciprocal_round_assign(rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal)); + assert_eq!(o_alt, o); + + let (reciprocal_alt, o_alt) = + reciprocal_prec_round_naive_1(x.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + let (reciprocal_alt, o_alt) = + reciprocal_prec_round_naive_2(x.clone(), x.significant_bits(), rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_reciprocal, rug_o) = rug_reciprocal_round(&rug::Float::exact_from(&x), rm); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_reciprocal)), + ComparableFloatRef(&reciprocal), + ); + assert_eq!(rug_o, o); + } + + let (reciprocal_alt, o_alt) = Float::ONE.div_round(x.clone(), rm); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + assert_eq!(o_alt, o); + + let r_reciprocal = if reciprocal.is_finite() && x.is_finite() { + if reciprocal.is_normal() { + assert_eq!(reciprocal.get_prec(), Some(x.significant_bits())); + } + let r_reciprocal = Rational::exact_from(&x).reciprocal(); + assert_eq!(reciprocal.partial_cmp(&r_reciprocal), Some(o)); + if o == Less { + let mut next = reciprocal.clone(); + next.increment(); + assert!(next > r_reciprocal); + } else if o == Greater { + let mut next = reciprocal.clone(); + next.decrement(); + assert!(next < r_reciprocal); + } + Some(r_reciprocal) + } else { + assert_eq!(o, Equal); + None + }; + + match ( + r_reciprocal.is_some() && *r_reciprocal.as_ref().unwrap() >= 0u32, + rm, + ) { + (_, Floor) | (true, Down) | (false, Up) => { + assert_ne!(o, Greater); + } + (_, Ceiling) | (true, Up) | (false, Down) => { + assert_ne!(o, Less); + } + (_, Exact) => assert_eq!(o, Equal), + _ => {} + } + + let (mut reciprocal_alt, mut o_alt) = (-&x).reciprocal_round(-rm); + reciprocal_alt.neg_assign(); + o_alt = o_alt.reverse(); + assert_eq!( + ComparableFloat(reciprocal_alt.abs_negative_zero()), + ComparableFloat(reciprocal.abs_negative_zero_ref()) + ); + assert_eq!(o_alt, o); + + if o == Equal { + for rm in exhaustive_rounding_modes() { + let (s, oo) = x.reciprocal_round_ref(rm); + assert_eq!( + ComparableFloat(s.abs_negative_zero_ref()), + ComparableFloat(reciprocal.abs_negative_zero_ref()) + ); + assert_eq!(oo, Equal); + } + } else { + assert_panic!(x.reciprocal_round_ref(Exact)); + } +} + +#[test] +fn reciprocal_round_properties() { + float_rounding_mode_pair_gen_var_13().test_properties(|(x, rm)| { + reciprocal_round_properties_helper(x, rm); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + float_rounding_mode_pair_gen_var_13().test_properties_with_config(&config, |(x, rm)| { + reciprocal_round_properties_helper(x, rm); + }); + + float_rounding_mode_pair_gen_var_14().test_properties(|(x, rm)| { + reciprocal_round_properties_helper(x, rm); + }); + + float_rounding_mode_pair_gen_var_15().test_properties(|(x, rm)| { + reciprocal_round_properties_helper(x, rm); + }); + + float_rounding_mode_pair_gen_var_16().test_properties(|(x, rm)| { + reciprocal_round_properties_helper(x, rm); + }); + + float_rounding_mode_pair_gen_var_17().test_properties(|(x, rm)| { + reciprocal_round_properties_helper(x, rm); + }); + + rounding_mode_gen().test_properties(|rm| { + let (reciprocal, o) = Float::NAN.reciprocal_round(rm); + assert!(reciprocal.is_nan()); + assert_eq!(o, Equal); + assert_eq!(Float::INFINITY.reciprocal_round(rm), (Float::ZERO, Equal)); + assert_eq!( + Float::NEGATIVE_INFINITY.reciprocal_round(rm), + (Float::NEGATIVE_ZERO, Equal) + ); + assert_eq!(Float::ZERO.reciprocal_round(rm), (Float::INFINITY, Equal)); + assert_eq!( + Float::NEGATIVE_ZERO.reciprocal_round(rm), + (Float::NEGATIVE_INFINITY, Equal) + ); + assert_eq!(Float::ONE.reciprocal_round(rm), (Float::ONE, Equal)); + assert_eq!( + Float::NEGATIVE_ONE.reciprocal_round(rm), + (Float::NEGATIVE_ONE, Equal) + ); + }); +} + +#[allow(clippy::type_repetition_in_bounds)] +fn reciprocal_properties_helper_2() +where + Float: From + PartialOrd, + for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, +{ + primitive_float_gen::().test_properties(|x| { + let reciprocal_1 = x.reciprocal(); + let reciprocal_2 = emulate_primitive_float_fn(|x, prec| x.reciprocal_prec(prec).0, x); + assert_eq!(NiceFloat(reciprocal_1), NiceFloat(reciprocal_2)); + }); +} + +#[allow(clippy::needless_pass_by_value)] +fn reciprocal_properties_helper(x: Float) { + let reciprocal = x.clone().reciprocal(); + assert!(reciprocal.is_valid()); + + let reciprocal_alt = (&x).reciprocal(); + assert!(reciprocal_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&reciprocal_alt), + ComparableFloatRef(&reciprocal) + ); + + let mut x_alt = x.clone(); + x_alt.reciprocal_assign(); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal)); + + assert_eq!( + ComparableFloatRef( + &reciprocal_prec_round_naive_1(x.clone(), x.significant_bits(), Nearest).0 + ), + ComparableFloatRef(&reciprocal) + ); + assert_eq!( + ComparableFloatRef( + &reciprocal_prec_round_naive_2(x.clone(), x.significant_bits(), Nearest).0 + ), + ComparableFloatRef(&reciprocal) + ); + + let rug_reciprocal = rug_reciprocal(&rug::Float::exact_from(&x)); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_reciprocal)), + ComparableFloatRef(&reciprocal), + ); + + assert_eq!( + ComparableFloatRef(&(Float::ONE / x.clone())), + ComparableFloatRef(&reciprocal) + ); + + if reciprocal.is_normal() && x.is_finite() { + assert_eq!(reciprocal.get_prec(), Some(x.significant_bits())); + } + + let mut reciprocal_alt = (-&x).reciprocal(); + reciprocal_alt.neg_assign(); + assert_eq!( + ComparableFloat(reciprocal_alt.abs_negative_zero()), + ComparableFloat(reciprocal.abs_negative_zero_ref()) + ); +} + +#[test] +fn reciprocal_properties() { + float_gen().test_properties(|x| { + reciprocal_properties_helper(x); + }); + + let mut config = GenConfig::new(); + config.insert("mean_precision_n", 2048); + config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); + float_gen().test_properties_with_config(&config, |x| { + reciprocal_properties_helper(x); + }); + + float_gen_var_6().test_properties(|x| { + reciprocal_properties_helper(x); + }); + + float_gen_var_7().test_properties(|x| { + reciprocal_properties_helper(x); + }); + + float_gen_var_8().test_properties(|x| { + reciprocal_properties_helper(x); + }); + + float_gen_var_11().test_properties(|x| { + reciprocal_properties_helper(x); + }); + + apply_fn_to_primitive_floats!(reciprocal_properties_helper_2); +} diff --git a/malachite-float/tests/arithmetic/shl.rs b/malachite-float/tests/arithmetic/shl.rs index 3d9626776..135e22c16 100644 --- a/malachite-float/tests/arithmetic/shl.rs +++ b/malachite-float/tests/arithmetic/shl.rs @@ -365,6 +365,7 @@ where } assert_eq!(ComparableFloat(-&n << u), ComparableFloat(-(&n << u))); + assert_eq!(ComparableFloatRef(&(&n << u >> u)), ComparableFloatRef(&n)); assert_eq!( ComparableFloat(&n << u), ComparableFloat(n * Float::power_of_2(u64::exact_from(u))) @@ -438,6 +439,7 @@ where assert_eq!(ComparableFloat(&n << neg_i), ComparableFloat(&n >> i)); } + assert_eq!(ComparableFloatRef(&(&n << i >> i)), ComparableFloatRef(&n)); assert_eq!( ComparableFloat(&n << i), ComparableFloat(n * Float::power_of_2(i64::exact_from(i))) diff --git a/malachite-float/tests/arithmetic/shr.rs b/malachite-float/tests/arithmetic/shr.rs index d7a5247a7..ae3f2342a 100644 --- a/malachite-float/tests/arithmetic/shr.rs +++ b/malachite-float/tests/arithmetic/shr.rs @@ -335,9 +335,10 @@ fn test_shr_signed() { fn shr_properties_helper_unsigned() where for<'a> &'a Integer: Shr, - Float: Shr + ShrAssign, + Float: Shl + Shr + ShrAssign, for<'a> &'a Float: Shr, i64: TryFrom, + u64: TryFrom, { float_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let mut mut_n = n.clone(); @@ -364,9 +365,14 @@ where } assert_eq!(ComparableFloat(-&n >> u), ComparableFloat(-(&n >> u))); + assert_eq!(ComparableFloatRef(&(&n >> u << u)), ComparableFloatRef(&n)); assert_eq!( ComparableFloat(&n >> u), - ComparableFloat(n * Float::power_of_2(i64::exact_from(u).checked_neg().unwrap())) + ComparableFloat(&n * Float::power_of_2(i64::exact_from(u).checked_neg().unwrap())) + ); + assert_eq!( + ComparableFloat(&n >> u), + ComparableFloat(n / Float::power_of_2(u64::exact_from(u))) ); }); @@ -433,9 +439,14 @@ where assert_eq!(ComparableFloat(&n >> neg_i), ComparableFloat(&n << i)); } + assert_eq!(ComparableFloatRef(&(&n >> i << i)), ComparableFloatRef(&n)); + assert_eq!( + ComparableFloat(&n >> i), + ComparableFloat(&n * Float::power_of_2(i64::exact_from(i).checked_neg().unwrap())) + ); assert_eq!( ComparableFloat(&n >> i), - ComparableFloat(n * Float::power_of_2(i64::exact_from(i).checked_neg().unwrap())) + ComparableFloat(n / Float::power_of_2(i64::exact_from(i))) ); }); diff --git a/malachite-float/tests/arithmetic/square.rs b/malachite-float/tests/arithmetic/square.rs index da8c89f87..12f073fb7 100644 --- a/malachite-float/tests/arithmetic/square.rs +++ b/malachite-float/tests/arithmetic/square.rs @@ -24,7 +24,9 @@ use malachite_base::test_util::generators::{ unsigned_rounding_mode_pair_gen_var_3, }; use malachite_float::arithmetic::square::square_prec_round_naive; -use malachite_float::test_util::arithmetic::square::{rug_square, rug_square_round}; +use malachite_float::test_util::arithmetic::square::{ + rug_square, rug_square_prec, rug_square_prec_round, rug_square_round, +}; use malachite_float::test_util::common::{ emulate_primitive_float_fn, parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; @@ -62,7 +64,7 @@ fn test_square() { assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); assert_eq!( - ComparableFloatRef(&Float::from(&rug_square(rug::Float::exact_from(&x)))), + ComparableFloatRef(&Float::from(&rug_square(&rug::Float::exact_from(&x)))), ComparableFloatRef(&square) ); @@ -294,6 +296,13 @@ fn test_square_prec() { let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); + + let (rug_square, rug_o) = rug_square_prec(&rug::Float::exact_from(&x), prec); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_square)), + ComparableFloatRef(&square), + ); + assert_eq!(rug_o, o); }; test("NaN", "NaN", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", 1, "Infinity", "Infinity", Equal); @@ -757,7 +766,7 @@ fn test_square_round() { assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { - let (rug_square, rug_o) = rug_square_round(rug::Float::exact_from(&x), rm); + let (rug_square, rug_o) = rug_square_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), @@ -1438,6 +1447,15 @@ fn test_square_prec_round() { let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, rm); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_square, rug_o) = rug_square_prec_round(&rug::Float::exact_from(&x), prec, rm); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_square)), + ComparableFloatRef(&square), + ); + assert_eq!(rug_o, o); + } }; test("NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); @@ -2324,6 +2342,15 @@ fn square_prec_round_properties() { assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_square, rug_o) = rug_square_prec_round(&rug::Float::exact_from(&x), prec, rm); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_square)), + ComparableFloatRef(&square), + ); + assert_eq!(rug_o, o); + } + if !x.is_nan() { assert!(square.is_sign_positive()); } @@ -2433,6 +2460,13 @@ fn square_prec_properties_helper(x: Float, prec: u64) { assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); + let (rug_square, rug_o) = rug_square_prec(&rug::Float::exact_from(&x), prec); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_square)), + ComparableFloatRef(&square), + ); + assert_eq!(rug_o, o); + let (square_alt, o_alt) = x.square_prec_round_ref(prec, Nearest); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); @@ -2567,7 +2601,7 @@ fn square_round_properties_helper(x: Float, rm: RoundingMode) { } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { - let (rug_square, rug_o) = rug_square_round(rug::Float::exact_from(&x), rm); + let (rug_square, rug_o) = rug_square_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), @@ -2683,11 +2717,12 @@ fn square_properties_helper_1(x: Float) { } } - let rug_square = rug_square(rug::Float::exact_from(&x)); + let rug_square = rug_square(&rug::Float::exact_from(&x)); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), ); + assert_eq!(ComparableFloat((-x).square()), ComparableFloat(square)); } diff --git a/malachite-float/tests/arithmetic/sub.rs b/malachite-float/tests/arithmetic/sub.rs index 70840250c..f82fb389c 100644 --- a/malachite-float/tests/arithmetic/sub.rs +++ b/malachite-float/tests/arithmetic/sub.rs @@ -19,7 +19,8 @@ use malachite_float::test_util::arithmetic::add::{ add_prec_round_naive, add_rational_prec_round_naive, }; use malachite_float::test_util::arithmetic::sub::{ - rug_sub, rug_sub_rational, rug_sub_rational_round, rug_sub_round, + rug_sub, rug_sub_prec, rug_sub_prec_round, rug_sub_rational, rug_sub_rational_prec, + rug_sub_rational_prec_round, rug_sub_rational_round, rug_sub_round, }; use malachite_float::test_util::common::{ emulate_primitive_float_fn_2, parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, @@ -85,8 +86,8 @@ fn test_sub() { assert_eq!( ComparableFloatRef(&Float::from(&rug_sub( - rug::Float::exact_from(&x), - rug::Float::exact_from(&y) + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y) ))), ComparableFloatRef(&diff) ); @@ -1779,9 +1780,20 @@ fn test_sub_prec() { assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); - let (diff_alt, o_alt) = add_prec_round_naive(x.clone(), -y, prec, Nearest); + let (diff_alt, o_alt) = add_prec_round_naive(x.clone(), -&y, prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + + let (rug_diff, rug_o) = rug_sub_prec( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_diff)), + ComparableFloatRef(&diff), + ); + assert_eq!(rug_o, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( @@ -2571,7 +2583,7 @@ fn test_sub_round() { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = - rug_sub_round(rug::Float::exact_from(&x), rug::Float::exact_from(&y), rm); + rug_sub_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), @@ -6795,6 +6807,20 @@ fn test_sub_prec_round() { let (diff_alt, o_alt) = add_prec_round_naive(x.clone(), -&y, prec, rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_diff, rug_o) = rug_sub_prec_round( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_diff)), + ComparableFloatRef(&diff), + ); + assert_eq!(rug_o, o); + } }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); @@ -9327,8 +9353,8 @@ fn test_sub_rational() { assert_eq!( ComparableFloatRef(&Float::from(&rug_sub_rational( - rug::Float::exact_from(&x), - rug::Rational::from(&y) + &rug::Float::exact_from(&x), + &rug::Rational::from(&y) ))), ComparableFloatRef(&diff) ); @@ -9437,6 +9463,17 @@ fn test_sub_rational_prec() { let (diff_alt, o_alt) = add_rational_prec_round_naive(x.clone(), -&y, prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + + let (rug_diff, rug_o) = rug_sub_rational_prec( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_diff)), + ComparableFloatRef(&diff) + ); + assert_eq!(rug_o, o); }; test("NaN", "NaN", "-123", 1, "NaN", "NaN", Equal); test( @@ -9575,8 +9612,8 @@ fn test_sub_rational_round() { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_rational_round( - rug::Float::exact_from(&x), - rug::Rational::exact_from(&y), + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), rm, ); assert_eq!( @@ -10149,6 +10186,20 @@ fn test_sub_rational_prec_round() { let (diff_alt, o_alt) = add_rational_prec_round_naive(x.clone(), -&y, prec, rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_diff, rug_o) = rug_sub_rational_prec_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_diff)), + ComparableFloatRef(&diff) + ); + assert_eq!(rug_o, o); + } }; test("NaN", "NaN", "-123", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", 1, Ceiling, "NaN", "NaN", Equal); @@ -10808,6 +10859,39 @@ fn sub_prec_round_properties() { assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_diff, rug_o) = rug_sub_prec_round( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_diff)), + ComparableFloatRef(&diff), + ); + assert_eq!(rug_o, o); + } + + if o == Equal && diff.is_finite() { + assert_eq!( + ComparableFloat( + diff.add_prec_round_ref_ref(&y, x.significant_bits(), Exact) + .0 + .abs_negative_zero() + ), + ComparableFloat(x.abs_negative_zero_ref()) + ); + assert_eq!( + ComparableFloat( + x.sub_prec_round_ref_ref(&diff, y.significant_bits(), Exact) + .0 + .abs_negative_zero() + ), + ComparableFloat(y.abs_negative_zero_ref()) + ); + } + let r_diff = if diff.is_finite() { if diff.is_normal() { assert_eq!(diff.get_prec(), Some(prec)); @@ -10991,6 +11075,36 @@ fn sub_prec_properties() { assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + let (rug_diff, rug_o) = rug_sub_prec( + &rug::Float::exact_from(&x), + &rug::Float::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_diff)), + ComparableFloatRef(&diff), + ); + assert_eq!(rug_o, o); + + if o == Equal && diff.is_finite() { + assert_eq!( + ComparableFloat( + diff.add_prec_ref_ref(&y, x.significant_bits()) + .0 + .abs_negative_zero() + ), + ComparableFloat(x.abs_negative_zero_ref()) + ); + assert_eq!( + ComparableFloat( + x.sub_prec_ref_ref(&diff, y.significant_bits()) + .0 + .abs_negative_zero() + ), + ComparableFloat(y.abs_negative_zero_ref()) + ); + } + let (diff_alt, o_alt) = x.sub_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); @@ -11150,6 +11264,11 @@ fn sub_round_properties_helper(x: Float, y: Float, rm: RoundingMode) { assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + if o == Equal && diff.is_finite() { + assert_eq!(diff.add_round_ref_ref(&y, Exact).0, x); + assert_eq!(x.sub_round_ref_ref(&diff, Exact).0, y); + } + let r_diff = if diff.is_finite() { if x.is_normal() && y.is_normal() && diff.is_normal() { assert_eq!( @@ -11186,7 +11305,7 @@ fn sub_round_properties_helper(x: Float, y: Float, rm: RoundingMode) { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = - rug_sub_round(rug::Float::exact_from(&x), rug::Float::exact_from(&y), rm); + rug_sub_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), @@ -11384,9 +11503,14 @@ fn sub_properties_helper_2(x: Float, y: Float) { .sub_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) .0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); - let diff_alt = x.sub_round_ref_ref(&y, Nearest).0; + let (diff_alt, o) = x.sub_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); + if o == Equal && diff.is_finite() { + assert_eq!(&diff + &y, x); + assert_eq!(&x - &diff, y); + } + if diff.is_finite() && x.is_normal() && y.is_normal() && diff.is_normal() { assert_eq!( diff.get_prec(), @@ -11404,7 +11528,7 @@ fn sub_properties_helper_2(x: Float, y: Float) { } } - let rug_diff = rug_sub(rug::Float::exact_from(&x), rug::Float::exact_from(&y)); + let rug_diff = rug_sub(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), @@ -11531,6 +11655,32 @@ fn sub_rational_prec_round_properties() { assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { + let (rug_diff, rug_o) = rug_sub_rational_prec_round( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + rm, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_diff)), + ComparableFloatRef(&diff) + ); + assert_eq!(rug_o, o); + } + + if o == Equal && diff.is_finite() { + assert_eq!( + ComparableFloat( + diff.add_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) + .0 + .abs_negative_zero() + ), + ComparableFloat(x.abs_negative_zero_ref()) + ); + // TODO additional test + } + let r_diff = if diff.is_finite() { if diff.is_normal() { assert_eq!(diff.get_prec(), Some(prec)); @@ -11677,6 +11827,29 @@ fn sub_rational_prec_properties() { assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + let (rug_diff, rug_o) = rug_sub_rational_prec( + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), + prec, + ); + assert_eq!( + ComparableFloatRef(&Float::from(&rug_diff)), + ComparableFloatRef(&diff) + ); + assert_eq!(rug_o, o); + + if o == Equal && diff.is_finite() { + assert_eq!( + ComparableFloat( + diff.add_rational_prec_ref_ref(&y, x.significant_bits()) + .0 + .abs_negative_zero() + ), + ComparableFloat(x.abs_negative_zero_ref()) + ); + // TODO additional test + } + let (diff_alt, o_alt) = x.sub_rational_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); @@ -11800,6 +11973,11 @@ fn sub_rational_round_properties() { assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); + if o == Equal && diff.is_finite() && diff != 0 { + assert_eq!(diff.add_rational_round_ref_ref(&y, Exact).0, x); + // TODO additional test + } + let r_diff = if diff.is_finite() { if x.is_normal() && diff.is_normal() { assert_eq!(diff.get_prec(), Some(x.get_prec().unwrap())); @@ -11834,8 +12012,8 @@ fn sub_rational_round_properties() { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_rational_round( - rug::Float::exact_from(&x), - rug::Rational::exact_from(&y), + &rug::Float::exact_from(&x), + &rug::Rational::exact_from(&y), rm, ); assert_eq!( @@ -11968,9 +12146,14 @@ fn sub_rational_properties() { assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = x.sub_rational_prec_ref_ref(&y, x.significant_bits()).0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); - let diff_alt = x.sub_rational_round_ref_ref(&y, Nearest).0; + let (diff_alt, o) = x.sub_rational_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); + if o == Equal && diff.is_finite() && diff != 0 { + assert_eq!(&diff + &y, x); + // TODO additional test + } + if diff.is_finite() && x.is_normal() && diff.is_normal() { assert_eq!(diff.get_prec(), Some(x.get_prec().unwrap())); let r_diff = Rational::exact_from(&x) - &y; @@ -11985,7 +12168,7 @@ fn sub_rational_properties() { } } - let rug_diff = rug_sub_rational(rug::Float::exact_from(&x), rug::Rational::from(&y)); + let rug_diff = rug_sub_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), diff --git a/malachite-float/tests/basic/get_and_set.rs b/malachite-float/tests/basic/get_and_set.rs index ad1434532..f44de46fe 100644 --- a/malachite-float/tests/basic/get_and_set.rs +++ b/malachite-float/tests/basic/get_and_set.rs @@ -360,6 +360,16 @@ fn test_set_prec_round() { assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); + let (x_alt, o_alt) = Float::from_float_prec_round(old_x.clone(), prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + assert_eq!(o_alt, o); + + let (x_alt, o_alt) = Float::from_float_prec_round_ref(&old_x, prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + assert_eq!(o_alt, o); + if rm != Exact { let mut rug_x = rug::Float::exact_from(&old_x); assert_eq!( @@ -721,25 +731,38 @@ fn set_prec_round_fail() { #[test] fn set_prec_round_properties() { - float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(mut x, p, rm)| { + float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(mut x, prec, rm)| { let old_x = x.clone(); - let o = x.set_prec_round(p, rm); + let o = x.set_prec_round(prec, rm); assert!(x.is_valid()); let final_x = x.clone(); if x.is_normal() { - assert_eq!(x.get_prec(), Some(p)); + assert_eq!(x.get_prec(), Some(prec)); assert_eq!(x.partial_cmp(&old_x), Some(o)); } else { assert_eq!(o, Equal); assert_eq!(ComparableFloatRef(&old_x), ComparableFloatRef(&x)); } + let (x_alt, o_alt) = Float::from_float_prec_round(old_x.clone(), prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + assert_eq!(o_alt, o); + + let (x_alt, o_alt) = Float::from_float_prec_round_ref(&old_x, prec, rm); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + assert_eq!(o_alt, o); + if rm == Exact { assert_eq!(o, Equal); } else { let mut rug_x = rug::Float::exact_from(&old_x); assert_eq!( - rug_x.set_prec_round(u32::exact_from(p), rug_round_exact_from_rounding_mode(rm)), + rug_x.set_prec_round( + u32::exact_from(prec), + rug_round_exact_from_rounding_mode(rm) + ), o ); assert_eq!( @@ -756,7 +779,7 @@ fn set_prec_round_properties() { } let mut x = -old_x; - x.set_prec_round(p, -rm); + x.set_prec_round(prec, -rm); assert_eq!(ComparableFloat(x), ComparableFloat(-final_x)); }); } @@ -773,6 +796,16 @@ fn test_set_prec() { assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); + let (x_alt, o_alt) = Float::from_float_prec(old_x.clone(), prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + assert_eq!(o_alt, o); + + let (x_alt, o_alt) = Float::from_float_prec_ref(&old_x, prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + assert_eq!(o_alt, o); + let mut rug_x = rug::Float::exact_from(&old_x); rug_x.set_prec(u32::exact_from(prec)); assert_eq!(ComparableFloat(x), ComparableFloat(Float::from(&rug_x))); @@ -833,21 +866,31 @@ fn test_set_prec() { #[test] fn set_prec_properties() { - float_unsigned_pair_gen_var_1().test_properties(|(mut x, p)| { + float_unsigned_pair_gen_var_1().test_properties(|(mut x, prec)| { let old_x = x.clone(); - let o = x.set_prec(p); + let o = x.set_prec(prec); let final_x = x.clone(); assert!(x.is_valid()); if x.is_normal() { - assert_eq!(x.get_prec(), Some(p)); + assert_eq!(x.get_prec(), Some(prec)); assert_eq!(x.partial_cmp(&old_x), Some(o)); } else { assert_eq!(o, Equal); assert_eq!(ComparableFloatRef(&old_x), ComparableFloatRef(&x)); } + let (x_alt, o_alt) = Float::from_float_prec(old_x.clone(), prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + assert_eq!(o_alt, o); + + let (x_alt, o_alt) = Float::from_float_prec_ref(&old_x, prec); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + assert_eq!(o_alt, o); + let mut rug_x = rug::Float::exact_from(&old_x); - rug_x.set_prec(u32::exact_from(p)); + rug_x.set_prec(u32::exact_from(prec)); assert_eq!( ComparableFloatRef(&x), ComparableFloatRef(&Float::from(&rug_x)) @@ -861,7 +904,7 @@ fn set_prec_properties() { } let mut x = -old_x; - x.set_prec(p); + x.set_prec(prec); assert_eq!(ComparableFloat(x), ComparableFloat(-final_x)); }); } diff --git a/malachite-float/tests/constants/prime_constant.rs b/malachite-float/tests/constants/prime_constant.rs new file mode 100644 index 000000000..2c12cf0e7 --- /dev/null +++ b/malachite-float/tests/constants/prime_constant.rs @@ -0,0 +1,338 @@ +// 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::IsPowerOf2; +use malachite_base::num::basic::traits::PrimeConstant; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_base::test_util::generators::{ + unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, +}; +use malachite_float::test_util::common::to_hex_string; +use malachite_float::test_util::constants::prime_constant::prime_constant_prec_round_naive; +use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; +use std::cmp::Ordering::{self, *}; +use std::panic::catch_unwind; + +fn test_prime_constant_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { + let (x, o) = Float::prime_constant_prec(prec); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x_alt, o_alt) = prime_constant_prec_round_naive(prec, Nearest); + assert_eq!(x, x_alt); + assert_eq!(o, o_alt); +} + +#[test] +pub fn test_prime_constant_prec() { + test_prime_constant_prec_helper(1, "0.5", "0x0.8#1", Greater); + test_prime_constant_prec_helper(2, "0.4", "0x0.6#2", Less); + test_prime_constant_prec_helper(3, "0.44", "0x0.7#3", Greater); + test_prime_constant_prec_helper(4, "0.41", "0x0.68#4", Less); + test_prime_constant_prec_helper(5, "0.42", "0x0.6c#5", Greater); + test_prime_constant_prec_helper(6, "0.414", "0x0.6a#6", Less); + test_prime_constant_prec_helper(7, "0.414", "0x0.6a#7", Less); + test_prime_constant_prec_helper(8, "0.414", "0x0.6a0#8", Less); + test_prime_constant_prec_helper(9, "0.415", "0x0.6a4#9", Greater); + test_prime_constant_prec_helper(10, "0.4146", "0x0.6a2#10", Less); + test_prime_constant_prec_helper( + 100, + "0.4146825098511116602481096221542", + "0x0.6a28a20a08a208282282208088#100", + Less, + ); + test_prime_constant_prec_helper( + 1000, + "0.414682509851111660248109622154307708365774238137916977868245414488640960619357334196290\ + 048428475777939616159352082985957835749978453022009904120814650033958993701974119186285615\ + 579237191637251488161071073428432480218016979856815134246794749243902778820311537783180662\ + 98787003544718107300315282293658657", + "0x0.6a28a20a08a20828228220808a28800220a00a08220828028a00200228828020820a08a00800228800208\ + 028820208220808808028028220808a20020220220800a00008200820a08020828208a00200a20828008820200\ + 808020208220208808800200800a00a28020008a20008a200002202008088208002208202080#1000", + Less, + ); + test_prime_constant_prec_helper( + 10000, + "0.414682509851111660248109622154307708365774238137916977868245414488640960619357334196290\ + 048428475777939616159352082985957835749978453022009904120814650033958993701974119186285615\ + 579237191637251488161071073428432480218016979856815134246794749243902778820311537783180662\ + 987870035447181073003152822936586571701195884345760580684835877525498698320011540191930758\ + 099002319261468413919152574118369129168574279239129804341592424543430422903399908325112045\ + 668292742611194732667211553722399175647987527658878910703815406904018048152558727250330913\ + 032734465178315959501124916374515488312368223411699732976990859213965904304781712473399850\ + 022855936162301792842610279636663239004692389139831027778036326093312778898964673169309518\ + 310306063152926347489776338241054180226337674492907279938068989754912015273280509376794011\ + 427472704319064395781618400649434291302477306540023894812147846692492936635719588061120657\ + 051390501956020214967100891969377486235872143778145145772057385386205343716378192432613513\ + 172804602223001006685864520195545148953810709046574934296166432665763774833905637940402631\ + 576801946504697746229836623924610157737793410864303438788766145163542908821015516523230106\ + 797290246886870760828326453371632716614992987127399459741555239537031562083871442168565303\ + 189912375257157779026541835903342269582971374263275545243196592115378128694441070207946879\ + 764496037081508369373832295654819400087481268863376301792472431388415929294658211923608901\ + 402710138982797422281950231204740825160556996531760010125162932087538066645067994257503747\ + 988951392973626720366328982170505846234832544143958403519197518756622565009818379834626553\ + 617954708446358169530464486348037793106750286422766029143787907491013162528697477255180525\ + 301688970187379440498919433856401585513390951795192326204312092377569597171283867789460769\ + 396842845072133229690180683640002570495073917768933999215761139873608859874089589096776461\ + 995923745390535138086006656259166023212941879359754829079532092146864715376576674216923592\ + 356284657954731472882379615899071977783469111502062539802490350514979367013733212811256787\ + 651076562739406500368100788692192060657019146542871834536027154909579465624259941136769107\ + 561003973746479133595976239940200240349439391177366640902400434482715348474352654705232334\ + 865757263289528822462280034190931946143020430007789481367871305250457767936834157491630698\ + 107741376398506062111121345698764997552559136414698454192672485636202709453131509266585281\ + 706706580881014762163488645479634465001692797445197175229384471918672226624328100132469141\ + 109007889697011845498155181004138530396370327432831414575546500251524843825045622130807383\ + 973351694821712447724540951485939349474765305310454105446321469155906341381357010374677903\ + 488746578301462245594571327626904723478958729803396726212447661231362593184418074810567100\ + 150303566417543158729492869454556673124380354806665894633517169712578312518114309438722159\ + 398158466744490582994391095649028975452941714271570359608073520730264326067239780059666358\ + 3765668592857275961081596601034186349684386", + "0x0.6a28a20a08a20828228220808a28800220a00a08220828028a00200228828020820a08a00800228800208\ + 028820208220808808028028220808a20020220220800a00008200820a08020828208a00200a20828008820200\ + 808020208220208808800200800a00a28020008a20008a20000220200808820800220820208008828028200a00\ + a08000228820808208000028020200820808008820a08008020000a20a08a20028200000000820808000200800\ + 228820228200200a28820020020200208820220220008828828200800008228000008a00800a00808208200008\ + 228008020020200020008228a00800820800028000a00000820208a20208028020008020800a28020028000a08\ + a00808000200000220808000a20200028808208800a00000828220800208a08820020820008820020208800000\ + 200008020220a08000020028000808800800200a20208228820228200a00808800200800a08a00020008820208\ + 800020200820808020020008820a00000028020220008808008200220800008028000800000228008220020808\ + 808000028a00200000028208220a00220028028000a00020800008000808a28000020200208028828200a00200\ + a00800208820208200020028800208808020208200000828020008820000a00800228020008808000220a20a00\ + 220000200000800a20828200000a08000820028200200028820008a00008000008020a00a00a00828028020808\ + 000000200a00808200800020800800a00008220820000a00800208a20000028008200020208200008000a20a08\ + 200820020020000a08800020200000228828008800200000008020800800208020028820208028800208220a00\ + a00020020200008820028208200000020800220200808008000228800000800828000820800200800220000000\ + 820820208a00208a08000020a20000a20028220000008208808020000000200028228a00800208808020800008\ + a08000000220200820808200220a08828028000820000220020008000000820000220000808220800208200a00\ + 800808028020200200800000a20208808000200820a08020028020820808200828208200808000008200000a00\ + 008808020000000808000228020a08800020200200008000828008200a00a08020008800000a00028028020000\ + 228808000820a00200020220800000028028220820208800820200220008008020000020800828000020200008\ + 020800228200808220800000020008028008028000a00008000008000208000800020a00008828020200820808\ + 828028008820a00220008000220800008808220220008220008008a00000008800000820800800800208a20000\ + 820020208800a00200000008000a08000020008200800828808020820000020008220200200008028028820000\ + 208800228800208008000008020808028000000220a00220008200000000800808200a20000200808000a00800\ + 228008200020808808820208200208820808000220000220028020a00800a20000208000000208808020020a00\ + 000028228000800a08020200000200208000208800208800808200220800820028000800008a00800020220008\ + a08000020800208200828028a00000a20820020800200800820220000000020008008220a00208008000a00808\ + 000028008220800028008220020208008820020a00200220008200020a008080002080000000#10000", + Less, + ); + + let pc_f32 = Float::prime_constant_prec(u64::from(f32::MANTISSA_DIGITS)).0; + assert_eq!(pc_f32.to_string(), "0.41468251"); + assert_eq!(to_hex_string(&pc_f32), "0x0.6a28a20#24"); + assert_eq!(pc_f32, f32::PRIME_CONSTANT); + + let pc_f64 = Float::prime_constant_prec(u64::from(f64::MANTISSA_DIGITS)).0; + assert_eq!(pc_f64.to_string(), "0.41468250985111166"); + assert_eq!(to_hex_string(&pc_f64), "0x0.6a28a20a08a208#53"); + assert_eq!(pc_f64, f64::PRIME_CONSTANT); +} + +fn test_prime_constant_prec_round_helper( + prec: u64, + rm: RoundingMode, + out: &str, + out_hex: &str, + out_o: Ordering, +) { + let (x, o) = Float::prime_constant_prec_round(prec, rm); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x_alt, o_alt) = prime_constant_prec_round_naive(prec, rm); + assert_eq!(x, x_alt); + assert_eq!(o, o_alt); +} + +#[test] +pub fn test_prime_constant_prec_round() { + test_prime_constant_prec_round_helper(1, Floor, "0.2", "0x0.4#1", Less); + test_prime_constant_prec_round_helper(1, Ceiling, "0.5", "0x0.8#1", Greater); + test_prime_constant_prec_round_helper(1, Down, "0.2", "0x0.4#1", Less); + test_prime_constant_prec_round_helper(1, Up, "0.5", "0x0.8#1", Greater); + test_prime_constant_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Greater); + + test_prime_constant_prec_round_helper(2, Floor, "0.4", "0x0.6#2", Less); + test_prime_constant_prec_round_helper(2, Ceiling, "0.5", "0x0.8#2", Greater); + test_prime_constant_prec_round_helper(2, Down, "0.4", "0x0.6#2", Less); + test_prime_constant_prec_round_helper(2, Up, "0.5", "0x0.8#2", Greater); + test_prime_constant_prec_round_helper(2, Nearest, "0.4", "0x0.6#2", Less); + + test_prime_constant_prec_round_helper(3, Floor, "0.38", "0x0.6#3", Less); + test_prime_constant_prec_round_helper(3, Ceiling, "0.44", "0x0.7#3", Greater); + test_prime_constant_prec_round_helper(3, Down, "0.38", "0x0.6#3", Less); + test_prime_constant_prec_round_helper(3, Up, "0.44", "0x0.7#3", Greater); + test_prime_constant_prec_round_helper(3, Nearest, "0.44", "0x0.7#3", Greater); + + test_prime_constant_prec_round_helper(4, Floor, "0.41", "0x0.68#4", Less); + test_prime_constant_prec_round_helper(4, Ceiling, "0.44", "0x0.70#4", Greater); + test_prime_constant_prec_round_helper(4, Down, "0.41", "0x0.68#4", Less); + test_prime_constant_prec_round_helper(4, Up, "0.44", "0x0.70#4", Greater); + test_prime_constant_prec_round_helper(4, Nearest, "0.41", "0x0.68#4", Less); + + test_prime_constant_prec_round_helper(5, Floor, "0.41", "0x0.68#5", Less); + test_prime_constant_prec_round_helper(5, Ceiling, "0.42", "0x0.6c#5", Greater); + test_prime_constant_prec_round_helper(5, Down, "0.41", "0x0.68#5", Less); + test_prime_constant_prec_round_helper(5, Up, "0.42", "0x0.6c#5", Greater); + test_prime_constant_prec_round_helper(5, Nearest, "0.42", "0x0.6c#5", Greater); + + test_prime_constant_prec_round_helper(6, Floor, "0.414", "0x0.6a#6", Less); + test_prime_constant_prec_round_helper(6, Ceiling, "0.42", "0x0.6c#6", Greater); + test_prime_constant_prec_round_helper(6, Down, "0.414", "0x0.6a#6", Less); + test_prime_constant_prec_round_helper(6, Up, "0.42", "0x0.6c#6", Greater); + test_prime_constant_prec_round_helper(6, Nearest, "0.414", "0x0.6a#6", Less); + + test_prime_constant_prec_round_helper(7, Floor, "0.414", "0x0.6a#7", Less); + test_prime_constant_prec_round_helper(7, Ceiling, "0.418", "0x0.6b#7", Greater); + test_prime_constant_prec_round_helper(7, Down, "0.414", "0x0.6a#7", Less); + test_prime_constant_prec_round_helper(7, Up, "0.418", "0x0.6b#7", Greater); + test_prime_constant_prec_round_helper(7, Nearest, "0.414", "0x0.6a#7", Less); + + test_prime_constant_prec_round_helper(8, Floor, "0.414", "0x0.6a0#8", Less); + test_prime_constant_prec_round_helper(8, Ceiling, "0.416", "0x0.6a8#8", Greater); + test_prime_constant_prec_round_helper(8, Down, "0.414", "0x0.6a0#8", Less); + test_prime_constant_prec_round_helper(8, Up, "0.416", "0x0.6a8#8", Greater); + test_prime_constant_prec_round_helper(8, Nearest, "0.414", "0x0.6a0#8", Less); + + test_prime_constant_prec_round_helper(9, Floor, "0.414", "0x0.6a0#9", Less); + test_prime_constant_prec_round_helper(9, Ceiling, "0.415", "0x0.6a4#9", Greater); + test_prime_constant_prec_round_helper(9, Down, "0.414", "0x0.6a0#9", Less); + test_prime_constant_prec_round_helper(9, Up, "0.415", "0x0.6a4#9", Greater); + test_prime_constant_prec_round_helper(9, Nearest, "0.415", "0x0.6a4#9", Greater); + + test_prime_constant_prec_round_helper(10, Floor, "0.4146", "0x0.6a2#10", Less); + test_prime_constant_prec_round_helper(10, Ceiling, "0.415", "0x0.6a4#10", Greater); + test_prime_constant_prec_round_helper(10, Down, "0.4146", "0x0.6a2#10", Less); + test_prime_constant_prec_round_helper(10, Up, "0.415", "0x0.6a4#10", Greater); + test_prime_constant_prec_round_helper(10, Nearest, "0.4146", "0x0.6a2#10", Less); + + test_prime_constant_prec_round_helper( + 100, + Floor, + "0.4146825098511116602481096221542", + "0x0.6a28a20a08a208282282208088#100", + Less, + ); + test_prime_constant_prec_round_helper( + 100, + Ceiling, + "0.4146825098511116602481096221546", + "0x0.6a28a20a08a208282282208090#100", + Greater, + ); + test_prime_constant_prec_round_helper( + 100, + Down, + "0.4146825098511116602481096221542", + "0x0.6a28a20a08a208282282208088#100", + Less, + ); + test_prime_constant_prec_round_helper( + 100, + Up, + "0.4146825098511116602481096221546", + "0x0.6a28a20a08a208282282208090#100", + Greater, + ); + test_prime_constant_prec_round_helper( + 100, + Nearest, + "0.4146825098511116602481096221542", + "0x0.6a28a20a08a208282282208088#100", + Less, + ); +} + +#[test] +#[should_panic] +fn prime_constant_prec_round_fail_1() { + Float::prime_constant_prec_round(0, Floor); +} + +#[test] +#[should_panic] +fn prime_constant_prec_round_fail_2() { + Float::prime_constant_prec_round(1, Exact); +} + +#[test] +#[should_panic] +fn prime_constant_prec_round_fail_3() { + Float::prime_constant_prec_round(1000, Exact); +} + +#[test] +fn prime_constant_prec_properties() { + unsigned_gen_var_11().test_properties(|prec| { + let (pc, o) = Float::prime_constant_prec(prec); + assert!(pc.is_valid()); + assert_eq!(pc.get_prec(), Some(prec)); + assert_ne!(o, Equal); + if o == Less { + let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Ceiling); + let mut next_upper = pc.clone(); + next_upper.increment(); + if !next_upper.is_power_of_2() { + assert_eq!(ComparableFloat(pc_alt), ComparableFloat(next_upper)); + assert_eq!(o_alt, Greater); + } + } else if !pc.is_power_of_2() { + let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Floor); + let mut next_lower = pc.clone(); + next_lower.decrement(); + assert_eq!(ComparableFloat(pc_alt), ComparableFloat(next_lower)); + assert_eq!(o_alt, Less); + } + let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Nearest); + assert_eq!(ComparableFloatRef(&pc_alt), ComparableFloatRef(&pc)); + assert_eq!(o_alt, o); + + let (pc_alt, o_alt) = prime_constant_prec_round_naive(prec, Nearest); + assert_eq!(pc, pc_alt); + assert_eq!(o, o_alt); + }); +} + +#[test] +fn prime_constant_prec_round_properties() { + unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { + let (pc, o) = Float::prime_constant_prec_round(prec, rm); + assert!(pc.is_valid()); + assert_eq!(pc.get_prec(), Some(prec)); + assert_ne!(o, Equal); + if o == Less { + let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Ceiling); + let mut next_upper = pc.clone(); + next_upper.increment(); + if !next_upper.is_power_of_2() { + assert_eq!(ComparableFloat(pc_alt), ComparableFloat(next_upper)); + assert_eq!(o_alt, Greater); + } + } else if !pc.is_power_of_2() { + let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Floor); + let mut next_lower = pc.clone(); + next_lower.decrement(); + assert_eq!(ComparableFloat(pc_alt), ComparableFloat(next_lower)); + assert_eq!(o_alt, Less); + } + + let (pc_alt, o_alt) = prime_constant_prec_round_naive(prec, rm); + assert_eq!(pc, pc_alt); + assert_eq!(o, o_alt); + }); + + unsigned_gen_var_11().test_properties(|prec| { + assert_panic!(Float::prime_constant_prec_round(prec, Exact)); + }); +} diff --git a/malachite-float/tests/constants/thue_morse_constant.rs b/malachite-float/tests/constants/thue_morse_constant.rs new file mode 100644 index 000000000..42a99ac97 --- /dev/null +++ b/malachite-float/tests/constants/thue_morse_constant.rs @@ -0,0 +1,338 @@ +// 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::IsPowerOf2; +use malachite_base::num::basic::traits::ThueMorseConstant; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_base::test_util::generators::{ + unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, +}; +use malachite_float::test_util::common::to_hex_string; +use malachite_float::test_util::constants::thue_morse_constant::*; +use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; +use std::cmp::Ordering::{self, *}; +use std::panic::catch_unwind; + +fn test_thue_morse_constant_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { + let (x, o) = Float::thue_morse_constant_prec(prec); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x_alt, o_alt) = thue_morse_constant_prec_round_naive(prec, Nearest); + assert_eq!(x, x_alt); + assert_eq!(o, o_alt); +} + +#[test] +pub fn test_thue_morse_constant_prec() { + test_thue_morse_constant_prec_helper(1, "0.5", "0x0.8#1", Greater); + test_thue_morse_constant_prec_helper(2, "0.4", "0x0.6#2", Less); + test_thue_morse_constant_prec_helper(3, "0.44", "0x0.7#3", Greater); + test_thue_morse_constant_prec_helper(4, "0.41", "0x0.68#4", Less); + test_thue_morse_constant_prec_helper(5, "0.41", "0x0.68#5", Less); + test_thue_morse_constant_prec_helper(6, "0.414", "0x0.6a#6", Greater); + test_thue_morse_constant_prec_helper(7, "0.414", "0x0.6a#7", Greater); + test_thue_morse_constant_prec_helper(8, "0.412", "0x0.698#8", Less); + test_thue_morse_constant_prec_helper(9, "0.412", "0x0.698#9", Less); + test_thue_morse_constant_prec_helper(10, "0.4126", "0x0.69a#10", Greater); + test_thue_morse_constant_prec_helper( + 100, + "0.4124540336401075977833613682584", + "0x0.69969669966969969669699668#100", + Less, + ); + test_thue_morse_constant_prec_helper( + 1000, + "0.412454033640107597783361368258455283089478374455769557573379415348793592365782588963804\ + 540486212133396256366446538137487421617125193606520130996812525914093898811685058241405148\ + 794923736837717681632072372543961648455116929274915967121308797839015745939416763942926546\ + 99576354558364476401478446511510844", + "0x0.6996966996696996966969966996966996696996699696696996966996696996966969966996966969969\ + 669966969966996966996696996966969966996966996696996699696696996966996696996699696699669699\ + 6966969966996966969969669966969969669699669969669966969966996966969969669968#1000", + Greater, + ); + test_thue_morse_constant_prec_helper( + 10000, + "0.412454033640107597783361368258455283089478374455769557573379415348793592365782588963804\ + 540486212133396256366446538137487421617125193606520130996812525914093898811685058241405148\ + 794923736837717681632072372543961648455116929274915967121308797839015745939416763942926546\ + 995763545583644764014784465115108432988880527862797583778966429806153625600892794767509570\ + 613156170981916634767556262265886591706560103745429025080980592282684200382286637025552138\ + 072551019786013560720441271576469980054213089589582092326366528534417259882166080658990995\ + 454185078647844640598822656110795985657599962216385510031350572070562361426971255128326932\ + 200511472227565707730468866881043116266791929041303471097804134296620336523301148618999636\ + 607737503684384287533124783775524067880628087063676089104069872257951121771322589484343969\ + 687095887155500338806472758969301236596955913500219809107121878986270983191365987288252181\ + 126158494661750104956413082261728325258668242137155812289887905859814150448158087621806081\ + 262788059473203194858059514889641770915367577963421317521615653898873066742051436896862845\ + 559388487896091534788479920439498978693239273118810516671742331317074845718885491752000298\ + 494549886494536473002915644233647450149747441404205378363056251376268024177778124482615212\ + 986239829412055649329758982540912039441942593759895057769683431420175890362746422845117500\ + 028864842247279148167611365866356168475145086817445555637346709003759617604542400457827717\ + 878660619366846815483941374378957060770110880180541318234323659237369552401312033505621806\ + 489384014183232923162046501177883641270956312786606124433156307628120044554491098561964906\ + 941642998546962635980094725095337754362574897392106593547505034744530716373746139055913844\ + 730509118321844885047459136295028893709649115890738042446256488167921608092525231651808551\ + 275515631923236859178416003062357823567287388396791613593690713019818632422297617615418611\ + 504665052818584325511618352200787725967763734519804573074925771880268729695759436794061431\ + 099083941098658903463402394219222397121260948820568428682987584463231060168451271023138827\ + 618185738550975032215601211268731359671002623792857579075515885840571314634970190214029027\ + 767535211043320712596064063934151016649744328535127842648397490736292971851028934173894800\ + 896326950620264219873205858953858503888863733655930190565936770347310031381812711297640523\ + 854923089574146136921130192885320184597064184712813990427490161972158454924359809839110934\ + 222905109312597374946863138945391555541320741472882457682612774489682755147712902066198766\ + 365305692386197821993411562093365185277357462610197541359244519518547852573339123003451159\ + 324066183679763125504488718106276971066142222729525177728792136200206791458838091045048890\ + 889263477842031146946636054226135511708407225571080034132437244605493617364337010772961383\ + 884632019459005730120007550129264229222419321684701101892904472852138411474750231020219380\ + 490568164815194679503954588116034274794607988054271917142826665676154809041554888257037645\ + 08626387325662901457682774568054766955037516", + "0x0.6996966996696996966969966996966996696996699696696996966996696996966969966996966969969\ + 669966969966996966996696996966969966996966996696996699696696996966996696996699696699669699\ + 696696996699696696996966996696996966969966996966996696996699696696996966996696996966969966\ + 996966969969669966969966996966996696996966969966996966969969669966969969669699669969669966\ + 969966996966969969669966969966996966996696996966969966996966996696996699696696996966996696\ + 996966969966996966969969669966969966996966996696996966969966996966996696996699696696996966\ + 996696996699696699669699696696996699696696996966996696996966969966996966996696996699696696\ + 996966996696996699696699669699696696996699696699669699669969669699696699669699696696996699\ + 696696996966996696996699696699669699696696996699696696996966996696996966969966996966996696\ + 996699696696996966996696996966969966996966969969669966969966996966996696996966969966996966\ + 996696996699696696996966996696996699696699669699696696996699696696996966996696996966969966\ + 996966996696996699696696996966996696996966969966996966969969669966969966996966996696996966\ + 969966996966969969669966969969669699669969669966969966996966969969669966969966996966996696\ + 996966969966996966996696996699696696996966996696996966969966996966969969669966969966996966\ + 996696996966969966996966969969669966969969669699669969669966969966996966969969669966969969\ + 669699669969669699696699669699669969669966969969669699669969669966969966996966969969669966\ + 969966996966996696996966969966996966969969669966969969669699669969669966969966996966969969\ + 669966969966996966996696996966969966996966996696996699696696996966996696996966969966996966\ + 969969669966969966996966996696996966969966996966996696996699696696996966996696996699696699\ + 669699696696996699696696996966996696996966969966996966996696996699696696996966996696996966\ + 969966996966969969669966969966996966996696996966969966996966969969669966969969669699669969\ + 669966969966996966969969669966969966996966996696996966969966996966996696996699696696996966\ + 996696996966969966996966969969669966969966996966996696996966969966996966996696996699696696\ + 996966996696996699696699669699696696996699696696996966996696996966969966996966996696996699\ + 696696996966996696996699696699669699696696996699696699669699669969669699696699669699696696\ + 996699696696996966996696996699696699669699696696996699696696996966996696996966969966996966\ + 996696996699696696996966996696996966969966996966969969669966969966996966996696996966969966\ + 9969669966969966996966969969669966969966996966996696996966969966996966969968#10000", + Less, + ); + + let tmc_f32 = Float::thue_morse_constant_prec(u64::from(f32::MANTISSA_DIGITS)).0; + assert_eq!(tmc_f32.to_string(), "0.41245404"); + assert_eq!(to_hex_string(&tmc_f32), "0x0.6996968#24"); + assert_eq!(tmc_f32, f32::THUE_MORSE_CONSTANT); + + let tmc_f64 = Float::thue_morse_constant_prec(u64::from(f64::MANTISSA_DIGITS)).0; + assert_eq!(tmc_f64.to_string(), "0.41245403364010758"); + assert_eq!(to_hex_string(&tmc_f64), "0x0.69969669966968#53"); + assert_eq!(tmc_f64, f64::THUE_MORSE_CONSTANT); +} + +fn test_thue_morse_constant_prec_round_helper( + prec: u64, + rm: RoundingMode, + out: &str, + out_hex: &str, + out_o: Ordering, +) { + let (x, o) = Float::thue_morse_constant_prec_round(prec, rm); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x_alt, o_alt) = thue_morse_constant_prec_round_naive(prec, rm); + assert_eq!(x, x_alt); + assert_eq!(o, o_alt); +} + +#[test] +pub fn test_thue_morse_constant_prec_round() { + test_thue_morse_constant_prec_round_helper(1, Floor, "0.2", "0x0.4#1", Less); + test_thue_morse_constant_prec_round_helper(1, Ceiling, "0.5", "0x0.8#1", Greater); + test_thue_morse_constant_prec_round_helper(1, Down, "0.2", "0x0.4#1", Less); + test_thue_morse_constant_prec_round_helper(1, Up, "0.5", "0x0.8#1", Greater); + test_thue_morse_constant_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Greater); + + test_thue_morse_constant_prec_round_helper(2, Floor, "0.4", "0x0.6#2", Less); + test_thue_morse_constant_prec_round_helper(2, Ceiling, "0.5", "0x0.8#2", Greater); + test_thue_morse_constant_prec_round_helper(2, Down, "0.4", "0x0.6#2", Less); + test_thue_morse_constant_prec_round_helper(2, Up, "0.5", "0x0.8#2", Greater); + test_thue_morse_constant_prec_round_helper(2, Nearest, "0.4", "0x0.6#2", Less); + + test_thue_morse_constant_prec_round_helper(3, Floor, "0.38", "0x0.6#3", Less); + test_thue_morse_constant_prec_round_helper(3, Ceiling, "0.44", "0x0.7#3", Greater); + test_thue_morse_constant_prec_round_helper(3, Down, "0.38", "0x0.6#3", Less); + test_thue_morse_constant_prec_round_helper(3, Up, "0.44", "0x0.7#3", Greater); + test_thue_morse_constant_prec_round_helper(3, Nearest, "0.44", "0x0.7#3", Greater); + + test_thue_morse_constant_prec_round_helper(4, Floor, "0.41", "0x0.68#4", Less); + test_thue_morse_constant_prec_round_helper(4, Ceiling, "0.44", "0x0.70#4", Greater); + test_thue_morse_constant_prec_round_helper(4, Down, "0.41", "0x0.68#4", Less); + test_thue_morse_constant_prec_round_helper(4, Up, "0.44", "0x0.70#4", Greater); + test_thue_morse_constant_prec_round_helper(4, Nearest, "0.41", "0x0.68#4", Less); + + test_thue_morse_constant_prec_round_helper(5, Floor, "0.41", "0x0.68#5", Less); + test_thue_morse_constant_prec_round_helper(5, Ceiling, "0.42", "0x0.6c#5", Greater); + test_thue_morse_constant_prec_round_helper(5, Down, "0.41", "0x0.68#5", Less); + test_thue_morse_constant_prec_round_helper(5, Up, "0.42", "0x0.6c#5", Greater); + test_thue_morse_constant_prec_round_helper(5, Nearest, "0.41", "0x0.68#5", Less); + + test_thue_morse_constant_prec_round_helper(6, Floor, "0.406", "0x0.68#6", Less); + test_thue_morse_constant_prec_round_helper(6, Ceiling, "0.414", "0x0.6a#6", Greater); + test_thue_morse_constant_prec_round_helper(6, Down, "0.406", "0x0.68#6", Less); + test_thue_morse_constant_prec_round_helper(6, Up, "0.414", "0x0.6a#6", Greater); + test_thue_morse_constant_prec_round_helper(6, Nearest, "0.414", "0x0.6a#6", Greater); + + test_thue_morse_constant_prec_round_helper(7, Floor, "0.41", "0x0.69#7", Less); + test_thue_morse_constant_prec_round_helper(7, Ceiling, "0.414", "0x0.6a#7", Greater); + test_thue_morse_constant_prec_round_helper(7, Down, "0.41", "0x0.69#7", Less); + test_thue_morse_constant_prec_round_helper(7, Up, "0.414", "0x0.6a#7", Greater); + test_thue_morse_constant_prec_round_helper(7, Nearest, "0.414", "0x0.6a#7", Greater); + + test_thue_morse_constant_prec_round_helper(8, Floor, "0.412", "0x0.698#8", Less); + test_thue_morse_constant_prec_round_helper(8, Ceiling, "0.414", "0x0.6a0#8", Greater); + test_thue_morse_constant_prec_round_helper(8, Down, "0.412", "0x0.698#8", Less); + test_thue_morse_constant_prec_round_helper(8, Up, "0.414", "0x0.6a0#8", Greater); + test_thue_morse_constant_prec_round_helper(8, Nearest, "0.412", "0x0.698#8", Less); + + test_thue_morse_constant_prec_round_helper(9, Floor, "0.412", "0x0.698#9", Less); + test_thue_morse_constant_prec_round_helper(9, Ceiling, "0.413", "0x0.69c#9", Greater); + test_thue_morse_constant_prec_round_helper(9, Down, "0.412", "0x0.698#9", Less); + test_thue_morse_constant_prec_round_helper(9, Up, "0.413", "0x0.69c#9", Greater); + test_thue_morse_constant_prec_round_helper(9, Nearest, "0.412", "0x0.698#9", Less); + + test_thue_morse_constant_prec_round_helper(10, Floor, "0.4121", "0x0.698#10", Less); + test_thue_morse_constant_prec_round_helper(10, Ceiling, "0.4126", "0x0.69a#10", Greater); + test_thue_morse_constant_prec_round_helper(10, Down, "0.4121", "0x0.698#10", Less); + test_thue_morse_constant_prec_round_helper(10, Up, "0.4126", "0x0.69a#10", Greater); + test_thue_morse_constant_prec_round_helper(10, Nearest, "0.4126", "0x0.69a#10", Greater); + + test_thue_morse_constant_prec_round_helper( + 100, + Floor, + "0.4124540336401075977833613682584", + "0x0.69969669966969969669699668#100", + Less, + ); + test_thue_morse_constant_prec_round_helper( + 100, + Ceiling, + "0.4124540336401075977833613682588", + "0x0.69969669966969969669699670#100", + Greater, + ); + test_thue_morse_constant_prec_round_helper( + 100, + Down, + "0.4124540336401075977833613682584", + "0x0.69969669966969969669699668#100", + Less, + ); + test_thue_morse_constant_prec_round_helper( + 100, + Up, + "0.4124540336401075977833613682588", + "0x0.69969669966969969669699670#100", + Greater, + ); + test_thue_morse_constant_prec_round_helper( + 100, + Nearest, + "0.4124540336401075977833613682584", + "0x0.69969669966969969669699668#100", + Less, + ); +} + +#[test] +#[should_panic] +fn thue_morse_constant_prec_round_fail_1() { + Float::thue_morse_constant_prec_round(0, Floor); +} + +#[test] +#[should_panic] +fn thue_morse_constant_prec_round_fail_2() { + Float::thue_morse_constant_prec_round(1, Exact); +} + +#[test] +#[should_panic] +fn thue_morse_constant_prec_round_fail_3() { + Float::thue_morse_constant_prec_round(1000, Exact); +} + +#[test] +fn thue_morse_constant_prec_properties() { + unsigned_gen_var_11().test_properties(|prec| { + let (tmc, o) = Float::thue_morse_constant_prec(prec); + assert!(tmc.is_valid()); + assert_eq!(tmc.get_prec(), Some(prec)); + assert_ne!(o, Equal); + if o == Less { + let (tmc_alt, o_alt) = Float::thue_morse_constant_prec_round(prec, Ceiling); + let mut next_upper = tmc.clone(); + next_upper.increment(); + if !next_upper.is_power_of_2() { + assert_eq!(ComparableFloat(tmc_alt), ComparableFloat(next_upper)); + assert_eq!(o_alt, Greater); + } + } else if !tmc.is_power_of_2() { + let (tmc_alt, o_alt) = Float::thue_morse_constant_prec_round(prec, Floor); + let mut next_lower = tmc.clone(); + next_lower.decrement(); + assert_eq!(ComparableFloat(tmc_alt), ComparableFloat(next_lower)); + assert_eq!(o_alt, Less); + } + let (tmc_alt, o_alt) = Float::thue_morse_constant_prec_round(prec, Nearest); + assert_eq!(ComparableFloatRef(&tmc_alt), ComparableFloatRef(&tmc)); + assert_eq!(o_alt, o); + + let (tmc_alt, o_alt) = thue_morse_constant_prec_round_naive(prec, Nearest); + assert_eq!(tmc, tmc_alt); + assert_eq!(o, o_alt); + }); +} + +#[test] +fn thue_morse_constant_prec_round_properties() { + unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { + let (tmc, o) = Float::thue_morse_constant_prec_round(prec, rm); + assert!(tmc.is_valid()); + assert_eq!(tmc.get_prec(), Some(prec)); + assert_ne!(o, Equal); + if o == Less { + let (tmc_alt, o_alt) = Float::thue_morse_constant_prec_round(prec, Ceiling); + let mut next_upper = tmc.clone(); + next_upper.increment(); + if !next_upper.is_power_of_2() { + assert_eq!(ComparableFloat(tmc_alt), ComparableFloat(next_upper)); + assert_eq!(o_alt, Greater); + } + } else if !tmc.is_power_of_2() { + let (tmc_alt, o_alt) = Float::thue_morse_constant_prec_round(prec, Floor); + let mut next_lower = tmc.clone(); + next_lower.decrement(); + assert_eq!(ComparableFloat(tmc_alt), ComparableFloat(next_lower)); + assert_eq!(o_alt, Less); + } + + let (tmc_alt, o_alt) = thue_morse_constant_prec_round_naive(prec, rm); + assert_eq!(tmc, tmc_alt); + assert_eq!(o, o_alt); + }); + + unsigned_gen_var_11().test_properties(|prec| { + assert_panic!(Float::thue_morse_constant_prec_round(prec, Exact)); + }); +} diff --git a/malachite-float/tests/conversion/from_integer.rs b/malachite-float/tests/conversion/from_integer.rs index 6a0b25b60..b12a20fd8 100644 --- a/malachite-float/tests/conversion/from_integer.rs +++ b/malachite-float/tests/conversion/from_integer.rs @@ -472,6 +472,30 @@ fn from_integer_prec_round_ref_fail() { )); } +#[test] +fn test_from_integer_min_prec() { + let test = |s, out, out_hex| { + let u = Integer::from_str(s).unwrap(); + + let x = Float::from_integer_min_prec(u.clone()); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + + let x = Float::from_integer_min_prec_ref(&u); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + }; + test("0", "0.0", "0x0.0"); + test("1", "1.0", "0x1.0#1"); + test("123", "123.0", "0x7b.0#7"); + test("1000000000000", "1.0e12", "0xe.8d4a51E+9#28"); + test("-1", "-1.0", "-0x1.0#1"); + test("-123", "-123.0", "-0x7b.0#7"); + test("-1000000000000", "-1.0e12", "-0xe.8d4a51E+9#28"); +} + #[test] fn from_integer_properties() { integer_gen().test_properties(|n| { @@ -622,3 +646,26 @@ fn from_integer_prec_round_properties() { } }); } + +#[test] +fn from_integer_min_prec_properties() { + integer_gen().test_properties(|n| { + let float_n = Float::from_integer_min_prec(n.clone()); + assert!(float_n.is_valid()); + + let float_n_alt = Float::from_integer_min_prec_ref(&n); + assert!(float_n_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_n_alt), + ComparableFloatRef(&float_n) + ); + assert_eq!(float_n, n); + + assert_eq!(float_n.get_min_prec(), float_n.get_prec()); + + let prec = Float::from(&n).get_min_prec().unwrap_or(1); + let (f, o) = Float::from_integer_prec(n, prec); + assert_eq!(ComparableFloat(f), ComparableFloat(float_n)); + assert_eq!(o, Equal); + }); +} diff --git a/malachite-float/tests/conversion/from_natural.rs b/malachite-float/tests/conversion/from_natural.rs index bb3209024..e520374b1 100644 --- a/malachite-float/tests/conversion/from_natural.rs +++ b/malachite-float/tests/conversion/from_natural.rs @@ -88,6 +88,13 @@ fn test_from_natural_prec() { test("1000000000000", 1, "1.0e12", "0x1.0E+10#1", Greater); test("1000000000000", 10, "9.997e11", "0xe.8cE+9#10", Less); test("1000000000000", 20, "9.999997e11", "0xe.8d4aE+9#20", Less); + test( + "289905948138435080392", + 64, + "2.8990594813843508038e20", + "0xf.b740d3d8283d70cE+16#64", + Less, + ); } #[test] @@ -270,6 +277,67 @@ fn test_from_natural_prec_round() { "0xe.8d4aE+9#20", Less, ); + + test( + "20928269765806917927943182622889", + 64, + Nearest, + "2.0928269765806917929e31", + "0x1.0826e3012a87296eE+26#64", + Greater, + ); + + // - in from_natural_prec_round + // - x == 0 in from_natural_prec_round + test("0", 1, Down, "0.0", "0x0.0", Equal); + // - x != 0 in from_natural_prec_round + // - bits <= prec in from_natural_prec_round + test("1", 1, Down, "1.0", "0x1.0#1", Equal); + // - bits > prec in from_natural_prec_round + // - needed_bits == 0 in from_natural_prec_round + // - mask_width < Limb::WIDTH in from_natural_prec_round + // - rm == Floor || rm == Down in from_natural_prec_round + // - (rm == Floor || rm == Down) && !inexact in from_natural_prec_round + test("2", 1, Down, "2.0", "0x2.0#1", Equal); + // - rm == Ceiling || rm == Up in from_natural_prec_round + // - (rm == Ceiling || rm == Up) && !inexact in from_natural_prec_round + test("2", 1, Up, "2.0", "0x2.0#1", Equal); + // - rm == Nearest in from_natural_prec_round + // - rm == Nearest && (!half_bit || !inexact_after_half && !x.get_bit(bits - prec) && !inexact + // in from_natural_prec_round + test("2", 1, Nearest, "2.0", "0x2.0#1", Equal); + // - rm == Exact in from_natural_prec_round + test("2", 1, Exact, "2.0", "0x2.0#1", Equal); + // - (rm == Floor || rm == Down) && inexact in from_natural_prec_round + test("3", 1, Down, "2.0", "0x2.0#1", Less); + // - (rm == Ceiling || rm == Up) && inexact in from_natural_prec_round + // - (rm == Ceiling || rm == Up) && significand.limb_count() > original_limb_count in + // from_natural_prec_round + test("3", 1, Up, "4.0", "0x4.0#1", Greater); + // - rm == Nearest && half_bit && (inexact_after_half || x.get_bit(bits - prec)) in + // from_natural_prec_round + // - rm == Nearest && half_bit && (inexact_after_half || x.get_bit(bits - prec)) && + // significand.limb_count() > original_limb_count in from_natural_prec_round + test("3", 1, Nearest, "4.0", "0x4.0#1", Greater); + // - rm == Nearest && (!half_bit || !inexact_after_half && !x.get_bit(bits - prec) && inexact in + // from_natural_prec_round + test("5", 1, Nearest, "4.0", "0x4.0#1", Less); + // - (rm == Ceiling || rm == Up) && significand.limb_count() <= original_limb_count in + // from_natural_prec_round + test("5", 2, Up, "6.0", "0x6.0#2", Greater); + // - rm == Nearest && half_bit && (inexact_after_half || x.get_bit(bits - prec)) && + // significand.limb_count() <= original_limb_count in from_natural_prec_round + test("11", 2, Nearest, "1.0e1", "0xc.0#2", Greater); + // - needed_bits != 0 in from_natural_prec_round + // - mask_width >= Limb::WIDTH in from_natural_prec_round + test( + "10524811972430560515843", + 15, + Floor, + "1.05244e22", + "0x2.3a88E+18#15", + Less, + ); } #[test] @@ -294,6 +362,27 @@ fn from_natural_prec_round_ref_fail() { )); } +#[test] +fn test_from_natural_min_prec() { + let test = |s, out, out_hex| { + let u = Natural::from_str(s).unwrap(); + + let x = Float::from_natural_min_prec(u.clone()); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + + let x = Float::from_natural_min_prec_ref(&u); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + }; + test("0", "0.0", "0x0.0"); + test("1", "1.0", "0x1.0#1"); + test("123", "123.0", "0x7b.0#7"); + test("1000000000000", "1.0e12", "0xe.8d4a51E+9#28"); +} + #[test] fn from_natural_properties() { natural_gen().test_properties(|n| { @@ -458,3 +547,30 @@ fn from_natural_prec_round_properties() { } }); } + +#[test] +fn from_natural_min_prec_properties() { + natural_gen().test_properties(|n| { + let float_n = Float::from_natural_min_prec(n.clone()); + assert!(float_n.is_valid()); + + let float_n_alt = Float::from_natural_min_prec_ref(&n); + assert!(float_n_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_n_alt), + ComparableFloatRef(&float_n) + ); + assert_eq!(float_n, n); + + assert_eq!(float_n.get_min_prec(), float_n.get_prec()); + + assert_eq!( + ComparableFloatRef(&Float::from_integer_min_prec(Integer::from(&n))), + ComparableFloatRef(&float_n) + ); + let prec = Float::from(&n).get_min_prec().unwrap_or(1); + let (f, o) = Float::from_natural_prec(n, prec); + assert_eq!(ComparableFloat(f), ComparableFloat(float_n)); + assert_eq!(o, Equal); + }); +} diff --git a/malachite-float/tests/conversion/from_primitive_int.rs b/malachite-float/tests/conversion/from_primitive_int.rs index 929d4257d..883d52336 100644 --- a/malachite-float/tests/conversion/from_primitive_int.rs +++ b/malachite-float/tests/conversion/from_primitive_int.rs @@ -6,29 +6,30 @@ // 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::named::Named; +use malachite_base::num::arithmetic::traits::PowerOf2; 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::comparison::traits::PartialOrdAbs; -use malachite_base::num::conversion::traits::ExactFrom; +use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; -use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::generators::{ - signed_unsigned_pair_gen_var_20, unsigned_pair_gen_var_32, + signed_gen, signed_gen_var_5, signed_pair_gen_var_2, signed_unsigned_pair_gen_var_20, + unsigned_gen, unsigned_pair_gen_var_32, unsigned_signed_pair_gen_var_1, }; use malachite_float::test_util::common::{rug_round_try_from_rounding_mode, to_hex_string}; use malachite_float::test_util::generators::*; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; +use malachite_nz::platform::{Limb, SignedLimb}; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; use rug::Assign; -use std::cmp::{ - max, - Ordering::{self, *}, -}; +use std::cmp::max; +use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] @@ -37,6 +38,8 @@ fn test_from_primitive_int() { where Float: From, rug::Float: Assign, + Limb: WrappingFrom, + SignedLimb: WrappingFrom, { let x = Float::from(u); assert!(x.is_valid()); @@ -47,11 +50,25 @@ fn test_from_primitive_int() { let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); + + if T::NAME == Limb::NAME { + let x_alt = Float::const_from_unsigned(Limb::wrapping_from(u)); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); + } + + if T::NAME == SignedLimb::NAME { + let x_alt = Float::const_from_signed(SignedLimb::wrapping_from(u)); + assert!(x_alt.is_valid()); + assert_eq!(ComparableFloat(x_alt), ComparableFloat(x)); + } } fn test_helper_ui() where Float: From, rug::Float: Assign, + Limb: WrappingFrom, + SignedLimb: WrappingFrom, { test_helper(T::ZERO, "0.0", "0x0.0"); test_helper(T::ONE, "1.0", "0x1.0#1"); @@ -64,6 +81,8 @@ fn test_from_primitive_int() { where Float: From, rug::Float: Assign, + Limb: WrappingFrom, + SignedLimb: WrappingFrom, { test_helper(T::NEGATIVE_ONE, "-1.0", "-0x1.0#1"); test_helper(T::from(-123i8), "-123.0", "-0x7b.0#7"); @@ -770,6 +789,65 @@ fn from_primitive_int_prec_round_fail() { apply_fn_to_signeds!(from_signed_prec_round_fail_helper); } +#[test] +fn test_const_from_unsigned_times_power_of_2() { + fn test_helper(u: Limb, pow: i32, out: &str, out_hex: &str) { + let x = Float::const_from_unsigned_times_power_of_2(u, pow); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + } + test_helper(0, 0, "0.0", "0x0.0"); + test_helper(0, 10, "0.0", "0x0.0"); + test_helper(0, -10, "0.0", "0x0.0"); + test_helper(1, 0, "1.0", "0x1.0#1"); + test_helper(1, 10, "1.0e3", "0x4.0E+2#1"); + test_helper(1, -10, "0.001", "0x0.004#1"); + #[cfg(not(feature = "32_bit_limbs"))] + { + test_helper( + 884279719003555, + -48, + "3.141592653589793", + "0x3.243f6a8885a3#50", + ); + } +} + +#[test] +fn test_const_from_signed_times_power_of_2() { + fn test_helper(u: SignedLimb, pow: i32, out: &str, out_hex: &str) { + let x = Float::const_from_signed_times_power_of_2(u, pow); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + } + test_helper(0, 0, "0.0", "0x0.0"); + test_helper(0, 10, "0.0", "0x0.0"); + test_helper(0, -10, "0.0", "0x0.0"); + test_helper(1, 0, "1.0", "0x1.0#1"); + test_helper(1, 10, "1.0e3", "0x4.0E+2#1"); + test_helper(1, -10, "0.001", "0x0.004#1"); + test_helper(-1, 0, "-1.0", "-0x1.0#1"); + test_helper(-1, 10, "-1.0e3", "-0x4.0E+2#1"); + test_helper(-1, -10, "-0.001", "-0x0.004#1"); + #[cfg(not(feature = "32_bit_limbs"))] + { + test_helper( + 884279719003555, + -48, + "3.141592653589793", + "0x3.243f6a8885a3#50", + ); + test_helper( + -884279719003555, + -48, + "-3.141592653589793", + "-0x3.243f6a8885a3#50", + ); + } +} + #[allow(clippy::type_repetition_in_bounds)] fn from_primitive_int_properties_helper_unsigned() where @@ -777,11 +855,22 @@ where rug::Float: Assign, Natural: From + PartialEq, for<'a> T: ExactFrom<&'a Float>, + Limb: WrappingFrom, { unsigned_gen::().test_properties(|n| { let float_n = Float::from(n); assert!(float_n.is_valid()); + if T::WIDTH == Limb::WIDTH { + let n_alt = Float::const_from_unsigned(Limb::wrapping_from(n)); + assert!(n_alt.is_valid()); + assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); + + let n_alt = Float::const_from_unsigned_times_power_of_2(Limb::wrapping_from(n), 0); + assert!(n_alt.is_valid()); + assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); + } + let rug_n = rug::Float::with_val(max(1, u32::exact_from(n.significant_bits())), n); assert_eq!( ComparableFloatRef(&float_n), @@ -814,11 +903,22 @@ where rug::Float: Assign, Integer: From + PartialEq, for<'a> T: ExactFrom<&'a Float>, + SignedLimb: WrappingFrom, { signed_gen::().test_properties(|n| { let float_n = Float::from(n); assert!(float_n.is_valid()); + if T::WIDTH == SignedLimb::WIDTH { + let n_alt = Float::const_from_signed(SignedLimb::wrapping_from(n)); + assert!(n_alt.is_valid()); + assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); + + let n_alt = Float::const_from_signed_times_power_of_2(SignedLimb::wrapping_from(n), 0); + assert!(n_alt.is_valid()); + assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); + } + let rug_n = rug::Float::with_val(max(1, u32::exact_from(n.significant_bits())), n); assert_eq!( ComparableFloatRef(&float_n), @@ -1095,3 +1195,43 @@ fn from_primitive_int_prec_round_properties() { apply_fn_to_unsigneds!(from_primitive_int_prec_round_properties_helper_unsigned); apply_fn_to_signeds!(from_primitive_int_prec_round_properties_helper_signed); } + +#[test] +fn const_from_unsigned_times_power_of_2_properties() { + unsigned_signed_pair_gen_var_1().test_properties(|(n, pow)| { + let float_n = Float::const_from_unsigned_times_power_of_2(n, pow); + assert!(float_n.is_valid()); + assert!(float_n >= 0); + assert_eq!( + ComparableFloat(float_n), + ComparableFloat(Float::from(n) << pow) + ); + }); + + signed_gen_var_5().test_properties(|pow| { + assert_eq!( + ComparableFloat(Float::const_from_unsigned_times_power_of_2(1, pow)), + ComparableFloat(Float::power_of_2(i64::from(pow))) + ); + }); +} + +#[test] +fn const_from_signed_times_power_of_2_properties() { + signed_pair_gen_var_2().test_properties(|(n, pow)| { + let float_n = Float::const_from_signed_times_power_of_2(n, pow); + assert!(float_n.is_valid()); + assert_eq!(float_n >= 0, n >= 0); + assert_eq!( + ComparableFloat(float_n), + ComparableFloat(Float::from(n) << pow) + ); + }); + + signed_gen_var_5().test_properties(|pow| { + assert_eq!( + ComparableFloat(Float::const_from_signed_times_power_of_2(1, pow)), + ComparableFloat(Float::power_of_2(i64::from(pow))) + ); + }); +} diff --git a/malachite-float/tests/conversion/from_rational.rs b/malachite-float/tests/conversion/from_rational.rs index e648eb3fe..95025b42d 100644 --- a/malachite-float/tests/conversion/from_rational.rs +++ b/malachite-float/tests/conversion/from_rational.rs @@ -10,6 +10,10 @@ use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom}; use malachite_base::rounding_modes::RoundingMode::*; +use malachite_float::conversion::from_rational::{ + from_rational_prec_round_direct, from_rational_prec_round_ref_direct, + from_rational_prec_round_ref_using_div, from_rational_prec_round_using_div, +}; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; use malachite_float::test_util::common::to_hex_string; use malachite_float::test_util::generators::rational_unsigned_rounding_mode_triple_gen_var_1; @@ -39,6 +43,30 @@ fn test_from_rational_prec() { assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); + let (x, o) = from_rational_prec_round_direct(u.clone(), prec, Nearest); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x, o) = from_rational_prec_round_ref_direct(&u, prec, Nearest); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x, o) = from_rational_prec_round_using_div(u.clone(), prec, Nearest); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x, o) = from_rational_prec_round_ref_using_div(&u, prec, Nearest); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Rational::from(&u)); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); @@ -110,6 +138,30 @@ fn test_from_rational_prec_round() { assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); + let (x, o) = from_rational_prec_round_direct(u.clone(), prec, rm); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x, o) = from_rational_prec_round_using_div(u.clone(), prec, rm); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x, o) = from_rational_prec_round_ref_direct(&u, prec, rm); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + + let (x, o) = from_rational_prec_round_ref_using_div(&u, prec, rm); + assert!(x.is_valid()); + assert_eq!(x.to_string(), out); + assert_eq!(to_hex_string(&x), out_hex); + assert_eq!(o, out_o); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Rational::from(&u), rm); @@ -796,6 +848,38 @@ fn from_rational_prec_properties() { assert_eq!(o, o_alt); assert_eq!(float_x.partial_cmp(&x), Some(o)); + let (float_x_alt, o_alt) = from_rational_prec_round_direct(x.clone(), prec, Nearest); + assert!(float_x_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_x_alt), + ComparableFloatRef(&float_x) + ); + assert_eq!(o, o_alt); + + let (float_x_alt, o_alt) = from_rational_prec_round_using_div(x.clone(), prec, Nearest); + assert!(float_x_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_x_alt), + ComparableFloatRef(&float_x) + ); + assert_eq!(o, o_alt); + + let (float_x_alt, o_alt) = from_rational_prec_round_ref_direct(&x, prec, Nearest); + assert!(float_x_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_x_alt), + ComparableFloatRef(&float_x) + ); + assert_eq!(o, o_alt); + + let (float_x_alt, o_alt) = from_rational_prec_round_ref_using_div(&x, prec, Nearest); + assert!(float_x_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_x_alt), + ComparableFloatRef(&float_x) + ); + assert_eq!(o, o_alt); + let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Rational::from(&x)); assert_eq!( ComparableFloatRef(&float_x), @@ -839,6 +923,38 @@ fn from_rational_prec_round_properties() { _ => {} } + let (float_x_alt, o_alt) = from_rational_prec_round_direct(x.clone(), prec, rm); + assert!(float_x_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_x_alt), + ComparableFloatRef(&float_x) + ); + assert_eq!(o, o_alt); + + let (float_x_alt, o_alt) = from_rational_prec_round_using_div(x.clone(), prec, rm); + assert!(float_x_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_x_alt), + ComparableFloatRef(&float_x) + ); + assert_eq!(o, o_alt); + + let (float_x_alt, o_alt) = from_rational_prec_round_ref_direct(&x, prec, rm); + assert!(float_x_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_x_alt), + ComparableFloatRef(&float_x) + ); + assert_eq!(o, o_alt); + + let (float_x_alt, o_alt) = from_rational_prec_round_ref_using_div(&x, prec, rm); + assert!(float_x_alt.is_valid()); + assert_eq!( + ComparableFloatRef(&float_x_alt), + ComparableFloatRef(&float_x) + ); + assert_eq!(o, o_alt); + if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Rational::from(&x), rm); diff --git a/malachite-float/tests/lib.rs b/malachite-float/tests/lib.rs index 08e6ebbf1..da7e6ad14 100644 --- a/malachite-float/tests/lib.rs +++ b/malachite-float/tests/lib.rs @@ -63,17 +63,18 @@ extern crate malachite_base; pub mod arithmetic { pub mod abs; pub mod add; + pub mod div; pub mod is_power_of_2; pub mod mul; pub mod neg; pub mod power_of_2; + pub mod reciprocal; pub mod shl; pub mod shr; pub mod sign; pub mod square; pub mod sub; } - pub mod basic { pub mod classification; pub mod complexity; @@ -104,6 +105,10 @@ pub mod comparison { pub mod partial_eq_primitive_int; pub mod partial_eq_rational; } +pub mod constants { + pub mod prime_constant; + pub mod thue_morse_constant; +} pub mod conversion { pub mod clone; pub mod from_integer; diff --git a/malachite-nz/Cargo.toml b/malachite-nz/Cargo.toml index 7b6552572..c5b59dd05 100644 --- a/malachite-nz/Cargo.toml +++ b/malachite-nz/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "malachite-nz" -version = "0.4.15" +version = "0.4.16" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true @@ -23,7 +23,7 @@ path = "src/bin.rs" [dependencies] itertools = { version = "0.11.0", default-features = false, features = ["use_alloc"] } libm = { version = "0.2.8", default-features = false } -malachite-base = { version = "0.4.15", default-features = false } +malachite-base = { version = "0.4.16", default-features = false } serde = { version = "1.0.188", optional = true, default-features = false, features = ["alloc", "derive"] } indoc = { version = "2.0.4", optional = true} diff --git a/malachite-nz/src/integer/random/mod.rs b/malachite-nz/src/integer/random/mod.rs index c88c24ccc..85e478772 100644 --- a/malachite-nz/src/integer/random/mod.rs +++ b/malachite-nz/src/integer/random/mod.rs @@ -9,8 +9,8 @@ use crate::integer::Integer; use crate::natural::random::{ get_random_natural_less_than, get_random_natural_with_bits, - get_striped_random_natural_with_bits, random_naturals_less_than, - striped_random_natural_inclusive_range, RandomNaturalsLessThan, + get_striped_random_natural_from_inclusive_range, get_striped_random_natural_with_bits, + random_naturals_less_than, striped_random_natural_inclusive_range, RandomNaturalsLessThan, StripedRandomNaturalInclusiveRange, }; use crate::natural::Natural; @@ -811,11 +811,11 @@ pub fn uniform_random_integer_inclusive_range( /// ``` /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; -/// use malachite_nz::integer::random::get_uniform_random_integer_in_range; +/// use malachite_nz::integer::random::get_uniform_random_integer_from_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( -/// get_uniform_random_integer_in_range( +/// get_uniform_random_integer_from_range( /// &mut random_primitive_ints(EXAMPLE_SEED), /// Integer::from(500u32), /// Integer::from(1000u32) @@ -823,7 +823,7 @@ pub fn uniform_random_integer_inclusive_range( /// 869 /// ); /// ``` -pub fn get_uniform_random_integer_in_range( +pub fn get_uniform_random_integer_from_range( limbs: &mut RandomPrimitiveInts, a: Integer, b: Integer, @@ -859,11 +859,11 @@ pub fn get_uniform_random_integer_in_range( /// ``` /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; -/// use malachite_nz::integer::random::get_uniform_random_integer_in_inclusive_range; +/// use malachite_nz::integer::random::get_uniform_random_integer_from_inclusive_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( -/// get_uniform_random_integer_in_inclusive_range( +/// get_uniform_random_integer_from_inclusive_range( /// &mut random_primitive_ints(EXAMPLE_SEED), /// Integer::from(500u32), /// Integer::from(1001u32) @@ -871,13 +871,13 @@ pub fn get_uniform_random_integer_in_range( /// 869 /// ); /// ``` -pub fn get_uniform_random_integer_in_inclusive_range( +pub fn get_uniform_random_integer_from_inclusive_range( limbs: &mut RandomPrimitiveInts, a: Integer, b: Integer, ) -> Integer { assert!(a <= b); - get_uniform_random_integer_in_range(limbs, a, b + Integer::ONE) + get_uniform_random_integer_from_range(limbs, a, b + Integer::ONE) } fn signed_significant_bits(a: &Integer) -> (u64, i64) { @@ -919,15 +919,15 @@ fn signed_max_bit_range( } } -fn get_random_integer_in_signed_min_bit_range( +fn get_random_integer_from_signed_min_bit_range( limbs: &mut RandomPrimitiveInts, a: Integer, unsigned_min_bits: u64, ) -> Integer { if a >= 0 { - get_uniform_random_integer_in_range(limbs, a, Integer::power_of_2(unsigned_min_bits)) + get_uniform_random_integer_from_range(limbs, a, Integer::power_of_2(unsigned_min_bits)) } else { - get_uniform_random_integer_in_inclusive_range( + get_uniform_random_integer_from_inclusive_range( limbs, a, -Integer::power_of_2(unsigned_min_bits - 1), @@ -935,20 +935,20 @@ fn get_random_integer_in_signed_min_bit_range( } } -fn get_random_integer_in_signed_max_bit_range( +fn get_random_integer_from_signed_max_bit_range( limbs: &mut RandomPrimitiveInts, a: Integer, unsigned_max_bits: u64, ) -> Integer { if a > 0 { - get_uniform_random_integer_in_inclusive_range( + get_uniform_random_integer_from_inclusive_range( limbs, Integer::power_of_2(unsigned_max_bits - 1), a, ) } else { // also handles a == 0 - get_uniform_random_integer_in_inclusive_range( + get_uniform_random_integer_from_inclusive_range( limbs, -Integer::power_of_2(unsigned_max_bits) + Integer::ONE, a, @@ -956,6 +956,53 @@ fn get_random_integer_in_signed_max_bit_range( } } +fn get_striped_random_integer_from_signed_min_bit_range( + xs: &mut StripedBitSource, + range_generator: &mut VariableRangeGenerator, + a: Integer, + unsigned_min_bits: u64, +) -> Integer { + if a >= 0 { + get_striped_random_integer_from_range( + xs, + range_generator, + a, + Integer::power_of_2(unsigned_min_bits), + ) + } else { + get_striped_random_integer_from_inclusive_range( + xs, + range_generator, + a, + -Integer::power_of_2(unsigned_min_bits - 1), + ) + } +} + +fn get_striped_random_integer_from_signed_max_bit_range( + xs: &mut StripedBitSource, + range_generator: &mut VariableRangeGenerator, + a: Integer, + unsigned_max_bits: u64, +) -> Integer { + if a > 0 { + get_striped_random_integer_from_inclusive_range( + xs, + range_generator, + Integer::power_of_2(unsigned_max_bits - 1), + a, + ) + } else { + // also handles a == 0 + get_striped_random_integer_from_inclusive_range( + xs, + range_generator, + -Integer::power_of_2(unsigned_max_bits) + Integer::ONE, + a, + ) + } +} + /// Generates random [`Integer`]s greater than or equal to a lower bound, or less than or equal to /// an upper bound. #[derive(Clone, Debug)] @@ -1059,7 +1106,7 @@ pub fn random_integer_range_to_infinity( /// # Examples /// ``` /// use malachite_base::num::random::random_primitive_ints; -/// use malachite_base::num::random::variable_range_generator; +/// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_random_integer_from_range_to_infinity; /// use malachite_nz::integer::Integer; @@ -1067,7 +1114,7 @@ pub fn random_integer_range_to_infinity( /// assert_eq!( /// get_random_integer_from_range_to_infinity( /// &mut random_primitive_ints(EXAMPLE_SEED.fork("limbs")), -/// &mut variable_range_generator(EXAMPLE_SEED.fork("rg")), +/// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), /// Integer::from(-1000), /// 20, /// 1 @@ -1091,7 +1138,7 @@ pub fn get_random_integer_from_range_to_infinity( mean_bits_denominator, ); if bits == min_bits { - get_random_integer_in_signed_min_bit_range(limbs, a, unsigned_min_bits) + get_random_integer_from_signed_min_bit_range(limbs, a, unsigned_min_bits) } else { Integer::from_sign_and_abs( bits >= 0, @@ -1177,7 +1224,7 @@ pub fn random_integer_range_to_negative_infinity( /// # Examples /// ``` /// use malachite_base::num::random::random_primitive_ints; -/// use malachite_base::num::random::variable_range_generator; +/// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_random_integer_from_range_to_negative_infinity; /// use malachite_nz::integer::Integer; @@ -1185,7 +1232,7 @@ pub fn random_integer_range_to_negative_infinity( /// assert_eq!( /// get_random_integer_from_range_to_negative_infinity( /// &mut random_primitive_ints(EXAMPLE_SEED.fork("limbs")), -/// &mut variable_range_generator(EXAMPLE_SEED.fork("rg")), +/// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), /// Integer::from(-1000), /// 20, /// 1 @@ -1209,7 +1256,7 @@ pub fn get_random_integer_from_range_to_negative_infinity( mean_bits_denominator, ); if bits == max_bits { - get_random_integer_in_signed_max_bit_range(limbs, a, unsigned_max_bits) + get_random_integer_from_signed_max_bit_range(limbs, a, unsigned_max_bits) } else { Integer::from_sign_and_abs( bits >= 0, @@ -1269,7 +1316,7 @@ impl Iterator for RandomIntegerRange { /// Generates random [`Integer`]s in the half-open interval $[a, b)$. /// /// In general, the [`Integer`]s are not generated uniformly; for that, use -/// [`uniform_random_integer_range`]. Instead, [`Natural`]s with smaller bit lengths are generated +/// [`uniform_random_integer_range`]. Instead, [`Integer`]s with smaller bit lengths are generated /// more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by @@ -1599,6 +1646,123 @@ pub fn striped_random_integer_inclusive_range( } } +/// Generates a random striped [`Integer`] in the range $[a, b)$. +/// +/// Because the [`Integer`] is constrained to be within a certain range, the actual mean run length +/// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run +/// length. +/// +/// See [`StripedBitSource`] for information about generating striped random numbers. +/// +/// # Expected complexity +/// $T(n) = O(n)$ +/// +/// $M(n) = O(n)$ +/// +/// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), +/// b.significant_bits())`. +/// +/// # Panics +/// Panics if $a \geq b$. +/// +/// # Examples +/// ``` +/// use malachite_base::num::random::striped::StripedBitSource; +/// use malachite_base::num::random::VariableRangeGenerator; +/// use malachite_base::random::EXAMPLE_SEED; +/// use malachite_nz::integer::random::get_striped_random_integer_from_range; +/// use malachite_nz::integer::Integer; +/// +/// assert_eq!( +/// get_striped_random_integer_from_range( +/// &mut StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1,), +/// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), +/// Integer::from(-4), +/// Integer::from(7), +/// ), +/// -4 +/// ); +/// ``` +#[inline] +pub fn get_striped_random_integer_from_range( + xs: &mut StripedBitSource, + range_generator: &mut VariableRangeGenerator, + a: Integer, + b: Integer, +) -> Integer { + assert!(a < b); + get_striped_random_integer_from_inclusive_range(xs, range_generator, a, b - Integer::ONE) +} + +/// Generates a random striped [`Integer`] in the range $[a, b]$. +/// +/// Because the [`Integer`] is constrained to be within a certain range, the actual mean run length +/// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run +/// length. +/// +/// See [`StripedBitSource`] for information about generating striped random numbers. +/// +/// # Expected complexity +/// $T(n) = O(n)$ +/// +/// $M(n) = O(n)$ +/// +/// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), +/// b.significant_bits())`. +/// +/// # Panics +/// Panics if $a > b$. +/// +/// # Examples +/// ``` +/// use malachite_base::num::random::striped::StripedBitSource; +/// use malachite_base::num::random::VariableRangeGenerator; +/// use malachite_base::random::EXAMPLE_SEED; +/// use malachite_nz::integer::random::get_striped_random_integer_from_inclusive_range; +/// use malachite_nz::integer::Integer; +/// +/// assert_eq!( +/// get_striped_random_integer_from_inclusive_range( +/// &mut StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1,), +/// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), +/// Integer::from(-4), +/// Integer::from(7), +/// ), +/// -4 +/// ); +/// ``` +pub fn get_striped_random_integer_from_inclusive_range( + xs: &mut StripedBitSource, + range_generator: &mut VariableRangeGenerator, + a: Integer, + b: Integer, +) -> Integer { + assert!(a <= b); + if a >= 0u32 { + Integer::from(get_striped_random_natural_from_inclusive_range( + xs, + a.unsigned_abs(), + b.unsigned_abs(), + )) + } else if b < 0u32 { + Integer::from_sign_and_abs( + false, + get_striped_random_natural_from_inclusive_range(xs, b.unsigned_abs(), a.unsigned_abs()), + ) + } else if range_generator.next_bool() { + Integer::from(get_striped_random_natural_from_inclusive_range( + xs, + Natural::ZERO, + b.unsigned_abs(), + )) + } else { + Integer::from_sign_and_abs( + false, + get_striped_random_natural_from_inclusive_range(xs, Natural::ONE, a.unsigned_abs()), + ) + } +} + fn striped_signed_min_bit_range( seed: Seed, a: Integer, @@ -1764,6 +1928,160 @@ pub fn striped_random_integer_range_to_infinity( } } +/// Generates a striped random [`Integer`] greater than or equal to a lower bound $a$. +/// +/// The mean bit length $m$ of the [`Integer`] is specified; it must be greater than the bit length +/// of $a$. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. +/// +/// The actual bit length is chosen from a geometric distribution with lower bound $a$ and mean $m$. +/// The resulting distribution has no mean or higher-order statistics (unless $a < m < a + 1$, which +/// is not typical). +/// +/// Because the [`Integer`] is constrained to be within a certain range, the actual mean run length +/// will usually not be $\mu$. Nonetheless, setting a higher $\mu$ will result in a higher mean run +/// length. +/// +/// See [`StripedBitSource`] for information about generating striped random numbers. +/// +/// # Expected complexity +/// $T(n, m) = O(n + m)$ +/// +/// $M(n, m) = O(n / m)$ +/// +/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is +/// `mean_precision_denominator`. +/// +/// # Panics +/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > 0$ and their ratio +/// is less than or equal to the bit length of $a$, or if they are too large and manipulating them +/// leads to arithmetic overflow. +/// +/// # Examples +/// ``` +/// use malachite_base::num::random::striped::StripedBitSource; +/// use malachite_base::num::random::VariableRangeGenerator; +/// use malachite_base::random::EXAMPLE_SEED; +/// use malachite_nz::integer::random::get_striped_random_integer_from_range_to_infinity; +/// use malachite_nz::integer::Integer; +/// +/// assert_eq!( +/// get_striped_random_integer_from_range_to_infinity( +/// &mut StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1,), +/// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), +/// Integer::from(-1000), +/// 20, +/// 1 +/// ), +/// -3 +/// ); +/// ``` +pub fn get_striped_random_integer_from_range_to_infinity( + xs: &mut StripedBitSource, + range_generator: &mut VariableRangeGenerator, + a: Integer, + mean_bits_numerator: u64, + mean_bits_denominator: u64, +) -> Integer { + let (unsigned_min_bits, min_bits) = signed_significant_bits(&a); + let bits = get_geometric_random_signed_from_inclusive_range( + range_generator, + min_bits, + i64::MAX, + mean_bits_numerator, + mean_bits_denominator, + ); + if bits == min_bits { + get_striped_random_integer_from_signed_min_bit_range( + xs, + range_generator, + a, + unsigned_min_bits, + ) + } else { + Integer::from_sign_and_abs( + bits >= 0, + get_striped_random_natural_with_bits(xs, bits.unsigned_abs()), + ) + } +} + +/// Generates a striped random [`Integer`] less than or equal to an upper bound $a$. +/// +/// The mean bit length $m$ of the [`Integer`] is specified; it must be greater than the bit length +/// of $a$. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. +/// +/// The actual bit length is chosen from a geometric distribution with lower bound $a$ and mean $m$. +/// The resulting distribution has no mean or higher-order statistics (unless $a < m < a + 1$, which +/// is not typical). +/// +/// Because the [`Integer`] is constrained to be within a certain range, the actual mean run length +/// will usually not be $\mu$. Nonetheless, setting a higher $\mu$ will result in a higher mean run +/// length. +/// +/// See [`StripedBitSource`] for information about generating striped random numbers. +/// +/// # Expected complexity +/// $T(n, m) = O(n + m)$ +/// +/// $M(n, m) = O(n / m)$ +/// +/// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is +/// `mean_precision_denominator`. +/// +/// # Panics +/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $b < 0$ and their ratio +/// is less than or equal to the bit length of $b$, or if they are too large and manipulating them +/// leads to arithmetic overflow. +/// +/// # Examples +/// ``` +/// use malachite_base::num::random::striped::StripedBitSource; +/// use malachite_base::num::random::VariableRangeGenerator; +/// use malachite_base::random::EXAMPLE_SEED; +/// use malachite_nz::integer::random::get_striped_random_integer_from_range_to_negative_infinity; +/// use malachite_nz::integer::Integer; +/// +/// assert_eq!( +/// get_striped_random_integer_from_range_to_negative_infinity( +/// &mut StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1,), +/// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), +/// Integer::from(-1000), +/// 20, +/// 1 +/// ), +/// -3975 +/// ); +/// ``` +pub fn get_striped_random_integer_from_range_to_negative_infinity( + xs: &mut StripedBitSource, + range_generator: &mut VariableRangeGenerator, + a: Integer, + mean_bits_numerator: u64, + mean_bits_denominator: u64, +) -> Integer { + let (unsigned_max_bits, max_bits) = signed_significant_bits(&a); + let bits = get_geometric_random_signed_from_inclusive_range( + range_generator, + i64::MIN, + max_bits, + mean_bits_numerator, + mean_bits_denominator, + ); + if bits == max_bits { + get_striped_random_integer_from_signed_max_bit_range( + xs, + range_generator, + a, + unsigned_max_bits, + ) + } else { + Integer::from_sign_and_abs( + bits >= 0, + get_striped_random_natural_with_bits(xs, bits.unsigned_abs()), + ) + } +} + /// Generates striped random [`Integer`]s less than or equal to an upper bound $a$. /// /// The mean bit length $m$ of the [`Integer`]s is specified; it must be greater than the bit length diff --git a/malachite-nz/src/natural/arithmetic/float_add.rs b/malachite-nz/src/natural/arithmetic/float_add.rs index 9ae9b1a27..f7fef2a9e 100644 --- a/malachite-nz/src/natural/arithmetic/float_add.rs +++ b/malachite-nz/src/natural/arithmetic/float_add.rs @@ -24,7 +24,6 @@ use crate::natural::Natural; use crate::platform::Limb; use core::cmp::Ordering::{self, *}; use core::mem::swap; -use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ NegModPowerOf2, OverflowingAddAssign, Parity, PowerOf2, ShrRound, WrappingAddAssign, }; @@ -1775,10 +1774,6 @@ fn add_float_significands_same_prec_ge_3w_ref_ref<'a>( (x_exp, Less) } else { if limbs_slice_add_limb_in_place(out, shift_bit) { - fail_on_untested_path( - "add_float_significands_same_prec_ge_3w, exp_diff == 0 && \ - rm == Nearest && out[0] & shift_bit != 0 && carry", - ); x_exp = x_exp.checked_add(1).unwrap(); out[last_index] = HIGH_BIT; } @@ -1788,9 +1783,6 @@ fn add_float_significands_same_prec_ge_3w_ref_ref<'a>( Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(out, shift_bit) { - fail_on_untested_path( - "exp_diff == 0 && (rm == Ceiling || rm == Up) && carry", - ); x_exp = x_exp.checked_add(1).unwrap(); out[last_index] = HIGH_BIT; } @@ -1964,10 +1956,6 @@ fn add_float_significands_same_prec_ge_3w_val_ref( (x_exp, Less) } else { if limbs_slice_add_limb_in_place(xs, shift_bit) { - fail_on_untested_path( - "add_float_significands_same_prec_ge_3w, exp_diff == 0 && \ - rm == Nearest && xs[0] & shift_bit != 0 && carry", - ); x_exp = x_exp.checked_add(1).unwrap(); xs[last_index] = HIGH_BIT; } @@ -1977,9 +1965,6 @@ fn add_float_significands_same_prec_ge_3w_val_ref( Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(xs, shift_bit) { - fail_on_untested_path( - "exp_diff == 0 && (rm == Ceiling || rm == Up) && carry", - ); x_exp = x_exp.checked_add(1).unwrap(); xs[last_index] = HIGH_BIT; } @@ -2124,10 +2109,6 @@ fn add_float_significands_same_prec_ge_3w_ref_val( (x_exp, Less) } else { if limbs_slice_add_limb_in_place(ys, shift_bit) { - fail_on_untested_path( - "add_float_significands_same_prec_ge_3w, exp_diff == 0 && \ - rm == Nearest && out[0] & shift_bit != 0 && carry", - ); x_exp = x_exp.checked_add(1).unwrap(); ys[last_index] = HIGH_BIT; } @@ -2137,9 +2118,6 @@ fn add_float_significands_same_prec_ge_3w_ref_val( Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(ys, shift_bit) { - fail_on_untested_path( - "exp_diff == 0 && (rm == Ceiling || rm == Up) && carry", - ); x_exp = x_exp.checked_add(1).unwrap(); ys[last_index] = HIGH_BIT; } diff --git a/malachite-nz/src/natural/arithmetic/float_div.rs b/malachite-nz/src/natural/arithmetic/float_div.rs new file mode 100644 index 000000000..4c6c32d12 --- /dev/null +++ b/malachite-nz/src/natural/arithmetic/float_div.rs @@ -0,0 +1,1782 @@ +// Copyright © 2024 Mikhail Hogrefe +// +// Uses code adopted from the GNU MPFR Library. +// +// Copyright © 1999-2024 Free Software Foundation, Inc. +// +// Contributed by the AriC and Caramba projects, INRIA. +// +// Uses code adopted from the GNU MP Library. +// +// Copyright © 1991-2018 Free Software Foundation, Inc. +// +// 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 crate::natural::arithmetic::add::{ + limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, +}; +use crate::natural::arithmetic::div::limbs_div_schoolbook_approx; +use crate::natural::arithmetic::div_mod::{ + div_mod_by_preinversion, limbs_div_limb_in_place_mod, limbs_div_limb_to_out_mod, + limbs_div_mod_by_two_limb_normalized, limbs_div_mod_qs_to_out_rs_to_ns, limbs_invert_limb, + limbs_two_limb_inverse_helper, +}; +use crate::natural::arithmetic::float_extras::round_helper_2; +use crate::natural::arithmetic::float_mul::{ + limbs_float_mul_high_same_length, limbs_float_mul_high_same_length_scratch_len, +}; +use crate::natural::arithmetic::mul::{limbs_mul_to_out, limbs_mul_to_out_scratch_len}; +use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; +use crate::natural::arithmetic::shr::{limbs_shr_to_out, limbs_slice_shr_in_place}; +use crate::natural::arithmetic::sub::{ + limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, +}; +use crate::natural::comparison::cmp::limbs_cmp_same_length; +use crate::natural::InnerNatural::{Large, Small}; +use crate::natural::Natural; +use crate::platform::{DoubleLimb, Limb}; +use alloc::vec::Vec; +use core::cmp::Ordering::{self, *}; +use malachite_base::fail_on_untested_path; +use malachite_base::num::arithmetic::traits::{ + CeilingLogBase2, NegModPowerOf2, OverflowingAddAssign, OverflowingNegAssign, Parity, PowerOf2, + ShrRound, WrappingAddAssign, WrappingNegAssign, WrappingSubAssign, XMulYToZZ, XXSubYYToZZ, +}; +use malachite_base::num::basic::integers::PrimitiveInt; +use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; +use malachite_base::num::logic::traits::LeadingZeros; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_base::slices::slice_test_zero; + +// This is mpfr_div from div.c, MPFR 4.3.0. +pub fn div_float_significands_in_place( + x: &mut Natural, + x_prec: u64, + y: &mut Natural, + y_prec: u64, + out_prec: u64, + rm: RoundingMode, +) -> (u64, Ordering) { + if x_prec == y_prec && out_prec == x_prec { + if let Some((increment_exp, o)) = + div_float_significands_in_place_same_prec(x, y, out_prec, rm) + { + return (u64::from(increment_exp), o); + } + } + match (&mut *x, y) { + (Natural(Small(small_x)), Natural(Small(small_y))) => { + let mut xs = vec![*small_x]; + let result = + div_float_significands_long_by_short_in_place(&mut xs, *small_y, out_prec, rm); + *x = Natural::from_owned_limbs_asc(xs); + result + } + (Natural(Large(ref mut xs)), Natural(Small(small_y))) => { + let result = div_float_significands_long_by_short_in_place(xs, *small_y, out_prec, rm); + x.demote_if_small(); + result + } + (Natural(Small(small_x)), Natural(Large(ref mut ys))) => { + let (out, exp_offset, o) = + div_float_significands_general(&[*small_x], ys, out_prec, rm); + *x = Natural::from_owned_limbs_asc(out); + (exp_offset, o) + } + (Natural(Large(xs)), Natural(Large(ref mut ys))) => { + let (out, exp_offset, o) = div_float_significands_general(xs, ys, out_prec, rm); + *x = Natural::from_owned_limbs_asc(out); + (exp_offset, o) + } + } +} + +// This is mpfr_div from div.c, MPFR 4.3.0. +pub fn div_float_significands_in_place_ref( + x: &mut Natural, + x_prec: u64, + y: &Natural, + y_prec: u64, + out_prec: u64, + rm: RoundingMode, +) -> (u64, Ordering) { + if x_prec == y_prec && out_prec == x_prec { + if let Some((increment_exp, o)) = + div_float_significands_in_place_same_prec_ref(x, y, out_prec, rm) + { + return (u64::from(increment_exp), o); + } + } + match (&mut *x, y) { + (Natural(Small(small_x)), Natural(Small(small_y))) => { + let mut xs = vec![*small_x]; + let result = + div_float_significands_long_by_short_in_place(&mut xs, *small_y, out_prec, rm); + *x = Natural::from_owned_limbs_asc(xs); + result + } + (Natural(Large(ref mut xs)), Natural(Small(small_y))) => { + let result = div_float_significands_long_by_short_in_place(xs, *small_y, out_prec, rm); + x.demote_if_small(); + result + } + (Natural(Small(small_x)), y) => { + let mut ys = y.to_limbs_asc(); + let (out, exp_offset, o) = + div_float_significands_general(&[*small_x], &mut ys, out_prec, rm); + *x = Natural::from_owned_limbs_asc(out); + (exp_offset, o) + } + (Natural(Large(xs)), y) => { + let mut ys = y.to_limbs_asc(); + let (out, exp_offset, o) = div_float_significands_general(xs, &mut ys, out_prec, rm); + *x = Natural::from_owned_limbs_asc(out); + (exp_offset, o) + } + } +} + +// This is mpfr_div from div.c, MPFR 4.3.0. +pub fn div_float_significands_ref_val( + x: &Natural, + x_prec: u64, + y: &mut Natural, + y_prec: u64, + out_prec: u64, + rm: RoundingMode, +) -> (Natural, u64, Ordering) { + if x_prec == y_prec && out_prec == x_prec { + if let Some((quotient, increment_exp, o)) = + div_float_significands_same_prec_ref_val(x, y, out_prec, rm) + { + return (quotient, u64::from(increment_exp), o); + } + } + match (x, y) { + (Natural(Small(small_x)), Natural(Small(small_y))) => { + let (qs, exp_offset, o) = + div_float_significands_long_by_short(&[*small_x], *small_y, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + (Natural(Large(xs)), Natural(Small(small_y))) => { + let (qs, exp_offset, o) = + div_float_significands_long_by_short(xs, *small_y, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + (Natural(Small(small_x)), Natural(Large(ref mut ys))) => { + let (qs, exp_offset, o) = div_float_significands_general(&[*small_x], ys, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + (Natural(Large(xs)), Natural(Large(ref mut ys))) => { + let (qs, exp_offset, o) = div_float_significands_general(xs, ys, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + } +} + +// This is mpfr_div from div.c, MPFR 4.3.0. +pub fn div_float_significands_ref_ref( + x: &Natural, + x_prec: u64, + y: &Natural, + y_prec: u64, + out_prec: u64, + rm: RoundingMode, +) -> (Natural, u64, Ordering) { + if x_prec == y_prec && out_prec == x_prec { + if let Some((quotient, increment_exp, o)) = + div_float_significands_same_prec_ref_ref(x, y, out_prec, rm) + { + return (quotient, u64::from(increment_exp), o); + } + } + match (x, y) { + (Natural(Small(small_x)), Natural(Small(small_y))) => { + let (qs, exp_offset, o) = + div_float_significands_long_by_short(&[*small_x], *small_y, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + (Natural(Large(xs)), Natural(Small(small_y))) => { + let (qs, exp_offset, o) = + div_float_significands_long_by_short(xs, *small_y, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + (Natural(Small(small_x)), y) => { + let mut ys = y.to_limbs_asc(); + let (qs, exp_offset, o) = + div_float_significands_general(&[*small_x], &mut ys, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + (Natural(Large(xs)), y) => { + let mut ys = y.to_limbs_asc(); + let (qs, exp_offset, o) = div_float_significands_general(xs, &mut ys, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + } +} + +fn div_float_significands_in_place_same_prec( + x: &mut Natural, + y: &mut Natural, + prec: u64, + rm: RoundingMode, +) -> Option<(bool, Ordering)> { + match (x, y) { + (Natural(Small(x)), Natural(Small(y))) => { + let (quotient, increment_exp, o) = if prec == Limb::WIDTH { + div_float_significands_same_prec_w(*x, *y, rm) + } else { + div_float_significands_same_prec_lt_w(*x, *y, prec, rm) + }; + *x = quotient; + Some((increment_exp, o)) + } + (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_mut_slice()) { + ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { + let (quotient_0, quotient_1, increment_exp, o) = + div_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); + *x_0 = quotient_0; + *x_1 = quotient_1; + Some((increment_exp, o)) + } + _ => None, + }, + _ => None, + } +} + +fn div_float_significands_in_place_same_prec_ref( + x: &mut Natural, + y: &Natural, + prec: u64, + rm: RoundingMode, +) -> Option<(bool, Ordering)> { + match (x, y) { + (Natural(Small(x)), Natural(Small(y))) => { + let (quotient, increment_exp, o) = if prec == Limb::WIDTH { + div_float_significands_same_prec_w(*x, *y, rm) + } else { + div_float_significands_same_prec_lt_w(*x, *y, prec, rm) + }; + *x = quotient; + Some((increment_exp, o)) + } + (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_slice()) { + ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { + let (quotient_0, quotient_1, increment_exp, o) = + div_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); + *x_0 = quotient_0; + *x_1 = quotient_1; + Some((increment_exp, o)) + } + _ => None, + }, + _ => None, + } +} + +fn div_float_significands_same_prec_ref_val( + x: &Natural, + y: &mut Natural, + prec: u64, + rm: RoundingMode, +) -> Option<(Natural, bool, Ordering)> { + match (x, y) { + (Natural(Small(x)), Natural(Small(y))) => { + let (quotient, increment_exp, o) = if prec == Limb::WIDTH { + div_float_significands_same_prec_w(*x, *y, rm) + } else { + div_float_significands_same_prec_lt_w(*x, *y, prec, rm) + }; + Some((Natural(Small(quotient)), increment_exp, o)) + } + (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_slice(), ys.as_slice()) { + ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { + let (quotient_0, quotient_1, increment_exp, o) = + div_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); + Some(( + Natural(Large(vec![quotient_0, quotient_1])), + increment_exp, + o, + )) + } + _ => None, + }, + _ => None, + } +} +fn div_float_significands_same_prec_ref_ref( + x: &Natural, + y: &Natural, + prec: u64, + rm: RoundingMode, +) -> Option<(Natural, bool, Ordering)> { + match (x, y) { + (Natural(Small(x)), Natural(Small(y))) => { + let (quotient, increment_exp, o) = if prec == Limb::WIDTH { + div_float_significands_same_prec_w(*x, *y, rm) + } else { + div_float_significands_same_prec_lt_w(*x, *y, prec, rm) + }; + Some((Natural(Small(quotient)), increment_exp, o)) + } + (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_slice(), ys.as_slice()) { + ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { + let (quotient_0, quotient_1, increment_exp, o) = + div_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); + Some(( + Natural(Large(vec![quotient_0, quotient_1])), + increment_exp, + o, + )) + } + _ => None, + }, + _ => None, + } +} + +const WIDTH_M1: u64 = Limb::WIDTH - 1; +const HIGH_BIT: Limb = 1 << WIDTH_M1; +const TWICE_WIDTH: u64 = Limb::WIDTH * 2; + +// This is mpfr_div_1 from mul.c, MPFR 4.3.0. +fn div_float_significands_same_prec_lt_w( + mut x: Limb, + y: Limb, + prec: u64, + rm: RoundingMode, +) -> (Limb, bool, Ordering) { + let shift = Limb::WIDTH - prec; + let shift_bit = Limb::power_of_2(shift); + let half_shift_bit = shift_bit >> 1; + let mask = shift_bit - 1; + let increment_exp = x >= y; + if increment_exp { + x -= y; + } + // First try with an approximate quotient. + let mut round_bit = Limb::wrapping_from( + (DoubleLimb::from(x) * DoubleLimb::from(limbs_invert_limb(y))) >> Limb::WIDTH, + ); + round_bit.wrapping_add_assign(x); + let mut q = if increment_exp { + round_bit >> 1 + } else { + round_bit + }; + // round_bit does not exceed the true quotient floor(x * 2 ^ WIDTH / y), with error at most 2, + // which means the rational quotient q satisfies round_bit <= q < round_bit + 3. We can round + // correctly except when the last shift - 1 bits of q0 are 000..000 or 111..111 or 111..110. + let sticky_bit = if (q + 2) & (mask >> 1) > 2 { + round_bit = q & half_shift_bit; + // result cannot be exact in this case + 1 + } else { + // The true quotient is round_bit, round_bit + 1, or round_bit + 2 + q = round_bit; + let (mut hi, mut lo) = Limb::x_mul_y_to_zz(q, y); + assert!(hi < x || (hi == x && lo == 0)); + // subtract {hi, lo} from {x, 0} + (hi, lo) = Limb::xx_sub_yy_to_zz(x, 0, hi, lo); + // the remainder {hi, lo} should be < y. + if hi != 0 || lo >= y { + q += 1; + if lo < y { + hi.wrapping_sub_assign(1); + } + lo.wrapping_sub_assign(y); + } + if hi != 0 || lo >= y { + q += 1; + if lo < y { + hi.wrapping_sub_assign(1); + } + lo.wrapping_sub_assign(y); + } + assert!(hi == 0 && lo < y); + let sticky_bit; + if increment_exp { + sticky_bit = lo | (q & 1); + q >>= 1; + } else { + sticky_bit = lo; + } + round_bit = q & half_shift_bit; + sticky_bit | (q & (mask >> 1)) + }; + let quotient = (HIGH_BIT | q) & !mask; + if round_bit == 0 && sticky_bit == 0 { + return (quotient, increment_exp, Equal); + } + match rm { + Exact => panic!("Inexact float division"), + Nearest => { + if round_bit == 0 || sticky_bit == 0 && quotient & shift_bit == 0 { + (quotient, increment_exp, Less) + } else { + (quotient.wrapping_add(shift_bit), increment_exp, Greater) + } + } + Floor | Down => (quotient, increment_exp, Less), + Ceiling | Up => (quotient.wrapping_add(shift_bit), increment_exp, Greater), + } +} + +// This is mpfr_div_1n from mul.c, MPFR 4.3.0. +fn div_float_significands_same_prec_w( + mut x: Limb, + y: Limb, + rm: RoundingMode, +) -> (Limb, bool, Ordering) { + let increment_exp = x >= y; + if increment_exp { + x -= y; + } + // First compute an approximate quotient. + let mut q = x.wrapping_add(Limb::wrapping_from( + (DoubleLimb::from(x) * DoubleLimb::from(limbs_invert_limb(y))) >> Limb::WIDTH, + )); + // round_bit does not exceed the true quotient floor(x * 2 ^ WIDTH / y), with error at most 2, + // which means the rational quotient q satisfies round_bit <= q < round_bit + 3, thus the true + // quotient is round_bit, round_bit + 1 or round_bit + 2. + let (mut hi, mut lo) = Limb::x_mul_y_to_zz(q, y); + assert!(hi < x || (hi == x && lo == 0)); + // subtract {hi, lo} from {x, 0} + (hi, lo) = Limb::xx_sub_yy_to_zz(x, 0, hi, lo); + // the remainder {hi, lo} should be < y. + if hi != 0 || lo >= y { + q += 1; + if lo < y { + hi.wrapping_sub_assign(1); + } + lo.wrapping_sub_assign(y); + } + if hi != 0 || lo >= y { + q += 1; + if lo < y { + hi.wrapping_sub_assign(1); + } + lo.wrapping_sub_assign(y); + } + assert!(hi == 0 && lo < y); + // now (x - extra * y) * 2 ^ WIDTH = q * y + lo with 0 <= lo < y + // + // If !increment_exp, the quotient is q0, the round bit is 1 if l >= y0 / 2, and sticky_bit are + // the remaining bits from l. If increment_exp, the quotient is HIGH_BIT + (q >> 1), the round + // bit is the least significant bit of q, and sticky_bit is lo. + let round_bit; + let (quotient, sticky_bit) = if increment_exp { + round_bit = q.odd(); + (HIGH_BIT | (q >> 1), lo) + } else { + // If "lo + lo < lo", then there is a carry in lo + lo, thus 2 * lo > y. Otherwise if there + // is no carry, we check whether 2 * lo >= v0. + let two_lo = lo << 1; + round_bit = (two_lo < lo) || (two_lo >= y); + ( + q, + if round_bit { + two_lo.wrapping_sub(y) + } else { + lo + }, + ) + }; + if !round_bit && sticky_bit == 0 { + return (quotient, increment_exp, Equal); + } + match rm { + Exact => panic!("Inexact float division"), + Nearest => { + if !round_bit || sticky_bit == 0 && quotient.even() { + (quotient, increment_exp, Less) + } else { + (quotient.wrapping_add(1), increment_exp, Greater) + } + } + Floor | Down => (quotient, increment_exp, Less), + Ceiling | Up => (quotient.wrapping_add(1), increment_exp, Greater), + } +} + +// Given x = x_1 * B + x_0 < y = y_1 * B + y_0 with y normalized (high bit of y_1 set), put in q = +// Q1 +// * B + Q0 an approximation of floor(x * B ^ 2 / y), with: B = 2 ^ WIDTH and q <= floor(x * B ^ 2 / +// y) <= q + 21. +// +// This is mpfr_div2_approx from div.c, MPFR 4.3.0, where Q0 and Q1 are returned. +fn div_float_2_approx(x_1: Limb, x_0: Limb, y_1: Limb, y_0: Limb) -> (Limb, Limb) { + // First compute an approximation of q_1, using a lower approximation of B ^ 2 / (y_1 + 1) - B + let inv = if y_1 == Limb::MAX { + 0 + } else { + limbs_invert_limb(y_1 + 1) + }; + // Now inv <= B ^ 2 / (y_1 + 1) - B. + let mut q_1 = + Limb::wrapping_from((DoubleLimb::from(x_1) * DoubleLimb::from(inv)) >> Limb::WIDTH); + q_1.wrapping_add_assign(x_1); + // Now q_1 <= x_1 * B / (y_1 + 1) < (x_1 * B + x_0) * B / (y_1 * B + y_0). + // + // Compute q_1 * (y_1 * B + y_0) into r_1 : r_0 : yy and subtract from u_1 : x_0 : 0. + let (mut r_1, mut r_0) = Limb::x_mul_y_to_zz(q_1, y_1); + let (xx, yy) = Limb::x_mul_y_to_zz(q_1, y_0); + if r_0.overflowing_add_assign(xx) { + r_1.wrapping_add_assign(1); + } + // We ignore yy below, but first increment r_0, to ensure we get a lower approximation of the + // remainder. + if yy != 0 { + r_0.wrapping_add_assign(1); + } + if r_0 == 0 && yy != 0 { + r_1.wrapping_add_assign(1); + } + r_1 = x_1.wrapping_sub(r_1); + let carry; + (r_0, carry) = x_0.overflowing_sub(r_0); + if carry { + r_1.wrapping_sub_assign(1); + } + // r_1 : r_0 should be non-negative. + assert!(!r_1.get_highest_bit()); + // The second quotient limb is approximated by (r_1 * B ^ 2 + r_0 * B) / y_1, and since (B + + // inv) / B approximates B / y_1, this is in turn approximated by (r * B + r_0) * (B + inv) / B + // = r_1 * B * r_1 * inv + r_0 + (r0 * inv / B). + q_1.wrapping_add_assign(r_1); + // Add floor(r_0 * inv / B) to q_0. + if r_0.overflowing_add_assign(Limb::wrapping_from( + (DoubleLimb::from(r_0) * DoubleLimb::from(inv)) >> Limb::WIDTH, + )) { + q_1.wrapping_add_assign(1); + } + assert!(r_1 <= 4); + for _ in 0..r_1 { + if r_0.overflowing_add_assign(inv) { + q_1.wrapping_add_assign(1); + } + } + (q_1, r_0) +} + +// This is mpfr_div_2 from div.c, MPFR 4.3.0, where Q1 and Q0 are returned. +fn div_float_significands_same_prec_gt_w_lt_2w( + mut x_0: Limb, + mut x_1: Limb, + y_0: Limb, + y_1: Limb, + prec: u64, + rm: RoundingMode, +) -> (Limb, Limb, bool, Ordering) { + let shift = TWICE_WIDTH - prec; + let shift_bit = Limb::power_of_2(shift); + let mask = shift_bit - 1; + let increment_exp = x_1 > y_1 || (x_1 == y_1 && x_0 >= y_0); + if increment_exp { + (x_1, x_0) = Limb::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0); + } + assert!(x_1 < y_1 || (x_1 == y_1 && x_0 < y_0)); + let (mut q_1, mut q_0) = div_float_2_approx(x_1, x_0, y_1, y_0); + // We know q1 * B + q0 is smaller or equal to the exact quotient, with difference at most 21. + let mut sticky_bit = if (q_0.wrapping_add(21)) & (mask >> 1) > 21 { + // The result is not exact when we can round with an approximation. + 1 + } else { + // We know q_1 : q_0 is a good-enough approximation, so use it! + // + // Since we know the difference should be at most 21 * (y_1 : y_0) after the subtraction + // below, thus at most 21 * 2 ^ 128, it suffices to compute the lower 3 limbs of (q_1 : q_0) + // * (y_1 : y_0). + let (mut s_1, mut s_0) = Limb::x_mul_y_to_zz(q_0, y_0); + let (mut s_2, mut lo) = Limb::x_mul_y_to_zz(q_0, y_1); + if s_1.overflowing_add_assign(lo) { + s_2.wrapping_add_assign(1); + } + let hi; + (hi, lo) = Limb::x_mul_y_to_zz(q_1, y_0); + s_2.wrapping_add_assign(hi); + if s_1.overflowing_add_assign(lo) { + s_2.wrapping_add_assign(1); + } + s_2.wrapping_add_assign(q_1.wrapping_mul(y_1)); + // Subtract s_2 : s_1 : s_0 from x_0 : 0 : 0, with result in s_2 : s_1 : s_0. + s_2 = x_0.wrapping_sub(s_2); + // Now negate s_1 : s_0. + s_1.wrapping_neg_assign(); + if s_0.overflowing_neg_assign() { + s_1.wrapping_sub_assign(1); + } + // There is a borrow in s_2 when s_0 and s_1 are not both zero. + if s_1 != 0 || s_0 != 0 { + s_2.wrapping_sub_assign(1); + } + while s_2 > 0 || s_1 > y_1 || (s_1 == y_1 && s_0 >= y_0) { + // Add 1 to q_1 : q_0. + if q_0.overflowing_add_assign(1) { + q_1.wrapping_add_assign(1); + } + // Subtract y_1 : y_0 to s_2 : s_1 : s_0 + if (s_1 < y_1) || (s_1 == y_1 && s_0 < y_0) { + s_2.wrapping_sub_assign(1); + } + (s_1, s_0) = Limb::xx_sub_yy_to_zz(s_1, s_0, y_1, y_0); + } + s_1 | s_0 + }; + if increment_exp { + sticky_bit |= q_0 & 1; + q_0 = (q_1 << WIDTH_M1) | (q_0 >> 1); + q_1 = HIGH_BIT | (q_1 >> 1); + } + let round_bit = q_0 & (shift_bit >> 1); + sticky_bit |= (q_0 & mask) ^ round_bit; + let mut z_1 = q_1; + let mut z_0 = q_0 & !mask; + if round_bit == 0 && sticky_bit == 0 { + return (z_0, z_1, increment_exp, Equal); + } + match rm { + Exact => panic!("Inexact float division"), + Nearest => { + if round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0) { + (z_0, z_1, increment_exp, Less) + } else if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { + (z_0, HIGH_BIT, false, Greater) + } else { + (z_0, z_1, increment_exp, Greater) + } + } + Floor | Down => (z_0, z_1, increment_exp, Less), + Ceiling | Up => { + if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { + (z_0, HIGH_BIT, false, Greater) + } else { + (z_0, z_1, increment_exp, Greater) + } + } + } +} + +// This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, assuming the +// highest bit of `d` is set. +fn limbs_div_limb_to_out_mod_with_fraction( + out: &mut [Limb], + fraction_len: usize, + ns: &[Limb], + d: Limb, +) -> Limb { + assert_ne!(d, 0); + let len = ns.len().checked_add(fraction_len).unwrap(); + assert_ne!(len, 0); + let out = &mut out[..len]; + assert!(d.get_highest_bit()); + // High quotient limb is 0 or 1, skip a divide step. + let (r, ns_init) = ns.split_last().unwrap(); + let mut r = *r; + let (out_last, out_init) = out.split_last_mut().unwrap(); + let adjust = r >= d; + if adjust { + r -= d; + } + *out_last = Limb::from(adjust); + // Multiply-by-inverse, divisor already normalized. + let d_inv = limbs_invert_limb(d); + let (out_lo, out_hi) = out_init.split_at_mut(fraction_len); + for (out_q, &n) in out_hi.iter_mut().zip(ns_init.iter()).rev() { + (*out_q, r) = div_mod_by_preinversion(r, n, d, d_inv); + } + for out_q in out_lo.iter_mut().rev() { + (*out_q, r) = div_mod_by_preinversion(r, 0, d, d_inv); + } + r +} + +// This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, assuming the +// highest bit of `d` is set. +fn limbs_div_limb_in_place_mod_with_fraction( + ns: &mut [Limb], + ns_len: usize, + fraction_len: usize, + d: Limb, +) -> Limb { + assert_ne!(d, 0); + let len = ns_len.checked_add(fraction_len).unwrap(); + assert_ne!(len, 0); + let ns = &mut ns[..len]; + assert!(d.get_highest_bit()); + // High quotient limb is 0 or 1, skip a divide step. + let mut r = ns[ns_len - 1]; + let adjust = r >= d; + if adjust { + r -= d; + } + ns.copy_within(..ns_len, fraction_len); + let (ns_high, ns_init) = ns.split_last_mut().unwrap(); + *ns_high = Limb::from(adjust); + // Multiply-by-inverse, divisor already normalized. + let d_inv = limbs_invert_limb(d); + let (ns_lo, ns_hi) = ns_init.split_at_mut(fraction_len); + for n in ns_hi.iter_mut().rev() { + (*n, r) = div_mod_by_preinversion(r, *n, d, d_inv); + } + for n in ns_lo.iter_mut().rev() { + (*n, r) = div_mod_by_preinversion(r, 0, d, d_inv); + } + r +} + +// This is mpfr_div_ui from div_ui.c, MPFR 4.3.0. +fn div_float_significands_long_by_short( + xs: &[Limb], + y: Limb, + prec: u64, + rm: RoundingMode, +) -> (Vec, u64, Ordering) { + let out_len = usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0); + let mut out = vec![0; out_len + 1]; + let (exp_offset, o) = div_float_significands_long_by_short_to_out(&mut out, xs, y, prec, rm); + out.truncate(out_len); + (out, exp_offset, o) +} + +// y cannot be a power of 2. +// +// This is mpfr_div_ui from div_ui.c, MPFR 4.3.0. +fn div_float_significands_long_by_short_to_out( + out: &mut [Limb], + xs: &[Limb], + y: Limb, + prec: u64, + rm: RoundingMode, +) -> (u64, Ordering) { + let xs_len = xs.len(); + let out_ge_xs = out.len() >= xs_len; + let diff = out.len().abs_diff(xs_len); + // We need to store out_len + 1 = xs_len + diff limbs of the quotient. + let (c, mut sticky_bit) = if out_ge_xs { + // used the entire dividend + // + // X = ({scratch, xs_len + diff} * y + c) * B ^ (-diff} = ({scratch, out_len + 1} * y + c) * + // B ^ (-dif) + (limbs_div_limb_to_out_mod_with_fraction(out, diff, xs, y), 0) + } else { + // dif < 0, i.e. xs_len > out_len + 1; ignore the (-diff) low limbs from x + // + // {xs - dif, out_len + 1} = {scratch, out_len + 1} * y + c, thus X = {xs, -dif} + {xs - + // diff, out_len + 1} * B ^ (-diff) = {xp, -diff} + ({scratch, out_len + 1} * y + c) * B ^ + // (-dif) + let (xs_lo, xs_hi) = xs.split_at(diff); + ( + limbs_div_limb_to_out_mod(out, xs_hi, y), + Limb::from(!slice_test_zero(xs_lo)), + ) + }; + // Let r = {xp, -diff} / B ^ (-diff) if diff < 0, r = 0 otherwise; 0 <= r < 1. + // + // Then X = ({scratch, out_len + 1} * y + c + r) * B ^ (-dif). x / y = (X / y) * B ^ (-xs_len) * + // 2 ^ exp = ({scratch, out_len + 1} + (c + r) / y) * B ^ (-(out_len + 1)) * 2 ^ exp where 0 <= + // (c + r) / y < 1. + // + // sticky_bit != 0 iff r != 0 + // + // If the highest limb of the result is 0 (xs[xs_len - 1] < y), remove it. Otherwise, compute + // the left shift to be performed to normalize. In the latter case, we discard some low bits + // computed. They contain information useful for the rounding, hence the updating of middle and + // inexact. + let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); + let shift_bit = Limb::power_of_2(shift); + let shift_mask = shift_bit - 1; + let out_head = out[0]; + let out_last = *out.last().unwrap(); + let round_bit; + let mut exp_offset = if out_last == 0 { + // round bit is 1 iff (c + r) / u >= 1/2 + if shift == 0 { + // In this case scratch[out_len] = 0 and shift = 0, the round bit is not in {scratch, + // out_len + 1}. It is 1 iff 2 * (c + r) - y >= 0. This means that in some cases, we + // should look at the most significant bit of r. + if c >= y - c { + // i.e. 2 * c >= y: round bit is always 1 + round_bit = 1; + // The sticky bit is 1 unless 2 * c - y = 0 and r = 0. + sticky_bit |= (c << 1).wrapping_sub(y); + } else { + // 2 * c < y + // + // The round bit is 1 iff r >= 1 / 2 and 2 * (c + 1 / 2) = y. + let xdm1 = if diff == 0 { + 0 + } else { + xs.get(diff - 1).copied().unwrap_or_default() + }; + round_bit = Limb::from(c == y >> 1 && !out_ge_xs && xdm1.get_highest_bit()); + // If round_bit is set, we need to recompute sticky_bit, since it might have taken + // into account the most-significant bit of xs[-diff - 1]. + if round_bit != 0 { + fail_on_untested_path("div_float_significands_long_by_short, round_bit != 0"); + sticky_bit = xdm1 << 1; // discard the most significant bit + if sticky_bit == 0 && !slice_test_zero(&xs[..diff]) { + sticky_bit = 1; + } + } else { + sticky_bit |= c; + } + } + } else { + // round bit is in scratch[0] + round_bit = out_head & (shift_bit >> 1); + sticky_bit |= (out_head & (shift_mask >> 1)) | c; + } + 0 + } else { + // scratch[out_len] != 0 + assert_ne!(out_last, 0); + let shift_2 = LeadingZeros::leading_zeros(out_last); + let comp_shift_2 = Limb::WIDTH - shift_2; + assert!(y >= 2); // see special cases at the beginning + assert_ne!(shift_2, 0); // since y >= 2, shift left to normalize + let old_head_1 = out_head >> comp_shift_2; + let old_head_2 = out_head << shift_2; + out.copy_within(1.., 0); + limbs_slice_shl_in_place(out, shift_2); + let out_head = out.first_mut().unwrap(); + *out_head |= old_head_1; + // now Y is the approximate quotient, w is the next limb. + let w = old_head_2; + if shift == 0 { + // round bit is upper bit from w + round_bit = w & HIGH_BIT; + sticky_bit |= (w - round_bit) | c; + } else { + round_bit = *out_head & (shift_bit >> 1); + sticky_bit |= (*out_head & (shift_mask >> 1)) | w | c; + } + comp_shift_2 + }; + // Clear the lowest `shift` bits + out[0] &= !shift_mask; + if round_bit == 0 && sticky_bit == 0 { + return (exp_offset, Equal); + } + let (_, out) = out.split_last_mut().unwrap(); + match rm { + Exact => panic!("Inexact float division"), + Nearest => { + if round_bit == 0 || (sticky_bit == 0 && (out[0] & shift_bit) == 0) { + (exp_offset, Less) + } else { + if limbs_slice_add_limb_in_place(out, shift_bit) { + exp_offset += 1; + *out.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } + } + Floor | Down => (exp_offset, Less), + Ceiling | Up => { + if limbs_slice_add_limb_in_place(out, shift_bit) { + exp_offset += 1; + *out.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } + } +} + +// y cannot be a power of 2. +// +// This is mpfr_div_ui from div_ui.c, MPFR 4.3.0. +fn div_float_significands_long_by_short_in_place( + xs: &mut Vec, + y: Limb, + prec: u64, + rm: RoundingMode, +) -> (u64, Ordering) { + let xs_len = xs.len(); + let out_len = usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0); + let out_ge_xs = out_len + 1 >= xs_len; + let diff = (out_len + 1).abs_diff(xs_len); + let x_lo_nonzero = diff < xs_len && !slice_test_zero(&xs[..diff]); + let xdm1 = if diff == 0 { + 0 + } else { + xs.get(diff - 1).copied().unwrap_or_default() + }; + // We need to store out_len + 1 = xs_len + diff limbs of the quotient. + let (c, mut sticky_bit) = if out_ge_xs { + // used the entire dividend + // + // X = ({scratch, xs_len + diff} * y + c) * B ^ (-diff} = ({scratch, out_len + 1} * y + c) * + // B ^ (-dif) + xs.resize(out_len + 1, 0); + ( + limbs_div_limb_in_place_mod_with_fraction(xs, xs_len, diff, y), + 0, + ) + } else { + // dif < 0, i.e. xs_len > out_len + 1; ignore the (-diff) low limbs from x + // + // {xs - dif, out_len + 1} = {scratch, out_len + 1} * y + c, thus X = {xs, -dif} + {xs - + // diff, out_len + 1} * B ^ (-diff) = {xp, -diff} + ({scratch, out_len + 1} * y + c) * B ^ + // (-dif) + let p = ( + limbs_div_limb_in_place_mod(&mut xs[diff..], y), + Limb::from(x_lo_nonzero), + ); + xs.drain(..diff); + p + }; + // Let r = {xp, -diff} / B ^ (-diff) if diff < 0, r = 0 otherwise; 0 <= r < 1. + // + // Then X = ({scratch, out_len + 1} * y + c + r) * B ^ (-dif). x / y = (X / y) * B ^ (-xs_len) * + // 2 ^ exp = ({scratch, out_len + 1} + (c + r) / y) * B ^ (-(out_len + 1)) * 2 ^ exp where 0 <= + // (c + r) / y < 1. + // + // sticky_bit != 0 iff r != 0 + // + // If the highest limb of the result is 0 (xs[xs_len - 1] < y), remove it. Otherwise, compute + // the left shift to be performed to normalize. In the latter case, we discard some low bits + // computed. They contain information useful for the rounding, hence the updating of middle and + // inexact. + let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); + let shift_bit = Limb::power_of_2(shift); + let shift_mask = shift_bit - 1; + let xs_head = xs[0]; + let xs_last = *xs.last().unwrap(); + let round_bit; + let mut exp_offset = if xs_last == 0 { + // round bit is 1 iff (c + r) / u >= 1/2 + if shift == 0 { + // In this case scratch[out_len] = 0 and shift = 0, the round bit is not in {scratch, + // out_len + 1}. It is 1 iff 2 * (c + r) - y >= 0. This means that in some cases, we + // should look at the most significant bit of r. + if c >= y - c { + // i.e. 2 * c >= y: round bit is always 1 + round_bit = 1; + // The sticky bit is 1 unless 2 * c - y = 0 and r = 0. + sticky_bit |= (c << 1).wrapping_sub(y); + } else { + // 2 * c < y + // + // The round bit is 1 iff r >= 1 / 2 and 2 * (c + 1 / 2) = y. + round_bit = Limb::from(c == y >> 1 && !out_ge_xs && xdm1.get_highest_bit()); + // If round_bit is set, we need to recompute sticky_bit, since it might have taken + // into account the most-significant bit of xs[-diff - 1]. + if round_bit != 0 { + fail_on_untested_path("div_float_significands_long_by_short, round_bit != 0"); + sticky_bit = xdm1 << 1; // discard the most significant bit + if sticky_bit == 0 && x_lo_nonzero { + sticky_bit = 1; + } + } else { + sticky_bit |= c; + } + } + } else { + // round bit is in scratch[0] + round_bit = xs_head & (shift_bit >> 1); + sticky_bit |= (xs_head & (shift_mask >> 1)) | c; + } + 0 + } else { + // scratch[out_len] != 0 + assert_ne!(xs_last, 0); + let shift_2 = LeadingZeros::leading_zeros(xs_last); + let comp_shift_2 = Limb::WIDTH - shift_2; + assert!(y >= 2); // see special cases at the beginning + assert_ne!(shift_2, 0); // since y >= 2, shift left to normalize + let old_head_1 = xs_head >> comp_shift_2; + let old_head_2 = xs_head << shift_2; + xs.copy_within(1.., 0); + limbs_slice_shl_in_place(xs, shift_2); + let xs_head = xs.first_mut().unwrap(); + *xs_head |= old_head_1; + // now Y is the approximate quotient, w is the next limb. + let w = old_head_2; + if shift == 0 { + // round bit is upper bit from w + round_bit = w & HIGH_BIT; + sticky_bit |= (w - round_bit) | c; + } else { + round_bit = *xs_head & (shift_bit >> 1); + sticky_bit |= (*xs_head & (shift_mask >> 1)) | w | c; + } + comp_shift_2 + }; + // Clear the lowest `shift` bits + xs[0] &= !shift_mask; + xs.truncate(out_len); + if round_bit == 0 && sticky_bit == 0 { + return (exp_offset, Equal); + } + match rm { + Exact => panic!("Inexact float division"), + Nearest => { + if round_bit == 0 || (sticky_bit == 0 && (xs[0] & shift_bit) == 0) { + (exp_offset, Less) + } else { + if limbs_slice_add_limb_in_place(xs, shift_bit) { + exp_offset += 1; + *xs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } + } + Floor | Down => (exp_offset, Less), + Ceiling | Up => { + if limbs_slice_add_limb_in_place(xs, shift_bit) { + exp_offset += 1; + *xs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } + } +} + +pub(crate) const MPFR_DIVHIGH_TAB: [i8; 17] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + +// This is `mpn_divrem` from `mpn/divrem.c`, GMP 6.2.1, where qxn is 0. +pub(crate) fn limbs_div_helper(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb]) -> bool { + let ns_len = ns.len(); + let ds_len = ds.len(); + assert!(ns_len >= ds_len); + assert_ne!(ds_len, 0); + assert!(ds[ds_len - 1].get_highest_bit()); + if ds_len == 2 { + limbs_div_mod_by_two_limb_normalized(qs, ns, ds) + } else { + let qs_len = ns_len - ds_len + 1; + let mut scratch = vec![0; qs_len]; + if ds_len == 1 { + ns[0] = limbs_div_limb_to_out_mod(&mut scratch, ns, ds[0]); + } else { + limbs_div_mod_qs_to_out_rs_to_ns(&mut scratch, ns, ds); + } + let (scratch_last, scratch_init) = scratch.split_last().unwrap(); + qs[..qs_len - 1].copy_from_slice(scratch_init); + assert!(*scratch_last < 2); + *scratch_last != 0 + } +} + +pub(crate) fn limbs_float_div_high_scratch_len(ds_len: usize) -> usize { + let k = if ds_len < MPFR_DIVHIGH_TAB.len() { + usize::exact_from(MPFR_DIVHIGH_TAB[ds_len]) + } else { + (ds_len / 3) << 1 + }; + if k == 0 { + 0 + } else { + let l = ds_len - k; + (l << 1) + limbs_float_mul_high_same_length_scratch_len(l) + } +} + +// Put in {qs, len} an approximation of N = {ns, 2 * len} divided by D = {ds, len}, +// +// with the most significant limb of the quotient as return value (0 or 1). Assumes the most +// significant bit of D is set. Clobbers N. +// +// This implements the ShortDiv algorithm from Short Division of Long Integers, David Harvey and +// Paul Zimmermann, Proceedings of the 20th Symposium on Computer Arithmetic (ARITH-20), July 25-27, +// 2011, pages 7-14. +// +// Assumes len >= 2 (which should be fulfilled also in the recursive calls). +// +// This is mpfr_divhigh_n from mulders.c, MPFR 4.2.0. +pub(crate) fn limbs_float_div_high( + qs: &mut [Limb], + ns: &mut [Limb], + ds: &[Limb], + scratch: &mut [Limb], +) -> bool { + let len = ds.len(); + const LENGTH_VALID: bool = MPFR_DIVHIGH_TAB.len() >= 15; + assert!(LENGTH_VALID); // so that 2*(n/3) >= (n+4)/2 + assert!(len >= 2); + let k = if len < MPFR_DIVHIGH_TAB.len() { + usize::exact_from(MPFR_DIVHIGH_TAB[len]) + } else { + (len / 3) << 1 + }; + let ns = &mut ns[..len << 1]; + let qs = &mut qs[..len]; + if k == 0 { + assert!(len > 2, "must implement mpfr_divhigh_n_basecase"); + let inverse = limbs_two_limb_inverse_helper(ds[len - 1], ds[len - 2]); + return limbs_div_schoolbook_approx(qs, ns, ds, inverse); + } + // Check the bounds from. In addition, we forbid k = len - 1, which would give l = 1 in the + // recursive call. It follows len >= 5. + assert!((len + 4) >> 1 <= k && k < len - 1); + let l = len - k; + let two_l = l << 1; + let two_len_m_k = len + l; + // first divide the most significant 2 * k limbs from N by the most significant k limbs of D + // exact + let (ds_lo, ds_hi) = ds.split_at(l); + let mut q_high = limbs_div_helper(&mut qs[l..], &mut ns[two_l..], ds_hi); + // It remains {ns, 2 * l + k} = {ns, len + l} as remainder + // + // now we have to subtract high(Q1) * D0 where Q1 = q_high * B ^ k + {qs + l, k} and D0 = {ds, + // l} + let (scratch_lo, scratch_hi) = scratch.split_at_mut(two_l); + limbs_float_mul_high_same_length(scratch_lo, &qs[k..], ds_lo, scratch_hi); + // We are only interested in the upper l limbs from {scratch, 2 * l} + let ns_mid = &mut ns[len..two_len_m_k]; + let mut carry = Limb::from(limbs_sub_same_length_in_place_left( + ns_mid, + &scratch_lo[l..], + )); + if q_high && limbs_sub_same_length_in_place_left(ns_mid, ds_lo) { + carry += 1; + } + while carry != 0 { + // Q1 was too large: subtract 1 from Q1 and add D to ns + l + if limbs_sub_limb_in_place(&mut qs[l..], 1) { + q_high = false; + } + if limbs_slice_add_same_length_in_place_left(&mut ns[l..two_len_m_k], ds) { + carry -= 1; + } + } + // Now it remains {ns, len + l} to divide by D + limbs_float_div_high(qs, &mut ns[k..], &ds[k..], scratch) + && limbs_slice_add_limb_in_place(&mut qs[l..], 1) + || q_high +} + +// Compare {xs, xs_len} and {ys, ys_len} >> extra, aligned by the more significant limbs. Takes into +// account ys[0] for extra = true. +// +// This is mpfr_mpn_cmp_aux from div.c, MPFR 4.2.0. +pub fn cmp_helper(xs: &[Limb], ys: &[Limb], extra: bool) -> Ordering { + let xs_len = xs.len(); + let mut cmp = Equal; + if extra { + let ys_len = ys.len() - 1; + if xs_len >= ys_len { + let (xs_lo, xs_hi) = xs.split_at(xs_len - ys_len); + for (i, x) in xs_hi.iter().enumerate().rev() { + let y = (ys[i + 1] << WIDTH_M1) | (ys[i] >> 1); + cmp = x.cmp(&y); + if cmp != Equal { + break; + } + } + let mut y = ys[0] << WIDTH_M1; + for x in xs_lo.iter().rev() { + if cmp != Equal { + break; + } + cmp = x.cmp(&y); + y = 0; // ensure we consider ys[0] & 1 only once + } + if cmp == Equal && y != 0 { + cmp = Less; + } + } else { + let k = ys_len - xs_len; + let ys_hi = &ys[k..]; + for (i, x) in xs.iter().enumerate().rev() { + let y = (ys_hi[i + 1] << WIDTH_M1) | (ys_hi[i] >> 1); + cmp = x.cmp(&y); + if cmp != Equal { + break; + } + } + for i in (0..k).rev() { + if cmp != Equal { + break; + } + let y = (ys[i + 1] << WIDTH_M1) | (ys[i] >> 1); + cmp = if y != 0 { Less } else { Equal }; + } + if cmp == Equal && extra && ys[0].odd() { + cmp = Less; + } + } + } else { + let ys_len = ys.len(); + if xs_len >= ys_len { + let (xs_lo, xs_hi) = xs.split_at(xs_len - ys_len); + cmp = limbs_cmp_same_length(xs_hi, ys); + if cmp == Equal && !slice_test_zero(xs_lo) { + cmp = Greater; + } + } else { + let (ys_lo, ys_hi) = ys.split_at(ys_len - xs_len); + cmp = limbs_cmp_same_length(xs, ys_hi); + if cmp == Equal && !slice_test_zero(ys_lo) { + cmp = Less; + } + } + } + cmp +} + +// xs <- xs - ys >> extra - carry, with carry = 0 or 1. Return borrow out. +// +// This is mpfr_mpn_sub_aux from div.c, MPFR 4.2.0. +fn sub_helper(xs: &mut [Limb], ys: &[Limb], mut carry: bool, extra: bool) -> bool { + if extra { + for (i, x) in xs.iter_mut().enumerate() { + let y = (ys[i + 1] << WIDTH_M1) | (ys[i] >> 1); + let mut diff = x.wrapping_sub(y); + if carry { + diff.wrapping_sub_assign(1); + } + carry = *x < y || carry && diff == Limb::MAX; + *x = diff; + } + } else { + for (x, &y) in xs.iter_mut().zip(ys.iter()) { + let mut diff = x.wrapping_sub(y); + if carry { + diff.wrapping_sub_assign(1); + } + carry = *x < y || carry && diff == Limb::MAX; + *x = diff; + } + } + carry +} + +#[inline] +fn div_float_significands_general( + xs: &[Limb], + ys: &mut [Limb], + prec: u64, + rm: RoundingMode, +) -> (Vec, u64, Ordering) { + let mut out = vec![0; usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0)]; + let (exp_offset, o) = div_float_significands_general_to_out(&mut out, xs, ys, prec, rm); + (out, exp_offset, o) +} + +pub(crate) const MPFR_DIV_THRESHOLD: usize = 25; + +#[derive(Eq, PartialEq, Clone, Copy)] +pub(crate) enum Cleanup { + None, + TruncateCheckQHigh, + Sub1Ulp, + Sub2Ulp, +} + +// TODO special case qs == ds +// +// This is mpfr_div from div.c, MPFR 4.2.0, skipping over various special cases +fn div_float_significands_general_to_out( + qs: &mut [Limb], + ns: &[Limb], + ds: &mut [Limb], + prec: u64, + rm: RoundingMode, +) -> (u64, Ordering) { + let ns_len = ns.len(); + let ds_len = ds.len(); + let qs_len = usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0); + let qs = &mut qs[..qs_len]; + // Determine if an extra bit comes from the division, i.e. if the significand of X (as a + // fraction in [1/2, 1) ) is larger than that of Y + let ns_last = *ns.last().unwrap(); + let ds_last = *ds.last().unwrap(); + let extra_bit = if ns_last == ds_last { + // most significant limbs are equal, must look at further limbs + if let Some((n, d)) = ns.iter().rev().zip(ds.iter().rev()).find(|&(n, d)| n != d) { + n > d + } else if ns_len >= ds_len { + // no more divisor limb + true + } else { + // k = 0: no more dividend limb + slice_test_zero(&ds[..ds_len - ns_len]) + } + } else { + ns_last > ds_last + }; + let mut exp_offset = u64::from(extra_bit); + // shift is the number of zero bits in the low limb of the quotient + let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); + let mut shift_bit = Limb::power_of_2(shift); + let shift_mask = shift_bit - 1; + let mut ys_vec; + let mut ys: &mut [Limb]; + let mut inex; + // We first try Mulders' short division (for large operands) + if qs_len >= MPFR_DIV_THRESHOLD && ds_len >= MPFR_DIV_THRESHOLD { + // We will perform a short (2 * n) / n division + let n = qs_len + 1; + let two_n = n << 1; + // since Mulders' short division clobbers the dividend, we have to copy it + let mut xs = vec![0; two_n]; + if ns_len >= two_n { + // truncate the dividend + xs[..two_n].copy_from_slice(&ns[ns_len - two_n..]); + } else { + // zero-pad the dividend + xs[two_n - ns_len..].copy_from_slice(ns); + } + if ds_len >= n { + // truncate the divisor + ys = &mut ds[ds_len - n..]; + } else { + // zero-pad the divisor + ys_vec = vec![0; n]; + ys = &mut ys_vec; + ys[n - ds_len..].copy_from_slice(ds); + } + // since n = qs_len + 1, we have n >= 2 here + let mut scratch = vec![0; n + limbs_float_div_high_scratch_len(n)]; + let (qs_2, scratch) = scratch.split_at_mut(n); + let q_high = limbs_float_div_high(qs_2, &mut xs, &ys[..n], scratch); + // in all cases, the error is at most (2 * n + 2) ulps on q_high * B ^ n + {qs_2, n}. + let p = i32::exact_from( + i64::exact_from(n << Limb::LOG_WIDTH) + - i64::exact_from((two_n + 2).ceiling_log_base_2()), + ); + // If rm == Nearest, we need to be able to round with a directed rounding and one more bit. + if q_high { + let qs_2_lo = &mut qs_2[..n]; + limbs_slice_shr_in_place(qs_2_lo, 1); + *qs_2_lo.last_mut().unwrap() |= HIGH_BIT; + if round_helper_2(qs_2_lo, p, prec + u64::from(rm == Nearest)) { + // We can round correctly whatever the rounding mode + qs.copy_from_slice(&qs_2[1..=qs_len]); + qs[0] &= !shift_mask; // put to zero low `shift` bits + return if rm == Exact { + panic!("Inexact float division"); + } else if rm == Nearest { + // round to nearest + // + // We know we can round, thus we are never in the even rule case: + // - if the round bit is 0, we truncate + // - if the round bit is 1, we add 1 + let round_bit = if shift == 0 { + qs_2[0].get_highest_bit() + } else { + (qs_2[1] >> (shift - 1)).odd() + }; + if round_bit { + if limbs_slice_add_limb_in_place(qs, shift_bit) { + exp_offset += 1; + // else exponent is now incorrect, but one will still get an overflow + qs[qs_len - 1] = HIGH_BIT; + } + (exp_offset, Greater) + } else { + (exp_offset, Less) + } + } else if rm == Up || rm == Ceiling { + if limbs_slice_add_limb_in_place(qs, shift_bit) { + exp_offset += 1; + // else exponent is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } else { + (exp_offset, Less) + }; + } + } + } + // Mulders' short division failed: we revert to integer division + let mut qs_2_vec = vec![]; + let mut qs_2: &mut [Limb] = if rm == Nearest && shift == 0 { + // We compute the quotient with one more limb, in order to get the round bit in the + // quotient, and the remainder only contains sticky bits. Need to allocate memory for the + // quotient + qs_2_vec = vec![0; qs_len + 1]; + &mut qs_2_vec + } else { + qs // directly put the quotient in the destination + }; + let qs_2_len = qs_2.len(); + let two_qs_2_len = qs_2_len << 1; + // prepare the dividend + let mut xs = vec![0; two_qs_2_len]; + let mut sticky_x = false; + if two_qs_2_len > ns_len { + // use the full dividend + let (xs_lo, xs_hi) = xs.split_at_mut(two_qs_2_len - ns_len); + if extra_bit { + *xs_lo.last_mut().unwrap() = limbs_shr_to_out(xs_hi, ns, 1); + } else { + xs_hi.copy_from_slice(ns); + } + } else { + // truncate the dividend + let (ns_lo, ns_hi) = ns.split_at(ns_len - two_qs_2_len); + let ns_hi = &ns_hi[..two_qs_2_len]; + if extra_bit { + sticky_x = limbs_shr_to_out(&mut xs, ns_hi, 1) != 0; + } else { + xs.copy_from_slice(ns_hi); + } + sticky_x = sticky_x || !slice_test_zero(ns_lo); + } + let mut low_x = sticky_x; + let mut k; + // Now sticky_x is non-zero iff the truncated part of x is non-zero + let mut sticky_y = false; + // Prepare the divisor + k = if ds_len >= qs_2_len { + k = ds_len - qs_2_len; + sticky_y = sticky_y || !slice_test_zero(&ds[..k]); + ys = &mut ds[k..]; // avoid copying the divisor + 0 + } else { + // ds_len < qs_2_len: small divisor case + ys = ds; + qs_2_len - ds_len + }; + // Here we perform the real division of {xs + k, two_qs_2_len - k} by {ys, qs_2_len - k} In the + // general case (ns_len > 2 * qs_2_len and ds_len > qs_2_len), we have: + // ``` + // ______________________________________ + // | | | x1 has 2 * qs_2_len limbs + // | x1 | x0 | x0 has ns_len - 2 * qs_2_len limbs + // |__________________________|___________| + + // ____________________ + // | | | y1 has qs_2_len limbs + // | y1 | y0 | y0 has ds_len - qs_2_len limbs + // |___________|________| + // ``` + // + // We divide x1 by y1, with quotient in q_high + {qs_2, qs_2_len} and remainder (denoted r + // below) stored in place of the low qs_2_len limbs of x1. + // + // If Mulders' short division failed, we revert to division with remainder + let mut q_high = limbs_div_helper(qs_2, &mut xs[k..], &ys[..qs_2_len - k]); + // let x1 be the upper part of x, and y1 the upper part of y (with sticky_x and sticky_y + // representing the lower parts), then the quotient of x1 by y1 is now in {qs_2, qs_2_len}, with + // possible carry in q_high, and the remainder in {xs + k, qs_2_len - k}. + // + // Warning: q_high may be 1 if x1 == y1, but x < y. + k = qs_2_len; + sticky_x = sticky_x || !slice_test_zero(&xs[..k]); + let mut sticky_bit = Limb::from(sticky_x | sticky_y); + // now sticky_bit is non-zero iff one of the following holds: + // - the truncated part of u is non-zero + // - the truncated part of v is non-zero + // - the remainder from division is non-zero + let (mut sticky_3, shift_2) = if qs_2_len == qs_len { + // does nothing when shift = 0 + (qs_2[0] & shift_mask, shift) + } else { + // qs_2_len = qs_len + 1: only happens when rm == Nearest and shift = 0 + qs.copy_from_slice(&qs_2_vec[1..=qs_len]); + qs_2 = &mut qs_2_vec; + (qs_2[0], Limb::WIDTH) + }; + qs_2[0] ^= sticky_3; + // sticky_3 contains the truncated bits from the quotient, including the round bit, and 1 <= + // shift_2 <= WIDTH is the number of bits in sticky_3 + inex = if sticky_bit != 0 || sticky_3 != 0 { + Greater + } else { + Equal + }; + // to round, we distinguish two cases: + // - ds_len <= qs_2_len: we used the full divisor + // - ds_len > qs_2_len: the divisor was truncated + let mut round_bit = 0; + let mut cleanup = Cleanup::None; + if ds_len <= qs_2_len { + // use the full divisor + sticky_bit = if rm == Nearest { + round_bit = sticky_3 & Limb::power_of_2(shift_2 - 1); + (sticky_3 ^ round_bit) | Limb::from(sticky_x) + } else if rm == Floor || rm == Down || inex == Equal { + Limb::from(inex != Equal) + } else if rm == Exact { + panic!("Inexact float division"); + } else { + 1 + }; + } else { + // ds_len > qs_2_len: need to truncate the divisor + if inex == Equal { + return (exp_offset, Equal); + } + // We know the estimated quotient is an upper bound of the exact quotient (with rounding + // toward zero), with a difference of at most 2 in qs_2[0]. Thus we can round except when + // sticky_3 is 000...000 or 000...001 for directed rounding, and 100...000 or 100...001 for + // rounding to nearest. (For rounding to nearest, we cannot determine the inexact flag for + // 000...000 or 000...001.) + let sticky_3_orig = sticky_3; + if rm == Nearest { + round_bit = sticky_3 & Limb::power_of_2(shift_2 - 1); + sticky_3 ^= round_bit; + } + if sticky_3 > 1 { + sticky_bit = sticky_3; + } else { + // hard case: we have to compare q1 * v0 and r + u0, where q1 * v0 has qs_2_len + + // (ds_len-qs_2_len) = ds_len limbs, and r + u0 has qs_2_len + (usize-2*qs_2_len) = + // usize-qs_2_len limbs + let k = ds_len - qs_2_len; + // sp <- {qs_2, qs_2_len} * {ds, ds_len - qs_2_len} + let mut scratch = vec![0; ds_len + limbs_mul_to_out_scratch_len(qs_2_len, k)]; + let (sp, scratch) = scratch.split_at_mut(ds_len); + qs_2[0] ^= sticky_3_orig; // restore original quotient + let ds_lo = &ds[..k]; + limbs_mul_to_out(sp, qs_2, ds_lo, scratch); + let q_high_2 = if q_high { + limbs_slice_add_same_length_in_place_left(&mut sp[qs_2_len..], ds_lo) + } else { + false + }; + qs_2[0] ^= sticky_3_orig; + // restore truncated quotient + // + // Compare q_high_2 + {sp, ds_len} to {xs, qs_2_len} + u0 + let (sp_lo, sp_hi) = sp.split_at_mut(k); + let mut cmp_s_r = if q_high_2 { + Greater + } else { + limbs_cmp_same_length(sp_hi, &xs[..qs_2_len]) + }; + if cmp_s_r == Equal { + // compare {sp, k} and u0 + cmp_s_r = if ns_len >= two_qs_2_len { + cmp_helper( + sp_lo, + &ns[..ns_len - two_qs_2_len + usize::from(extra_bit)], + extra_bit, + ) + } else if slice_test_zero(sp_lo) { + Equal + } else { + Greater + }; + } + // now + // - cmp_s_r > 0 if {sp, ds_len} > {xs, qs_2_len} + u0 + // - cmp_s_r = 0 if {sp, ds_len} = {xs, qs_2_len} + u0 + // - cmp_s_r < 0 if {sp, ds_len} < {xs, qs_2_len} + u0 + if cmp_s_r <= Equal { + // quotient is in [q1, q1+1) + sticky_bit = if cmp_s_r == Equal { sticky_3 } else { 1 }; + } else { + // cmp_s_r > 0, quotient is < q1: to determine if it is in [q1 - 2, q1 - 1] or in + // [q1 - 1, q1], we need to subtract the low part u0 of the dividend from q*v0 + let mut carry = false; + // subtract u0 >> extra_bit if non-zero + if q_high_2 { + // whatever the value of {ns, m + k}, it will be smaller than q_high_2 + {sp, k} + cmp_s_r = Greater; + } else { + if low_x { + let l = ns_len - two_qs_2_len; // number of limbs in u0 + let m = l.saturating_sub(k); + carry = extra_bit && ns[m].odd(); + if l >= k { + // u0 has at least as many limbs than s: first look if {ns, m} is not + // zero, and compare {sp, k} and {ns + m, k} + if !carry { + carry = !slice_test_zero(&ns[..m]); + } + low_x = carry; + carry = sub_helper( + sp_lo, + &ns[m..m + k + usize::from(extra_bit)], + carry, + extra_bit, + ); + } else { + // l < k: s has more limbs than u0 + low_x = false; + let kml = k - l; + if carry { + carry = limbs_sub_limb_in_place(&mut sp_lo[kml - 1..kml], HIGH_BIT); + } + carry = sub_helper( + &mut sp_lo[kml..], + &ns[..l + usize::from(extra_bit)], + carry, + extra_bit, + ); + } + } + if carry { + limbs_sub_limb_in_place(sp_hi, 1); + } + // subtract r + limbs_sub_same_length_in_place_left(sp_hi, &xs[..qs_2_len]); + // now compare {sp, ds_len} to y + cmp_s_r = limbs_cmp_same_length(sp, ds); + if cmp_s_r == Equal && low_x { + cmp_s_r = Greater; + // since in fact we subtracted less than 1 + } + } + if cmp_s_r <= Equal { + // q1 - 1 <= x / y < q1 + if sticky_3 == 1 { + // q1 - 1 is either representable (directed rounding), or the middle of two + // numbers (nearest) + sticky_bit = Limb::from(cmp_s_r != Equal); + } else if round_bit == 0 { + // round_bit=0, sticky_3=0: q1 - 1 is exact only when sh=0 + inex = if cmp_s_r != Equal || shift != 0 { + Less + } else { + Equal + }; + cleanup = if rm == Nearest || ((rm == Ceiling || rm == Up) && inex != Equal) + { + inex = Greater; + Cleanup::TruncateCheckQHigh + } else if inex != Equal && rm == Exact { + panic!("Inexact float division"); + } else { + Cleanup::Sub1Ulp + }; + } else { + // sticky_3 = 0, round_bit = 1 ==> rounding to nearest + return (exp_offset, cmp_s_r); + } + } else { + // q1 - 2 < x / y < q1 - 1 + // + // if rm == Nearest, the result is q1 when q1 - 2 >= q1 - 2 ^ (shift - 1), i.e. + // shift >= 2, otherwise (shift = 1) it is q1 - 2 + (inex, cleanup) = if rm == Exact { + panic!("Inexact float division"); + } else if rm == Nearest { + // shift > 0 + // + // Case shift = 1: sticky_bit = 0 always, and q1 - round_bit is exactly + // representable, like q1 - round_bit - 2. + // ``` + // round_bit action + // 0 subtract two ulps, inex = Less + // 1 truncate, inex = Greater + // ``` + // + // Case shift > 1: one ulp is 2 ^ (shift - 1) >= 2 + // ``` + // round_bit sticky_bit action + // 0 0 truncate, inex = Greater + // 0 1 truncate, inex = Greater + // 1 x truncate, inex = Less + // ``` + if shift == 1 { + if round_bit == 0 { + shift_bit = 1; + (Less, Cleanup::Sub2Ulp) + } else { + (Greater, Cleanup::TruncateCheckQHigh) + } + } else { + ( + if round_bit == 0 { Greater } else { Less }, + Cleanup::TruncateCheckQHigh, + ) + } + } else if rm == Floor || rm == Down { + // The result is down(q1 - 2), i.e. subtract one ulp if shift > 0, and two + // ulps if shift = 0 + ( + Less, + if shift == 0 { + Cleanup::Sub2Ulp + } else { + Cleanup::Sub1Ulp + }, + ) + } else { + ( + Greater, + if shift == 0 { + Cleanup::Sub1Ulp + } else { + Cleanup::TruncateCheckQHigh + }, + ) + }; + } + } + } + } + match cleanup { + Cleanup::None => { + // quotient is in [q1, q1 + 1), round_bit is the round_bit (0 for directed rounding) + return if rm == Floor || rm == Down || round_bit == 0 && sticky_bit == 0 { + ( + exp_offset, + if round_bit == 0 && sticky_bit == 0 { + Equal + } else { + Less + }, + ) + } else if rm == Exact { + panic!("Inexact float division"); + } else if rm == Nearest { + // sticky_bit != 0 or round != 0 + if round_bit == 0 { + // necessarily sticky_bit != 0 + (exp_offset, Less) + } else if sticky_bit != 0 { + if limbs_slice_add_limb_in_place(qs, shift_bit) { + exp_offset += 1; + // else qexp is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } else { + // round_bit = 1, sticky_bit = 0 + if qs[0] & shift_bit == 0 { + (exp_offset, Less) + } else { + if limbs_slice_add_limb_in_place(qs, shift_bit) { + exp_offset += 1; + // else qexp is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } + } + } else { + // round away from zero, sticky_bit != 0 + if limbs_slice_add_limb_in_place(qs, shift_bit) { + exp_offset += 1; + // else qexp is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + }; + } + Cleanup::Sub1Ulp => { + // we cannot subtract 1 << (shift + 1), since this is undefined for shift = WIDTH + if limbs_sub_limb_in_place(qs, shift_bit) { + q_high = false; + } + } + Cleanup::Sub2Ulp => { + if limbs_sub_limb_in_place(qs, shift_bit) { + q_high = false; + } + if limbs_sub_limb_in_place(qs, shift_bit) { + q_high = false; + } + } + _ => {} + } + if q_high { + exp_offset += 1; + // else qexp is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, inex) +} diff --git a/malachite-nz/src/natural/arithmetic/float_extras.rs b/malachite-nz/src/natural/arithmetic/float_extras.rs index 78c6e5182..30de3dacc 100644 --- a/malachite-nz/src/natural/arithmetic/float_extras.rs +++ b/malachite-nz/src/natural/arithmetic/float_extras.rs @@ -22,6 +22,7 @@ use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::LowMask; use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_base::slices::slice_test_zero; // This is MPFR_CAN_ROUND from mpfr-impl.h, MPFR 4.2.0. pub fn float_can_round(x: &Natural, err0: u64, prec: u64, rm: RoundingMode) -> bool { @@ -249,3 +250,59 @@ fn round_helper (i8, bool)>( } } } + +// Assuming xs is an approximation of a non-singular number with error at most equal to 2 ^ (EXP(x) +// - err0) (`err0` bits of x are known) of direction unknown, check if we can round x toward zero +// with precision prec. +// +// This is mpfr_round_p from round_p.c, MPFR 4.2.0. +pub(crate) fn round_helper_2(xs: &[Limb], err0: i32, prec: u64) -> bool { + let len = xs.len(); + assert!(xs.last().unwrap().get_highest_bit()); + let mut err = u64::exact_from(len << Limb::LOG_WIDTH); + if err0 <= 0 { + return false; + } + let err0 = u64::from(err0.unsigned_abs()); + if err0 <= prec || prec >= err { + return false; + } + err = min(err, err0); + let k = usize::exact_from(prec >> Limb::LOG_WIDTH); + let n = usize::exact_from(err >> Limb::LOG_WIDTH) - k; + assert!(len > k); + // Check first limb + let xs = &xs[len - k - n - 1..]; + let (xs_last, xs_init) = xs[..=n].split_last().unwrap(); + let mut tmp = *xs_last; + let mask = Limb::MAX >> (prec & Limb::WIDTH_MASK); + tmp &= mask; + if n == 0 { + // prec and error are in the same limb + let s = Limb::WIDTH - (err & Limb::WIDTH_MASK); + assert!(s < Limb::WIDTH); + tmp >>= s; + tmp != 0 && tmp != mask >> s + } else if tmp == 0 { + let (xs_head, xs_tail) = xs_init.split_first().unwrap(); + // Check if all (n - 1) limbs are 0 + if !slice_test_zero(xs_tail) { + return true; + } + // Check if final error limb is 0 + let s = Limb::WIDTH - (err & Limb::WIDTH_MASK); + s != Limb::WIDTH && *xs_head >> s != 0 + } else if tmp == mask { + let (xs_head, xs_tail) = xs_init.split_first().unwrap(); + // Check if all (n - 1) limbs are 11111111111111111 + if xs_tail.iter().any(|&x| x != Limb::MAX) { + return true; + } + // Check if final error limb is 0 + let s = Limb::WIDTH - (err & Limb::WIDTH_MASK); + s != Limb::WIDTH && *xs_head >> s != Limb::MAX >> s + } else { + // First limb is different from 000000 or 1111111 + true + } +} diff --git a/malachite-nz/src/natural/arithmetic/float_mul.rs b/malachite-nz/src/natural/arithmetic/float_mul.rs index a2482d437..195950f29 100644 --- a/malachite-nz/src/natural/arithmetic/float_mul.rs +++ b/malachite-nz/src/natural/arithmetic/float_mul.rs @@ -634,7 +634,7 @@ fn limbs_float_mul_high_same_length_basecase(out: &mut [Limb], xs: &[Limb], ys: } } -fn limbs_float_mul_high_same_length_scratch_len(len: usize) -> usize { +pub(crate) fn limbs_float_mul_high_same_length_scratch_len(len: usize) -> usize { if len > MUL_FFT_THRESHOLD { limbs_mul_same_length_to_out_scratch_len(len) } else { diff --git a/malachite-nz/src/natural/arithmetic/float_reciprocal.rs b/malachite-nz/src/natural/arithmetic/float_reciprocal.rs new file mode 100644 index 000000000..554ee7ed8 --- /dev/null +++ b/malachite-nz/src/natural/arithmetic/float_reciprocal.rs @@ -0,0 +1,885 @@ +// Copyright © 2024 Mikhail Hogrefe +// +// Uses code adopted from the GNU MPFR Library. +// +// Copyright © 1999-2024 Free Software Foundation, Inc. +// +// Contributed by the AriC and Caramba projects, INRIA. +// +// Uses code adopted from the GNU MP Library. +// +// Copyright © 1991-2018 Free Software Foundation, Inc. +// +// 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 crate::malachite_base::num::basic::integers::PrimitiveInt; +use crate::malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; +use crate::natural::arithmetic::add::{ + limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, +}; +use crate::natural::arithmetic::div_mod::{div_mod_by_preinversion, limbs_invert_limb}; +use crate::natural::arithmetic::float_div::{ + limbs_div_helper, limbs_float_div_high, limbs_float_div_high_scratch_len, Cleanup, + MPFR_DIV_THRESHOLD, +}; +use crate::natural::arithmetic::mul::{limbs_mul_to_out, limbs_mul_to_out_scratch_len}; +use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; +use crate::natural::arithmetic::sub::{ + limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, +}; +use crate::natural::comparison::cmp::limbs_cmp_same_length; +use crate::natural::InnerNatural::{Large, Small}; +use crate::natural::Natural; +use crate::platform::{DoubleLimb, Limb}; +use alloc::vec::Vec; +use core::cmp::Ordering::{self, *}; +use malachite_base::fail_on_untested_path; +use malachite_base::num::arithmetic::traits::{ + NegModPowerOf2, OverflowingAddAssign, OverflowingNegAssign, Parity, PowerOf2, ShrRound, + WrappingAddAssign, WrappingNegAssign, WrappingSubAssign, XMulYToZZ, XXSubYYToZZ, +}; +use malachite_base::rounding_modes::RoundingMode::{self, *}; +use malachite_base::slices::slice_test_zero; + +const WIDTH_M1: u64 = Limb::WIDTH - 1; +const HIGH_BIT: Limb = 1 << WIDTH_M1; +const TWICE_WIDTH: u64 = Limb::WIDTH * 2; + +// This is mpfr_div from div.c, MPFR 4.3.0, specialized for reciprocation. +pub fn reciprocal_float_significand_in_place( + x: &mut Natural, + x_prec: u64, + out_prec: u64, + rm: RoundingMode, +) -> (u64, Ordering) { + if out_prec == x_prec { + if let Some((increment_exp, o)) = + reciprocal_float_significand_in_place_same_prec(x, out_prec, rm) + { + return (u64::from(increment_exp), o); + } + } + match &mut *x { + Natural(Small(small_x)) => { + let (qs, exp_offset, o) = reciprocal_float_significand_short(*small_x, out_prec, rm); + *x = Natural::from_owned_limbs_asc(qs); + (exp_offset, o) + } + Natural(Large(xs)) => { + let (out, exp_offset, o) = reciprocal_float_significand_general(xs, out_prec, rm); + *x = Natural::from_owned_limbs_asc(out); + (exp_offset, o) + } + } +} + +// This is mpfr_div from div.c, MPFR 4.3.0, specialized for reciprocation. +pub fn reciprocal_float_significand_ref( + x: &Natural, + x_prec: u64, + out_prec: u64, + rm: RoundingMode, +) -> (Natural, u64, Ordering) { + if out_prec == x_prec { + if let Some((reciprocal, increment_exp, o)) = + reciprocal_float_significand_same_prec_ref(x, out_prec, rm) + { + return (reciprocal, u64::from(increment_exp), o); + } + } + match x { + Natural(Small(small_x)) => { + let (qs, exp_offset, o) = reciprocal_float_significand_short(*small_x, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + Natural(Large(xs)) => { + let mut xs = xs.clone(); + let (qs, exp_offset, o) = reciprocal_float_significand_general(&mut xs, out_prec, rm); + (Natural::from_owned_limbs_asc(qs), exp_offset, o) + } + } +} + +fn reciprocal_float_significand_in_place_same_prec( + x: &mut Natural, + prec: u64, + rm: RoundingMode, +) -> Option<(bool, Ordering)> { + match x { + Natural(Small(x)) => { + let (reciprocal, increment_exp, o) = if prec == Limb::WIDTH { + reciprocal_float_significand_same_prec_w(*x, rm) + } else { + reciprocal_float_significand_same_prec_lt_w(*x, prec, rm) + }; + *x = reciprocal; + Some((increment_exp, o)) + } + Natural(Large(xs)) => match xs.as_mut_slice() { + [x_0, x_1] if prec != TWICE_WIDTH => { + let (reciprocal_0, reciprocal_1, increment_exp, o) = + reciprocal_float_significand_same_prec_gt_w_lt_2w(*x_0, *x_1, prec, rm); + *x_0 = reciprocal_0; + *x_1 = reciprocal_1; + Some((increment_exp, o)) + } + _ => None, + }, + } +} + +fn reciprocal_float_significand_same_prec_ref( + x: &Natural, + prec: u64, + rm: RoundingMode, +) -> Option<(Natural, bool, Ordering)> { + match x { + Natural(Small(x)) => { + let (reciprocal, increment_exp, o) = if prec == Limb::WIDTH { + reciprocal_float_significand_same_prec_w(*x, rm) + } else { + reciprocal_float_significand_same_prec_lt_w(*x, prec, rm) + }; + Some((Natural(Small(reciprocal)), increment_exp, o)) + } + Natural(Large(xs)) => match xs.as_slice() { + [x_0, x_1] if prec != TWICE_WIDTH => { + let (reciprocal_0, reciprocal_1, increment_exp, o) = + reciprocal_float_significand_same_prec_gt_w_lt_2w(*x_0, *x_1, prec, rm); + Some(( + Natural(Large(vec![reciprocal_0, reciprocal_1])), + increment_exp, + o, + )) + } + _ => None, + }, + } +} + +// x cannot be equal to `2 ^ (WIDTH - 1)`. +// +// This is mpfr_div_1 from mul.c, MPFR 4.3.0, specialized for reciprocation. +fn reciprocal_float_significand_same_prec_lt_w( + x: Limb, + prec: u64, + rm: RoundingMode, +) -> (Limb, bool, Ordering) { + let shift = Limb::WIDTH - prec; + let shift_bit = Limb::power_of_2(shift); + let half_shift_bit = shift_bit >> 1; + let mask = shift_bit - 1; + // First try with an approximate reciprocal. + let q = HIGH_BIT | (limbs_invert_limb(x) >> 1); + // round_bit does not exceed the true reciprocal floor(HIGH_BIT * 2 ^ WIDTH / x), with error at + // most 2, which means the rational reciprocal q satisfies round_bit <= q < round_bit + 3. We + // can round correctly except when the last shift - 1 bits of q0 are 000..000 or 111..111 or + // 111..110. + let (round_bit, sticky_bit) = if (q + 2) & (mask >> 1) > 2 { + // result cannot be exact in this case + (q & half_shift_bit, 1) + } else { + let (mut hi, mut lo) = Limb::x_mul_y_to_zz(q, x); + assert!(hi < HIGH_BIT || (hi == HIGH_BIT && lo == 0)); + // subtract {hi, lo} from {HIGH_BIT, 0} + (hi, lo) = Limb::xx_sub_yy_to_zz(HIGH_BIT, 0, hi, lo); + assert!(hi == 0 && lo < x); + (q & half_shift_bit, lo | (q & (mask >> 1))) + }; + let reciprocal = (HIGH_BIT | q) & !mask; + match rm { + Exact => panic!("Inexact float reciprocation"), + Nearest => { + if round_bit == 0 || sticky_bit == 0 && reciprocal & shift_bit == 0 { + (reciprocal, false, Less) + } else { + (reciprocal.wrapping_add(shift_bit), false, Greater) + } + } + Floor | Down => (reciprocal, false, Less), + Ceiling | Up => (reciprocal.wrapping_add(shift_bit), false, Greater), + } +} + +// x cannot be equal to `2 ^ (WIDTH - 1)`. +fn reciprocal_float_significand_same_prec_w(x: Limb, rm: RoundingMode) -> (Limb, bool, Ordering) { + // First compute an approximate reciprocal. + let q = HIGH_BIT | (limbs_invert_limb(x) >> 1); + // round_bit does not exceed the true reciprocal floor(2 ^ WIDTH / x), with error at most 2, + // which means the rational reciprocal q satisfies round_bit <= q < round_bit + 3, thus the true + // reciprocal is round_bit, round_bit + 1 or round_bit + 2. + let (mut hi, mut lo) = Limb::x_mul_y_to_zz(q, x); + assert!(hi < HIGH_BIT || (hi == HIGH_BIT && lo == 0)); + // subtract {hi, lo} from {HIGH_BIT, 0} + (hi, lo) = Limb::xx_sub_yy_to_zz(HIGH_BIT, 0, hi, lo); + assert!(hi == 0 && lo < x); + // now (HIGH_BIT - extra * x) * 2 ^ WIDTH = q * x + lo with 0 <= lo < x + // + // If !increment_exp, the reciprocal is q0, the round bit is 1 if l >= x0 / 2, and sticky_bit + // are the remaining bits from l. If increment_exp, the reciprocal is HIGH_BIT + (q >> 1), the + // round bit is the least significant bit of q, and sticky_bit is lo. + // + // If "2 * lo < lo", then there is a carry in 2 * lo, thus 2 * lo > x. Otherwise if there is no + // carry, we check whether 2 * lo >= y0. + let two_lo = lo << 1; + let round_bit = (two_lo < lo) || (two_lo >= x); + let mut reciprocal = q; + let sticky_bit = if round_bit { + two_lo.wrapping_sub(x) + } else { + lo + }; + match rm { + Exact => panic!("Inexact float reciprocation"), + Nearest => { + if !round_bit || sticky_bit == 0 && reciprocal.even() { + (reciprocal, false, Less) + } else { + reciprocal.wrapping_add_assign(1); + (reciprocal, false, Greater) + } + } + Floor | Down => (reciprocal, false, Less), + Ceiling | Up => { + reciprocal.wrapping_add_assign(1); + (reciprocal, false, Greater) + } + } +} + +// Given (B << WIDTH) < x = x_1 * B + x_0 with x normalized (high bit of x_1 set), put in q = Q1 +// * B + Q0 an approximation of floor(B ^ 2 / x), with: B = 2 ^ WIDTH and q <= floor(B ^ 2 / +// x) <= q + 21. +// +// This is mpfr_div2_approx from div.c, MPFR 4.3.0, where Q0 and Q1 are returned, specialized for +// reciprocation. +fn reciprocal_float_2_approx(x_1: Limb, x_0: Limb) -> (Limb, Limb) { + // First compute an approximation of q_1, using a lower approximation of B ^ 2 / (x_1 + 1) - B + let inv = if x_1 == Limb::MAX { + 0 + } else { + limbs_invert_limb(x_1 + 1) + }; + // Now inv <= B ^ 2 / (x_1 + 1) - B. + let mut q_1 = HIGH_BIT | (inv >> 1); + // Now q_1 <= x_1 * B / (x_1 + 1) < (x_1 * B + x_0) * B / (x_1 * B + x_0). + // + // Compute q_1 * (x_1 * B + x_0) into r_1 : r_0 : xx and subtract from u_1 : x_0 : 0. + let (mut r_1, mut r_0) = Limb::x_mul_y_to_zz(q_1, x_1); + let (xx, yy) = Limb::x_mul_y_to_zz(q_1, x_0); + if r_0.overflowing_add_assign(xx) { + r_1.wrapping_add_assign(1); + } + // We ignore yy below, but first increment r_0, to ensure we get a lower approximation of the + // remainder. + if yy != 0 { + r_0.wrapping_add_assign(1); + } + if r_0 == 0 && yy != 0 { + r_1.wrapping_add_assign(1); + } + r_1 = HIGH_BIT.wrapping_sub(r_1); + let carry; + (r_0, carry) = r_0.overflowing_neg(); + if carry { + r_1.wrapping_sub_assign(1); + } + // r_1 : r_0 should be non-negative. + assert!(!r_1.get_highest_bit()); + // The second reciprocal limb is approximated by (r_1 * B ^ 2 + r_0 * B) / x_1, and since (B + + // inv) / B approximates B / x_1, this is in turn approximated by (r * B + r_0) * (B + inv) / B + // = r_1 * B * r_1 * inv + r_0 + (r0 * inv / B). + q_1.wrapping_add_assign(r_1); + // Add floor(r_0 * inv / B) to q_0. + if r_0.overflowing_add_assign(Limb::wrapping_from( + (DoubleLimb::from(r_0) * DoubleLimb::from(inv)) >> Limb::WIDTH, + )) { + q_1.wrapping_add_assign(1); + } + assert!(r_1 <= 4); + for _ in 0..r_1 { + if r_0.overflowing_add_assign(inv) { + q_1.wrapping_add_assign(1); + } + } + (q_1, r_0) +} + +// [x_0, x_1] cannot be equal to `2 ^ (2 * WIDTH - 1)`. +// +// This is mpfr_div_2 from div.c, MPFR 4.3.0, where Q0 and Q1 are returned, specialized for +// reciprocation. +fn reciprocal_float_significand_same_prec_gt_w_lt_2w( + x_0: Limb, + x_1: Limb, + prec: u64, + rm: RoundingMode, +) -> (Limb, Limb, bool, Ordering) { + let shift = TWICE_WIDTH - prec; + let shift_bit = Limb::power_of_2(shift); + let mask = shift_bit - 1; + assert!(HIGH_BIT < x_1 || (HIGH_BIT == x_1 && x_0 != 0)); + let (mut q_1, mut q_0) = reciprocal_float_2_approx(x_1, x_0); + // We know q1 * B + q0 is smaller or equal to the exact reciprocal, with difference at most 21. + let mut sticky_bit = if (q_0.wrapping_add(21)) & (mask >> 1) > 21 { + // The result is not exact when we can round with an approximation. + 1 + } else { + // We know q_1 : q_0 is a good-enough approximation, so use it! + // + // Since we know the difference should be at most 21 * (x_1 : x_0) after the subtraction + // below, thus at most 21 * 2 ^ 128, it suffices to compute the lower 3 limbs of (q_1 : q_0) + // * (x_1 : x_0). + let (mut s_1, mut s_0) = Limb::x_mul_y_to_zz(q_0, x_0); + let (mut s_2, mut lo) = Limb::x_mul_y_to_zz(q_0, x_1); + if s_1.overflowing_add_assign(lo) { + s_2.wrapping_add_assign(1); + } + let hi; + (hi, lo) = Limb::x_mul_y_to_zz(q_1, x_0); + s_2.wrapping_add_assign(hi); + if s_1.overflowing_add_assign(lo) { + s_2.wrapping_add_assign(1); + } + s_2.wrapping_add_assign(q_1.wrapping_mul(x_1)); + // Subtract s_2 : s_1 : s_0 from 0 : 0 : 0, with result in s_2 : s_1 : s_0. + s_2.wrapping_neg_assign(); + // Now negate s_1 : s_0. + s_1.wrapping_neg_assign(); + if s_0.overflowing_neg_assign() { + s_1.wrapping_sub_assign(1); + } + // There is a borrow in s_2 when s_0 and s_1 are not both zero. + if s_1 != 0 || s_0 != 0 { + s_2.wrapping_sub_assign(1); + } + while s_2 > 0 || s_1 > x_1 || s_1 == x_1 && s_0 >= x_0 { + // Add 1 to q_1 : q_0. + if q_0.overflowing_add_assign(1) { + q_1.wrapping_add_assign(1); + } + // Subtract x_1 : x_0 to s_2 : s_1 : s_0 + if s_1 < x_1 || s_1 == x_1 && s_0 < x_0 { + s_2.wrapping_sub_assign(1); + } + (s_1, s_0) = Limb::xx_sub_yy_to_zz(s_1, s_0, x_1, x_0); + } + s_1 | s_0 + }; + let round_bit = q_0 & (shift_bit >> 1); + sticky_bit |= (q_0 & mask) ^ round_bit; + let mut z_1 = q_1; + let mut z_0 = q_0 & !mask; + match rm { + Exact => panic!("Inexact float reciprocation"), + Nearest => { + if round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0 { + (z_0, z_1, false, Less) + } else if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { + (z_0, HIGH_BIT, false, Greater) + } else { + (z_0, z_1, false, Greater) + } + } + Floor | Down => (z_0, z_1, false, Less), + Ceiling | Up => { + if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { + (z_0, HIGH_BIT, false, Greater) + } else { + (z_0, z_1, false, Greater) + } + } + } +} + +// This is mpfr_div_ui from div_ui.c, MPFR 4.3.0, specialized for reciprocation. +fn reciprocal_float_significand_short( + y: Limb, + prec: u64, + rm: RoundingMode, +) -> (Vec, u64, Ordering) { + let out_len = usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0); + let mut out = vec![0; out_len + 1]; + let (exp_offset, o) = reciprocal_float_significand_short_to_out(&mut out, y, prec, rm); + out.truncate(out_len); + (out, exp_offset, o) +} + +fn limbs_reciprocal_limb_to_out_mod_with_fraction( + out: &mut [Limb], + fraction_len: usize, + d: Limb, +) -> Limb { + assert_ne!(d, 0); + let len = fraction_len.checked_add(1).unwrap(); + assert_ne!(len, 0); + let out = &mut out[..len]; + assert!(d.get_highest_bit()); + let (out_last, out_init) = out.split_last_mut().unwrap(); + *out_last = 0; + // Multiply-by-inverse, divisor already normalized. + let d_inv = limbs_invert_limb(d); + let mut r = HIGH_BIT; + for out_q in out_init[..fraction_len].iter_mut().rev() { + (*out_q, r) = div_mod_by_preinversion(r, 0, d, d_inv); + } + r +} + +// y cannot be a power of 2. +// +// This is mpfr_div_ui from div_ui.c, MPFR 4.3.0, specialized for reciprocation. +fn reciprocal_float_significand_short_to_out( + out: &mut [Limb], + y: Limb, + prec: u64, + rm: RoundingMode, +) -> (u64, Ordering) { + let diff = out.len().abs_diff(1); + // We need to store out_len + 1 = 1 + diff limbs of the reciprocal. used the entire dividend + // + // X = ({scratch, 1 + diff} * y + c) * B ^ (-diff} = ({scratch, out_len + 1} * y + c) * B ^ + // (-dif) + let c = limbs_reciprocal_limb_to_out_mod_with_fraction(out, diff, y); + // Let r = {xp, -diff} / B ^ (-diff) if diff < 0, r = 0 otherwise; 0 <= r < 1. + // + // Then X = ({scratch, out_len + 1} * y + c + r) * B ^ (-dif). x / y = (X / y) * B ^ (-1) * 2 ^ + // exp = ({scratch, out_len + 1} + (c + r) / y) * B ^ (-(out_len + 1)) * 2 ^ exp where 0 <= (c + + // r) / y < 1. + // + // sticky_bit != 0 iff r != 0 + // + // If the highest limb of the result is 0 (xs[0] < y), remove it. Otherwise, compute the left + // shift to be performed to normalize. In the latter case, we discard some low bits computed. + // They contain information useful for the rounding, hence the updating of middle and inexact. + let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); + let shift_bit = Limb::power_of_2(shift); + let shift_mask = shift_bit - 1; + let out_head = out[0]; + // round bit is 1 iff (c + r) / u >= 1/2 + let (mut exp_offset, round_bit, sticky_bit) = if shift == 0 { + // In this case scratch[out_len] = 0 and shift = 0, the round bit is not in {scratch, + // out_len + 1}. It is 1 iff 2 * (c + r) - y >= 0. This means that in some cases, we should + // look at the most significant bit of r. + if c >= y - c { + // i.e. 2 * c >= y: round bit is always 1 + // + // The sticky bit is 1 unless 2 * c - y = 0 and r = 0. + (0, 1, (c << 1).wrapping_sub(y)) + } else { + // 2 * c < y + // + // The round bit is 1 iff r >= 1 / 2 and 2 * (c + 1 / 2) = y. + // + // If round_bit is set, we need to recompute sticky_bit, since it might have taken into + // account the most-significant bit of xs[-diff - 1]. + (0, 0, c) + } + } else { + // round bit is in scratch[0] + ( + 0, + out_head & (shift_bit >> 1), + (out_head & (shift_mask >> 1)) | c, + ) + }; + // Clear the lowest `shift` bits + out[0] &= !shift_mask; + let (_, out) = out.split_last_mut().unwrap(); + match rm { + Exact => panic!("Inexact float reciprocation"), + Nearest => { + if round_bit == 0 || sticky_bit == 0 && out[0] & shift_bit == 0 { + (exp_offset, Less) + } else { + if limbs_slice_add_limb_in_place(out, shift_bit) { + exp_offset += 1; + *out.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } + } + Floor | Down => (exp_offset, Less), + Ceiling | Up => { + if limbs_slice_add_limb_in_place(out, shift_bit) { + exp_offset += 1; + *out.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } + } +} + +#[inline] +fn reciprocal_float_significand_general( + ys: &mut [Limb], + prec: u64, + rm: RoundingMode, +) -> (Vec, u64, Ordering) { + let mut out = vec![0; usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0)]; + let (exp_offset, o) = reciprocal_float_significand_general_to_out(&mut out, ys, prec, rm); + (out, exp_offset, o) +} + +// TODO special case qs == ds +// +// This is mpfr_div from div.c, MPFR 4.2.0, skipping over various special cases, specialized for +// reciprocation. +fn reciprocal_float_significand_general_to_out( + qs: &mut [Limb], + ds: &mut [Limb], + prec: u64, + rm: RoundingMode, +) -> (u64, Ordering) { + let ds_len = ds.len(); + let qs_len = usize::exact_from(prec.shr_round(Limb::LOG_WIDTH, Ceiling).0); + let qs = &mut qs[..qs_len]; + // Determine if an extra bit comes from the division, i.e. if the significand of X (as a + // fraction in [1/2, 1) ) is larger than that of Y + let ds_last = *ds.last().unwrap(); + let extra_bit = if ds_last == HIGH_BIT { + // k = 0: no more dividend limb + slice_test_zero(&ds[..ds_len - 1]) + } else { + HIGH_BIT > ds_last + }; + let mut exp_offset = u64::from(extra_bit); + // shift is the number of zero bits in the low limb of the reciprocal + let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); + let mut shift_bit = Limb::power_of_2(shift); + let shift_mask = shift_bit - 1; + let mut ys_vec; + let mut ys: &mut [Limb]; + // We first try Mulders' short division (for large operands) + if qs_len >= MPFR_DIV_THRESHOLD && ds_len >= MPFR_DIV_THRESHOLD { + // We will perform a short (2 * n) / n division + let n = qs_len + 1; + let two_n = n << 1; + // since Mulders' short division clobbers the dividend, we have to copy it + let mut xs = vec![0; two_n]; + // zero-pad the dividend + *xs.last_mut().unwrap() = HIGH_BIT; + if ds_len >= n { + // truncate the divisor + ys = &mut ds[ds_len - n..]; + } else { + // zero-pad the divisor + ys_vec = vec![0; n]; + ys = &mut ys_vec; + ys[n - ds_len..].copy_from_slice(ds); + } + // Since n = qs_len + 1, we have n >= 2 here. + let mut scratch = vec![0; n + limbs_float_div_high_scratch_len(n)]; + let (qs_2, scratch) = scratch.split_at_mut(n); + let q_high = limbs_float_div_high(qs_2, &mut xs, &ys[..n], scratch); + // In all cases, the error is at most (2 * n + 2) ulps on q_high * B ^ n + {qs_2, n}. + // + // If rm == Nearest, we need to be able to round with a directed rounding and one more bit. + if q_high { + let qs_2_lo = &mut qs_2[..n]; + limbs_slice_shr_in_place(qs_2_lo, 1); + *qs_2_lo.last_mut().unwrap() |= HIGH_BIT; + // round_helper_2 would always return false, so no need to call it + } + } + // Mulders' short division failed: we revert to integer division + let mut qs_2_vec = vec![]; + let mut qs_2: &mut [Limb] = if rm == Nearest && shift == 0 { + // We compute the reciprocal with one more limb, in order to get the round bit in the + // reciprocal, and the remainder only contains sticky bits. Need to allocate memory for the + // reciprocal + qs_2_vec = vec![0; qs_len + 1]; + &mut qs_2_vec + } else { + qs // directly put the reciprocal in the destination + }; + let qs_2_len = qs_2.len(); + let two_qs_2_len = qs_2_len << 1; + // prepare the dividend + let mut xs = vec![0; two_qs_2_len]; + // use the full dividend + xs[two_qs_2_len - 1] = if extra_bit { HIGH_BIT >> 1 } else { HIGH_BIT }; + // Prepare the divisor + let (mut k, sticky_y) = if ds_len >= qs_2_len { + let k = ds_len - qs_2_len; + let sy = !slice_test_zero(&ds[..k]); + ys = &mut ds[k..]; // avoid copying the divisor + (0, sy) + } else { + // ds_len < qs_2_len: small divisor case + ys = ds; + (qs_2_len - ds_len, false) + }; + // If Mulders' short division failed, we revert to division with remainder. + let mut q_high = limbs_div_helper(qs_2, &mut xs[k..], &ys[..qs_2_len - k]); + k = qs_2_len; + let sticky_x = !slice_test_zero(&xs[..k]); + let mut sticky_bit = Limb::from(sticky_x | sticky_y); + // now sticky_bit is non-zero iff one of the following holds: + // - the truncated part of u is non-zero + // - the truncated part of v is non-zero + // - the remainder from division is non-zero + let (mut sticky_3, shift_2) = if qs_2_len == qs_len { + // does nothing when shift = 0 + (qs_2[0] & shift_mask, shift) + } else { + // qs_2_len = qs_len + 1: only happens when rm == Nearest and shift = 0 + qs.copy_from_slice(&qs_2_vec[1..=qs_len]); + qs_2 = &mut qs_2_vec; + (qs_2[0], Limb::WIDTH) + }; + qs_2[0] ^= sticky_3; + // sticky_3 contains the truncated bits from the reciprocal, including the round bit, and 1 <= + // shift_2 <= WIDTH is the number of bits in sticky_3 to round, we distinguish two cases: + // - ds_len <= qs_2_len: we used the full divisor + // - ds_len > qs_2_len: the divisor was truncated + let mut inex = Greater; + let mut round_bit = 0; + let mut cleanup = Cleanup::None; + if ds_len <= qs_2_len { + // use the full divisor + sticky_bit = if rm == Nearest { + round_bit = sticky_3 & Limb::power_of_2(shift_2 - 1); + (sticky_3 ^ round_bit) | Limb::from(sticky_x) + } else if rm == Exact { + panic!("Inexact float reciprocation"); + } else { + 1 + }; + } else { + // ds_len > qs_2_len: need to truncate the divisor + // + // We know the estimated reciprocal is an upper bound of the exact reciprocal (with rounding + // toward zero), with a difference of at most 2 in qs_2[0]. Thus we can round except when + // sticky_3 is 000...000 or 000...001 for directed rounding, and 100...000 or 100...001 for + // rounding to nearest. (For rounding to nearest, we cannot determine the inexact flag for + // 000...000 or 000...001.) + let sticky_3_orig = sticky_3; + if rm == Nearest { + round_bit = sticky_3 & Limb::power_of_2(shift_2 - 1); + sticky_3 ^= round_bit; + } + if sticky_3 > 1 { + sticky_bit = sticky_3; + } else { + // hard case: we have to compare q1 * v0 and r + u0, where q1 * v0 has qs_2_len + + // (ds_len-qs_2_len) = ds_len limbs, and r + u0 has qs_2_len + (usize-2*qs_2_len) = + // usize-qs_2_len limbs + let k = ds_len - qs_2_len; + // sp <- {qs_2, qs_2_len} * {ds, ds_len - qs_2_len} + let mut scratch = vec![0; ds_len + limbs_mul_to_out_scratch_len(qs_2_len, k)]; + let (sp, scratch) = scratch.split_at_mut(ds_len); + qs_2[0] ^= sticky_3_orig; // restore original reciprocal + let ds_lo = &ds[..k]; + limbs_mul_to_out(sp, qs_2, ds_lo, scratch); + let q_high_2 = if q_high { + limbs_slice_add_same_length_in_place_left(&mut sp[qs_2_len..], ds_lo) + } else { + false + }; + qs_2[0] ^= sticky_3_orig; + // restore truncated reciprocal + // + // Compare q_high_2 + {sp, ds_len} to {xs, qs_2_len} + u0 + let (sp_lo, sp_hi) = sp.split_at_mut(k); + let mut cmp_s_r = if q_high_2 { + Greater + } else { + limbs_cmp_same_length(sp_hi, &xs[..qs_2_len]) + }; + if cmp_s_r == Equal { + // compare {sp, k} and u0 + cmp_s_r = if slice_test_zero(sp_lo) { + Equal + } else { + Greater + }; + } + // now + // - cmp_s_r > 0 if {sp, ds_len} > {xs, qs_2_len} + u0 + // - cmp_s_r = 0 if {sp, ds_len} = {xs, qs_2_len} + u0 + // - cmp_s_r < 0 if {sp, ds_len} < {xs, qs_2_len} + u0 + if cmp_s_r <= Equal { + // reciprocal is in [q1, q1+1) + sticky_bit = if cmp_s_r == Equal { sticky_3 } else { 1 }; + } else { + // cmp_s_r > 0, reciprocal is < q1: to determine if it is in [q1 - 2, q1 - 1] or in + // [q1 - 1, q1], we need to subtract the low part u0 of the dividend from q*v0 + // subtract u0 >> extra_bit if non-zero + if q_high_2 { + // whatever the value of {ns, m + k}, it will be smaller than q_high_2 + {sp, k} + cmp_s_r = Greater; + } else { + // subtract r + limbs_sub_same_length_in_place_left(sp_hi, &xs[..qs_2_len]); + // now compare {sp, ds_len} to y + cmp_s_r = limbs_cmp_same_length(sp, ds); + } + if cmp_s_r <= Equal { + // q1 - 1 <= x / y < q1 + if sticky_3 == 1 { + // q1 - 1 is either representable (directed rounding), or the middle of two + // numbers (nearest) + sticky_bit = Limb::from(cmp_s_r != Equal); + } else if round_bit == 0 { + // round_bit=0, sticky_3=0: q1 - 1 is exact only when sh=0 + inex = if cmp_s_r != Equal || shift != 0 { + Less + } else { + Equal + }; + cleanup = if rm == Nearest || ((rm == Ceiling || rm == Up) && inex != Equal) + { + inex = Greater; + Cleanup::TruncateCheckQHigh + } else if inex != Equal && rm == Exact { + panic!("Inexact float reciprocation"); + } else { + Cleanup::Sub1Ulp + }; + } else { + // sticky_3 = 0, round_bit = 1 ==> rounding to nearest + return (exp_offset, cmp_s_r); + } + } else { + // q1 - 2 < x / y < q1 - 1 + // + // if rm == Nearest, the result is q1 when q1 - 2 >= q1 - 2 ^ (shift - 1), i.e. + // shift >= 2, otherwise (shift = 1) it is q1 - 2 + (inex, cleanup) = if rm == Exact { + panic!("Inexact float reciprocation"); + } else if rm == Nearest { + // shift > 0 + // + // Case shift = 1: sticky_bit = 0 always, and q1 - round_bit is exactly + // representable, like q1 - round_bit - 2. + // ``` + // round_bit action + // 0 subtract two ulps, inex = Less + // 1 truncate, inex = Greater + // ``` + // + // Case shift > 1: one ulp is 2 ^ (shift - 1) >= 2 + // ``` + // round_bit sticky_bit action + // 0 0 truncate, inex = Greater + // 0 1 truncate, inex = Greater + // 1 x truncate, inex = Less + // ``` + if shift == 1 { + if round_bit == 0 { + shift_bit = 1; + (Less, Cleanup::Sub2Ulp) + } else { + (Greater, Cleanup::TruncateCheckQHigh) + } + } else { + ( + if round_bit == 0 { Greater } else { Less }, + Cleanup::TruncateCheckQHigh, + ) + } + } else if rm == Floor || rm == Down { + // The result is down(q1 - 2), i.e. subtract one ulp if shift > 0, and two + // ulps if shift = 0 + ( + Less, + if shift == 0 { + Cleanup::Sub2Ulp + } else { + Cleanup::Sub1Ulp + }, + ) + } else { + ( + Greater, + if shift == 0 { + Cleanup::Sub1Ulp + } else { + Cleanup::TruncateCheckQHigh + }, + ) + }; + } + } + } + } + match cleanup { + Cleanup::None => { + // reciprocal is in [q1, q1 + 1), round_bit is the round_bit (0 for directed rounding) + return if rm == Floor || rm == Down || round_bit == 0 && sticky_bit == 0 { + ( + exp_offset, + if round_bit == 0 && sticky_bit == 0 { + Equal + } else { + Less + }, + ) + } else if rm == Exact { + panic!("Inexact float reciprocation"); + } else if rm == Nearest { + // sticky_bit != 0 or round != 0 + if round_bit == 0 { + // necessarily sticky_bit != 0 + (exp_offset, Less) + } else if sticky_bit != 0 { + if limbs_slice_add_limb_in_place(qs, shift_bit) { + exp_offset += 1; + // else qexp is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } else { + fail_on_untested_path( + "div_float_significands_long_by_short, round_bit != 0 && sticky_bit != 0", + ); + // round_bit = 1, sticky_bit = 0 + if qs[0] & shift_bit == 0 { + (exp_offset, Less) + } else { + if limbs_slice_add_limb_in_place(qs, shift_bit) { + exp_offset += 1; + // else qexp is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + } + } + } else { + // round away from zero, sticky_bit != 0 + if limbs_slice_add_limb_in_place(qs, shift_bit) { + exp_offset += 1; + // else qexp is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, Greater) + }; + } + Cleanup::Sub1Ulp => { + // we cannot subtract 1 << (shift + 1), since this is undefined for shift = WIDTH + if limbs_sub_limb_in_place(qs, shift_bit) { + q_high = false; + } + } + Cleanup::Sub2Ulp => { + if limbs_sub_limb_in_place(qs, shift_bit) { + q_high = false; + } + if limbs_sub_limb_in_place(qs, shift_bit) { + q_high = false; + } + } + _ => {} + } + if q_high { + exp_offset += 1; + // else qexp is now incorrect, but one will still get an overflow + *qs.last_mut().unwrap() = HIGH_BIT; + } + (exp_offset, inex) +} diff --git a/malachite-nz/src/natural/arithmetic/float_sub.rs b/malachite-nz/src/natural/arithmetic/float_sub.rs index 232c618cc..28ae8c37f 100644 --- a/malachite-nz/src/natural/arithmetic/float_sub.rs +++ b/malachite-nz/src/natural/arithmetic/float_sub.rs @@ -4203,7 +4203,7 @@ fn sub_float_significands_general<'a>( } let last_out = &mut out[out_len - 1]; if !goto_end_of_sub && *last_out >> WIDTH_M1 == 0 { - // case 1 - epsilon + // case 1 - varepsilon *last_out = HIGH_BIT; add_exp = 1; } diff --git a/malachite-nz/src/natural/arithmetic/log_base.rs b/malachite-nz/src/natural/arithmetic/log_base.rs index 422ababfe..b6c3bb42a 100644 --- a/malachite-nz/src/natural/arithmetic/log_base.rs +++ b/malachite-nz/src/natural/arithmetic/log_base.rs @@ -26,7 +26,7 @@ use malachite_base::rounding_modes::RoundingMode::*; impl Natural { /// Calculates the approximate natural logarithm of a nonzero [`Natural`]. /// - /// $f(x) = (1+\epsilon)(\log x)$, where $|\epsilon| < 2^{-52}.$ + /// $f(x) = (1+\varepsilon)(\log x)$, where $|\varepsilon| < 2^{-52}.$ /// /// # Worst-case complexity /// $T(n) = O(n)$ diff --git a/malachite-nz/src/natural/arithmetic/mod.rs b/malachite-nz/src/natural/arithmetic/mod.rs index a2f222235..e55e593b8 100644 --- a/malachite-nz/src/natural/arithmetic/mod.rs +++ b/malachite-nz/src/natural/arithmetic/mod.rs @@ -77,10 +77,14 @@ pub mod factorial; #[cfg(feature = "float_helpers")] pub mod float_add; #[cfg(feature = "float_helpers")] +pub mod float_div; +#[cfg(feature = "float_helpers")] pub mod float_extras; #[cfg(feature = "float_helpers")] pub mod float_mul; #[cfg(feature = "float_helpers")] +pub mod float_reciprocal; +#[cfg(feature = "float_helpers")] pub mod float_square; #[cfg(feature = "float_helpers")] pub mod float_sub; diff --git a/malachite-nz/src/natural/random/mod.rs b/malachite-nz/src/natural/random/mod.rs index 04f432510..df87b538c 100644 --- a/malachite-nz/src/natural/random/mod.rs +++ b/malachite-nz/src/natural/random/mod.rs @@ -1104,12 +1104,12 @@ impl Iterator for StripedRandomNaturalInclusiveRange { /// Generates random striped [`Natural`]s in the range $[a, b)$. /// -/// The [`Natural`] are generated using a striped bit sequence with mean run length $m$, which is +/// The [`Natural`]s are generated using a striped bit sequence with mean run length $m$, which is /// `mean_stripe_numerator / mean_stripe_denominator`. /// -/// Because the [`Natural`] are constrained to be within a certain range, the actual mean run length -/// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run -/// length. +/// Because the [`Natural`]s are constrained to be within a certain range, the actual mean run +/// length will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean +/// run length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// @@ -1165,9 +1165,9 @@ pub fn striped_random_natural_range( /// The [`Natural`]s are generated using a striped bit sequence with mean run length $m$ = /// `mean_stripe_numerator / mean_stripe_denominator`. /// -/// Because the [`Natural`] are constrained to be within a certain range, the actual mean run length -/// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run -/// length. +/// Because the [`Natural`]s are constrained to be within a certain range, the actual mean run +/// length will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean +/// run length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// @@ -1228,6 +1228,142 @@ pub fn striped_random_natural_inclusive_range( } } +/// Generates a random striped [`Natural`] in the range $[a, b)$. +/// +/// See [`StripedBitSource`] for information about generating striped random numbers. +/// +/// # Expected complexity per iteration +/// $T(n) = O(n)$ +/// +/// $M(n) = O(n)$ +/// +/// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. +/// +/// # Panics +/// Panics if $a\geq b$. +/// +/// # Examples +/// ``` +/// use malachite_base::num::random::striped::StripedBitSource; +/// use malachite_base::random::EXAMPLE_SEED; +/// use malachite_base::strings::ToBinaryString; +/// use malachite_nz::natural::random::get_striped_random_natural_from_range; +/// use malachite_nz::natural::Natural; +/// +/// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 10, 1); +/// assert_eq!( +/// get_striped_random_natural_from_range( +/// &mut bit_source, +/// Natural::from(10000u32), +/// Natural::from(20000u32) +/// ) +/// .to_binary_string(), +/// "10011100111111" +/// ); +/// ``` +#[inline] +pub fn get_striped_random_natural_from_range( + xs: &mut StripedBitSource, + a: Natural, + b: Natural, +) -> Natural { + assert!(a < b); + get_striped_random_natural_from_inclusive_range(xs, a, b - Natural::ONE) +} + +/// Generates a random striped [`Natural`] in the range $[a, b]$. +/// +/// See [`StripedBitSource`] for information about generating striped random numbers. +/// +/// # Expected complexity per iteration +/// $T(n) = O(n)$ +/// +/// $M(n) = O(n)$ +/// +/// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. +/// +/// # Panics +/// Panics if $a > b$. +/// +/// # Examples +/// ``` +/// use malachite_base::num::random::striped::StripedBitSource; +/// use malachite_base::random::EXAMPLE_SEED; +/// use malachite_base::strings::ToBinaryString; +/// use malachite_nz::natural::random::get_striped_random_natural_from_inclusive_range; +/// use malachite_nz::natural::Natural; +/// +/// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 10, 1); +/// assert_eq!( +/// get_striped_random_natural_from_inclusive_range( +/// &mut bit_source, +/// Natural::from(10000u32), +/// Natural::from(19999u32) +/// ) +/// .to_binary_string(), +/// "10011100111111" +/// ); +/// ``` +#[allow(clippy::needless_pass_by_value)] +pub fn get_striped_random_natural_from_inclusive_range( + xs: &mut StripedBitSource, + a: Natural, + b: Natural, +) -> Natural { + assert!(a <= b); + let diff_bits = (&a ^ &b).significant_bits(); + let mask = Natural::low_mask(diff_bits); + let lo_template = (&a).round_to_multiple_of_power_of_2(diff_bits, Floor).0; + let hi_template = &lo_template | mask; + if diff_bits == 0 { + return lo_template; + } + let mut lo_template = lo_template.clone(); + let mut hi_template = hi_template.clone(); + let mut first = true; + let mut previous_forced = true; + let mut previous_bit = lo_template.get_bit(diff_bits); + for next_bit in (0..diff_bits).rev() { + let false_possible; + let true_possible; + if first { + false_possible = true; + true_possible = true; + lo_template.assign_bit(next_bit, true); + hi_template.assign_bit(next_bit, true); + first = false; + } else { + lo_template.assign_bit(next_bit, false); + hi_template.assign_bit(next_bit, false); + false_possible = ranges_intersect(&lo_template, &hi_template, &a, &b); + lo_template.assign_bit(next_bit, true); + hi_template.assign_bit(next_bit, true); + true_possible = ranges_intersect(&lo_template, &hi_template, &a, &b); + } + assert!(false_possible || true_possible); + let bit = if !false_possible { + previous_forced = true; + true + } else if !true_possible { + previous_forced = true; + false + } else { + if previous_forced { + xs.end_block(); + xs.set_previous_bit(previous_bit); + previous_forced = false; + } + xs.next().unwrap() + }; + if !bit { + lo_template.assign_bit(next_bit, false); + hi_template.assign_bit(next_bit, false); + } + previous_bit = bit; + } + lo_template +} + /// Generates striped random [`Natural`]s greater than or equal to a lower bound. #[derive(Clone, Debug)] pub struct StripedRandomNaturalRangeToInfinity { @@ -1265,9 +1401,9 @@ impl Iterator for StripedRandomNaturalRangeToInfinity { /// The [`Natural`]s are generated using a striped bit sequence with mean run length $m$ = /// `mean_stripe_numerator / mean_stripe_denominator`. /// -/// Because the [`Natural`] are constrained to be within a certain range, the actual mean run length -/// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run -/// length. +/// Because the [`Natural`]s are constrained to be within a certain range, the actual mean run +/// length will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean +/// run length. /// /// The output length is infinite. /// diff --git a/malachite-nz/src/test_util/generators/random.rs b/malachite-nz/src/test_util/generators/random.rs index 1d5968fd5..fd51202de 100644 --- a/malachite-nz/src/test_util/generators/random.rs +++ b/malachite-nz/src/test_util/generators/random.rs @@ -107,8 +107,8 @@ use malachite_base::num::random::geometric::{ use malachite_base::num::random::{ random_natural_signeds, random_positive_unsigneds, random_primitive_ints, random_unsigned_bit_chunks, random_unsigned_inclusive_range, random_unsigneds_less_than, - special_random_primitive_floats, variable_range_generator, RandomPrimitiveInts, - RandomUnsignedBitChunks, RandomUnsignedRange, RandomUnsignedsLessThan, VariableRangeGenerator, + special_random_primitive_floats, RandomPrimitiveInts, RandomUnsignedBitChunks, + RandomUnsignedRange, RandomUnsignedsLessThan, VariableRangeGenerator, }; use malachite_base::options::random::{random_options, RandomOptions}; use malachite_base::random::{Seed, EXAMPLE_SEED}; @@ -1647,7 +1647,7 @@ fn random_positive_float_naturals( mean_exponent_numerator, mean_exponent_denominator, ), - ranges: variable_range_generator(seed.fork("mantissas")), + ranges: VariableRangeGenerator::new(seed.fork("mantissas")), phantom: PhantomData, } } diff --git a/malachite-nz/tests/integer/random/get_random_integer_from_range_to_infinity.rs b/malachite-nz/tests/integer/random/get_random_integer_from_range_to_infinity.rs index 187de3758..446405fd2 100644 --- a/malachite-nz/tests/integer/random/get_random_integer_from_range_to_infinity.rs +++ b/malachite-nz/tests/integer/random/get_random_integer_from_range_to_infinity.rs @@ -6,10 +6,12 @@ // 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::arithmetic::traits::Pow; use malachite_base::num::basic::traits::Zero; -use malachite_base::num::random::{random_primitive_ints, variable_range_generator}; +use malachite_base::num::random::{random_primitive_ints, VariableRangeGenerator}; use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; use malachite_nz::integer::random::get_random_integer_from_range_to_infinity; use malachite_nz::integer::Integer; use std::str::FromStr; @@ -20,39 +22,81 @@ fn get_random_integer_from_range_to_infinity_helper( mean_bits_denominator: u64, out: &str, ) { - assert_eq!( - get_random_integer_from_range_to_infinity( - &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), - &mut variable_range_generator(EXAMPLE_SEED.fork("vr")), - Integer::from_str(a).unwrap(), - mean_bits_numerator, - mean_bits_denominator - ) - .to_string(), - out - ); + let mut xs = random_primitive_ints(EXAMPLE_SEED.fork("ints")); + let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")); + let xs = (0..10) + .map(|_| { + get_random_integer_from_range_to_infinity( + &mut xs, + &mut vrg, + Integer::from_str(a).unwrap(), + mean_bits_numerator, + mean_bits_denominator, + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_integer_from_range_to_infinity() { - get_random_integer_from_range_to_infinity_helper("0", 1, 1, "0"); - get_random_integer_from_range_to_infinity_helper("0", 10, 1, "7"); + get_random_integer_from_range_to_infinity_helper("0", 1, 1, "[0, 1, 4, 1, 2, 1, 1, 0, 0, 0]"); + get_random_integer_from_range_to_infinity_helper( + "0", + 10, + 1, + "[7, 7816, 428, 130, 1, 141, 10, 0, 4, 4483]", + ); get_random_integer_from_range_to_infinity_helper( "0", 100, 1, - "5101205056696451696397798478058511", + "[5101205056696451696397798478058511, 1562796, 8799850658374624318722, \ + 432133157539661383965541544934515144954635954990115469923269847259651409024994917000655083\ + 9187394388518593842616549212512013, \ + 279353891976332938189472063076409154515, 1660357170525, \ + 143642188899218739960634489126387586224289351782452807884934768151051511265288490384892849\ + 22660727526851378407, 86075361492, 353552745516847393429177033516378899307448925328642, \ + 577340679116474858586805525866181088123189468507069123812855481357566943854]", ); - get_random_integer_from_range_to_infinity_helper("1000", 11, 1, "1015"); get_random_integer_from_range_to_infinity_helper( "1000", + 11, + 1, + "[1015, 1672, 6316, 1282, 3037, 1805, 1122, 1003, 1014, 1019]", + ); + get_random_integer_from_range_to_infinity_helper( + "1000", + 100, + 1, + "[1206982412795330974999926231143439, 457693356, 169360311075942561584386, \ + 156864198081133600182484993110222733524619588763603298779764468364382591713280608608755884\ + 131404116709444244598775565, 66677412650746398524862933431554022355, 26949124609373, \ + 102746416386110194533593072869947149634954555999655687951279670456046799992002349096588693\ + 3126118631, 22626063730900, 2792352557430693060292673664470974590025115014402, \ + 68488724460300171666815845652220555564874106206890863873832895385292448366]", + ); + get_random_integer_from_range_to_infinity_helper( + "-1000", + 1, + 1, + "[-3, -2, -1, 1, 29, -3, 0, 0, -1, 0]", + ); + get_random_integer_from_range_to_infinity_helper( + "-1000", + 11, + 1, + "[-3, 136, -1, 2, -3, -731, 981996642, 764, 0, 1411]", + ); + get_random_integer_from_range_to_infinity_helper( + "-1000", 100, 1, - "1206982412795330974999926231143439", + "[70671, 33609936868504473224, 3330, 6514514285313835997, \ + 141387787476503121093422704441276431644102874620098798311586658867138567258580573643023899\ + 16124485683507351766006393560845, 250798235515229707219, 136491265145933085529437, \ + 303813780, 816375814318068602464139315741117, -237]", ); - get_random_integer_from_range_to_infinity_helper("-1000", 1, 1, "-3"); - get_random_integer_from_range_to_infinity_helper("-1000", 11, 1, "-3"); - get_random_integer_from_range_to_infinity_helper("-1000", 100, 1, "70671"); } #[test] @@ -60,7 +104,7 @@ fn test_get_random_integer_from_range_to_infinity() { fn get_random_integer_from_range_to_infinity_fail_1() { get_random_integer_from_range_to_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), - &mut variable_range_generator(EXAMPLE_SEED.fork("vr")), + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 1, 0, @@ -72,7 +116,7 @@ fn get_random_integer_from_range_to_infinity_fail_1() { fn get_random_integer_from_range_to_infinity_fail_2() { get_random_integer_from_range_to_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), - &mut variable_range_generator(EXAMPLE_SEED.fork("vr")), + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 2, 0, @@ -84,7 +128,7 @@ fn get_random_integer_from_range_to_infinity_fail_2() { fn get_random_integer_from_range_to_infinity_fail_3() { get_random_integer_from_range_to_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), - &mut variable_range_generator(EXAMPLE_SEED.fork("vr")), + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::from(10u32).pow(100), 10, 1, diff --git a/malachite-nz/tests/integer/random/get_random_integer_from_range_to_negative_infinity.rs b/malachite-nz/tests/integer/random/get_random_integer_from_range_to_negative_infinity.rs index 746bcbcd7..e0f267d38 100644 --- a/malachite-nz/tests/integer/random/get_random_integer_from_range_to_negative_infinity.rs +++ b/malachite-nz/tests/integer/random/get_random_integer_from_range_to_negative_infinity.rs @@ -6,10 +6,12 @@ // 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::arithmetic::traits::Pow; use malachite_base::num::basic::traits::Zero; -use malachite_base::num::random::{random_primitive_ints, variable_range_generator}; +use malachite_base::num::random::{random_primitive_ints, VariableRangeGenerator}; use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; use malachite_nz::integer::random::get_random_integer_from_range_to_negative_infinity; use malachite_nz::integer::Integer; use std::str::FromStr; @@ -20,38 +22,85 @@ fn get_random_integer_from_range_to_negative_infinity_helper( mean_bits_denominator: u64, out: &str, ) { - assert_eq!( - get_random_integer_from_range_to_negative_infinity( - &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), - &mut variable_range_generator(EXAMPLE_SEED.fork("vr")), - Integer::from_str(a).unwrap(), - mean_bits_numerator, - mean_bits_denominator - ) - .to_string(), - out - ); + let mut xs = random_primitive_ints(EXAMPLE_SEED.fork("ints")); + let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")); + let xs = (0..10) + .map(|_| { + get_random_integer_from_range_to_negative_infinity( + &mut xs, + &mut vrg, + Integer::from_str(a).unwrap(), + mean_bits_numerator, + mean_bits_denominator, + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_integer_from_range_to_negative_infinity() { - get_random_integer_from_range_to_negative_infinity_helper("0", 1, 1, "0"); - get_random_integer_from_range_to_negative_infinity_helper("0", 10, 1, "-7"); get_random_integer_from_range_to_negative_infinity_helper( "0", + 1, + 1, + "[0, -1, -4, -1, -2, -1, -1, 0, 0, 0]", + ); + get_random_integer_from_range_to_negative_infinity_helper( + "0", + 10, + 1, + "[-7, -7816, -428, -130, -1, -141, -10, 0, -4, -4483]", + ); + get_random_integer_from_range_to_negative_infinity_helper( + "0", + 100, + 1, + "[-5101205056696451696397798478058511, -1562796, -8799850658374624318722, \ + -43213315753966138396554154493451514495463595499011546992326984725965140902499491700065508\ + 39187394388518593842616549212512013, -279353891976332938189472063076409154515, \ + -1660357170525, \ + -14364218889921873996063448912638758622428935178245280788493476815105151126528849038489284\ + 922660727526851378407, -86075361492, \ + -353552745516847393429177033516378899307448925328642, \ + -577340679116474858586805525866181088123189468507069123812855481357566943854]", + ); + get_random_integer_from_range_to_negative_infinity_helper( + "1000", + 1, + 1, + "[-3, -2, -1, 1, 29, -3, 0, 0, -1, 0]", + ); + get_random_integer_from_range_to_negative_infinity_helper( + "1000", + 11, + 1, + "[-5135, -4, 108, -1, 3, -3, -3666351202, -1, -37251, 718]", + ); + get_random_integer_from_range_to_negative_infinity_helper( + "1000", 100, 1, - "-5101205056696451696397798478058511", + "[-2429686799, 648, -2730587924715692, 1, -4964076984094755832797, \ + -829471522969346588791746968515146309473173680336193392475266233389518923764834, \ + -89318048233905, -17177555, -451081617762069, -2086237]", + ); + get_random_integer_from_range_to_negative_infinity_helper( + "-1000", + 11, + 1, + "[-1008, -1672, -6316, -1282, -3037, -1805, -1122, -1020, -1009, -1004]", ); - get_random_integer_from_range_to_negative_infinity_helper("1000", 1, 1, "-3"); - get_random_integer_from_range_to_negative_infinity_helper("1000", 11, 1, "-5135"); - get_random_integer_from_range_to_negative_infinity_helper("1000", 100, 1, "-2429686799"); - get_random_integer_from_range_to_negative_infinity_helper("-1000", 11, 1, "-1008"); get_random_integer_from_range_to_negative_infinity_helper( "-1000", 100, 1, - "-1206982412795330974999926231143439", + "[-1206982412795330974999926231143439, -457693356, -169360311075942561584386, \ + -15686419808113360018248499311022273352461958876360329877976446836438259171328060860875588\ + 4131404116709444244598775565, -66677412650746398524862933431554022355, -26949124609373, \ + -10274641638611019453359307286994714963495455599965568795127967045604679999200234909658869\ + 33126118631, -22626063730900, -2792352557430693060292673664470974590025115014402, \ + -68488724460300171666815845652220555564874106206890863873832895385292448366]", ); } @@ -60,7 +109,7 @@ fn test_get_random_integer_from_range_to_negative_infinity() { fn get_random_integer_from_range_to_negative_infinity_fail_1() { get_random_integer_from_range_to_negative_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), - &mut variable_range_generator(EXAMPLE_SEED.fork("vr")), + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 1, 0, @@ -72,7 +121,7 @@ fn get_random_integer_from_range_to_negative_infinity_fail_1() { fn get_random_integer_from_range_to_negative_infinity_fail_2() { get_random_integer_from_range_to_negative_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), - &mut variable_range_generator(EXAMPLE_SEED.fork("vr")), + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 2, 0, @@ -84,7 +133,7 @@ fn get_random_integer_from_range_to_negative_infinity_fail_2() { fn get_random_integer_from_range_to_negative_infinity_fail_3() { get_random_integer_from_range_to_negative_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), - &mut variable_range_generator(EXAMPLE_SEED.fork("vr")), + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), -Integer::from(10u32).pow(100), 10, 1, diff --git a/malachite-nz/tests/integer/random/get_striped_random_integer_from_inclusive_range.rs b/malachite-nz/tests/integer/random/get_striped_random_integer_from_inclusive_range.rs new file mode 100644 index 000000000..0c9455b28 --- /dev/null +++ b/malachite-nz/tests/integer/random/get_striped_random_integer_from_inclusive_range.rs @@ -0,0 +1,141 @@ +// 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::random::striped::StripedBitSource; +use malachite_base::num::random::VariableRangeGenerator; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; +use malachite_nz::integer::random::get_striped_random_integer_from_inclusive_range; +use malachite_nz::integer::Integer; +use std::str::FromStr; + +fn get_striped_random_integer_from_inclusive_range_helper( + m_numerator: u64, + m_denominator: u64, + a: &str, + b: &str, + out: &str, +) { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), m_numerator, m_denominator); + let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vrg")); + let xs = (0..10) + .map(|_| { + get_striped_random_integer_from_inclusive_range( + &mut bit_source, + &mut vrg, + Integer::from_str(a).unwrap(), + Integer::from_str(b).unwrap(), + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); +} + +#[test] +fn test_get_striped_random_integer_from_inclusive_range() { + get_striped_random_integer_from_inclusive_range_helper( + 2, + 1, + "0", + "0", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 2, + 1, + "1950", + "2019", + "[2014, 1964, 2008, 1994, 1999, 1971, 1990, 1984, 2016, 2018]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 2, + 1, + "-10000", + "9000", + "[8458, 8998, 8818, -8899, -9414, 8703, 8540, 6141, 2042, 6456]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 2, + 1, + "-10000", + "-1000", + "[-8724, -9372, -8880, -9422, -8448, -9891, -8959, -8479, -1002, -4963]", + ); + + get_striped_random_integer_from_inclusive_range_helper( + 10, + 1, + "0", + "0", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 10, + 1, + "1950", + "2019", + "[2016, 1987, 2019, 1951, 2019, 1951, 2019, 1951, 1950, 1950]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 10, + 1, + "-10000", + "9000", + "[8312, 8992, 8992, -10000, -2046, 8192, 0, 4095, 63, 2047]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 10, + 1, + "-10000", + "-1000", + "[-8432, -10000, -1023, -9999, -10000, -1016, -1000, -1007, -8192, -4095]", + ); + + get_striped_random_integer_from_inclusive_range_helper( + 11, + 10, + "0", + "0", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 11, + 10, + "1950", + "2019", + "[1992, 1962, 2005, 2018, 1962, 2005, 2005, 2005, 1951, 2005]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 11, + 10, + "-10000", + "9000", + "[8634, 8874, 8362, -9557, -8877, 8874, 8533, 8362, 5461, 5333]", + ); + get_striped_random_integer_from_inclusive_range_helper( + 11, + 10, + "-10000", + "-1000", + "[-9077, -9558, -8874, -9557, -8853, -9557, -8885, -8874, -5462, -2710]", + ); +} + +#[test] +#[should_panic] +fn get_striped_random_integer_from_inclusive_range_fail_1() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); + let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vrg")); + get_striped_random_integer_from_inclusive_range( + &mut bit_source, + &mut vrg, + Integer::from(10u32), + Integer::from(9u32), + ); +} diff --git a/malachite-nz/tests/integer/random/get_striped_random_integer_from_range.rs b/malachite-nz/tests/integer/random/get_striped_random_integer_from_range.rs new file mode 100644 index 000000000..b5e1e1389 --- /dev/null +++ b/malachite-nz/tests/integer/random/get_striped_random_integer_from_range.rs @@ -0,0 +1,129 @@ +// 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::random::striped::StripedBitSource; +use malachite_base::num::random::VariableRangeGenerator; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; +use malachite_nz::integer::random::get_striped_random_integer_from_range; +use malachite_nz::integer::Integer; +use std::str::FromStr; + +fn get_striped_random_integer_from_range_helper( + m_numerator: u64, + m_denominator: u64, + a: &str, + b: &str, + out: &str, +) { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), m_numerator, m_denominator); + let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vrg")); + let xs = (0..10) + .map(|_| { + get_striped_random_integer_from_range( + &mut bit_source, + &mut vrg, + Integer::from_str(a).unwrap(), + Integer::from_str(b).unwrap(), + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); +} + +#[test] +fn test_get_striped_random_integer_from_range() { + get_striped_random_integer_from_range_helper(2, 1, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_integer_from_range_helper( + 2, + 1, + "1950", + "2020", + "[2014, 1964, 2008, 1994, 1999, 1971, 1990, 1984, 2016, 2018]", + ); + get_striped_random_integer_from_range_helper( + 2, + 1, + "-10000", + "9001", + "[8458, 8998, 8818, -8899, -9414, 8703, 8540, 6141, 2042, 6456]", + ); + get_striped_random_integer_from_range_helper( + 2, + 1, + "-10000", + "-999", + "[-8724, -9372, -8880, -9422, -8448, -9891, -8959, -8479, -1002, -4963]", + ); + + get_striped_random_integer_from_range_helper(10, 1, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_integer_from_range_helper( + 10, + 1, + "1950", + "2020", + "[2016, 1987, 2019, 1951, 2019, 1951, 2019, 1951, 1950, 1950]", + ); + get_striped_random_integer_from_range_helper( + 10, + 1, + "-10000", + "9001", + "[8312, 8992, 8992, -10000, -2046, 8192, 0, 4095, 63, 2047]", + ); + get_striped_random_integer_from_range_helper( + 10, + 1, + "-10000", + "-999", + "[-8432, -10000, -1023, -9999, -10000, -1016, -1000, -1007, -8192, -4095]", + ); + + get_striped_random_integer_from_range_helper( + 11, + 10, + "0", + "1", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_striped_random_integer_from_range_helper( + 11, + 10, + "1950", + "2020", + "[1992, 1962, 2005, 2018, 1962, 2005, 2005, 2005, 1951, 2005]", + ); + get_striped_random_integer_from_range_helper( + 11, + 10, + "-10000", + "9001", + "[8634, 8874, 8362, -9557, -8877, 8874, 8533, 8362, 5461, 5333]", + ); + get_striped_random_integer_from_range_helper( + 11, + 10, + "-10000", + "-999", + "[-9077, -9558, -8874, -9557, -8853, -9557, -8885, -8874, -5462, -2710]", + ); +} + +#[test] +#[should_panic] +fn get_striped_random_integer_from_range_fail_1() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); + let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vrg")); + get_striped_random_integer_from_range( + &mut bit_source, + &mut vrg, + Integer::from(10u32), + Integer::from(9u32), + ); +} diff --git a/malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_infinity.rs b/malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_infinity.rs new file mode 100644 index 000000000..a1a05d26d --- /dev/null +++ b/malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_infinity.rs @@ -0,0 +1,167 @@ +// 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::arithmetic::traits::Pow; +use malachite_base::num::basic::traits::Zero; +use malachite_base::num::random::striped::StripedBitSource; +use malachite_base::num::random::VariableRangeGenerator; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; +use malachite_nz::integer::random::get_striped_random_integer_from_range_to_infinity; +use malachite_nz::integer::Integer; +use std::str::FromStr; + +fn get_striped_random_integer_from_range_to_infinity_helper( + a: &str, + mean_stripe_numerator: u64, + mean_stripe_denominator: u64, + mean_bits_numerator: u64, + mean_bits_denominator: u64, + out: &str, +) { + let mut bit_source = StripedBitSource::new( + EXAMPLE_SEED.fork("bs"), + mean_stripe_numerator, + mean_stripe_denominator, + ); + let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")); + let xs = (0..10) + .map(|_| { + get_striped_random_integer_from_range_to_infinity( + &mut bit_source, + &mut vrg, + Integer::from_str(a).unwrap(), + mean_bits_numerator, + mean_bits_denominator, + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); +} + +#[test] +fn test_get_striped_random_integer_from_range_to_infinity() { + get_striped_random_integer_from_range_to_infinity_helper( + "0", + 10, + 1, + 1, + 1, + "[0, 1, 4, 1, 3, 1, 1, 0, 0, 0]", + ); + get_striped_random_integer_from_range_to_infinity_helper( + "0", + 10, + 1, + 10, + 1, + "[7, 4126, 511, 255, 1, 248, 15, 0, 7, 8191]", + ); + get_striped_random_integer_from_range_to_infinity_helper( + "0", + 10, + 1, + 100, + 1, + "[2920647185518839672075671782293383, 1048576, 4739083809502202445823, \ + 528812496939392674605437340435408671558612951523319156054677508322810572932328766514425150\ + 8429219658089743953085078238920703, 170472354644468060339516718901910044671, \ + 1099511627776, \ + 186415569962779171680854936542673085018277752582758046597588616311812447948859965258255723\ + 66927316848155197439, 137436864511, 187077834941321271646236832607563322963774152898535, \ + 897560034344005936431766292731307813053258931074478508157776167326430855104]", + ); + get_striped_random_integer_from_range_to_infinity_helper( + "1000", + 10, + 1, + 11, + 1, + "[1020, 2040, 4351, 1087, 4095, 1536, 2047, 1023, 1022, 1007]", + ); + get_striped_random_integer_from_range_to_infinity_helper( + "1000", + 10, + 1, + 100, + 1, + "[973535863568279311376735658835847, 268435456, 151115988660057280545023, \ + 788041621480711912165160823578914479144879663560965225783543272513529599243438802396891675\ + 96389234574457387517706367, 61144487963324812669777136988278751233, 35184372088704, \ + 108958909782649556234624985077749301722270247350340375090485228690114398468811820627146895\ + 0192652287, 34084862300097, 2922291218836765780501982453037225347447510761475, \ + 113055782260031715275206575103088333621424376204588378848515940842185162750]", + ); + get_striped_random_integer_from_range_to_infinity_helper( + "-1000", + 10, + 1, + 1, + 1, + "[-3, -2, -1, 1, 17, -2, 0, 0, -1, 0]", + ); + get_striped_random_integer_from_range_to_infinity_helper( + "-1000", + 10, + 1, + 11, + 1, + "[-3, 188, -1, 3, -3, -512, 1073725455, 1023, 0, 2047]", + ); + get_striped_random_integer_from_range_to_infinity_helper( + "-1000", + 10, + 1, + 100, + 1, + "[130951, 19023203726501412800, 2055, 4629700416936738823, \ + 206378257939585890650633610891897828407043084058691785319121408973257569307274994499096280\ + 35369831199775792242011278409759, 295147869995014168352, 132373800004962371502079, \ + 507510783, 1297559231579135076369342163583007, -128]", + ); +} + +#[test] +#[should_panic] +fn get_striped_random_integer_from_range_to_infinity_fail_1() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); + get_striped_random_integer_from_range_to_infinity( + &mut bit_source, + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), + Integer::ZERO, + 1, + 0, + ); +} + +#[test] +#[should_panic] +fn get_striped_random_integer_from_range_to_infinity_fail_2() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); + get_striped_random_integer_from_range_to_infinity( + &mut bit_source, + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), + Integer::ZERO, + 2, + 0, + ); +} + +#[test] +#[should_panic] +fn get_striped_random_integer_from_range_to_infinity_fail_3() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); + get_striped_random_integer_from_range_to_infinity( + &mut bit_source, + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), + Integer::from(10u32).pow(100), + 10, + 1, + ); +} diff --git a/malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_negative_infinity.rs b/malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_negative_infinity.rs new file mode 100644 index 000000000..ea9ae8951 --- /dev/null +++ b/malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_negative_infinity.rs @@ -0,0 +1,158 @@ +// 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::arithmetic::traits::Pow; +use malachite_base::num::basic::traits::Zero; +use malachite_base::num::random::striped::StripedBitSource; +use malachite_base::num::random::VariableRangeGenerator; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; +use malachite_nz::integer::random::get_striped_random_integer_from_range_to_negative_infinity; +use malachite_nz::integer::Integer; +use std::str::FromStr; + +fn get_striped_random_integer_from_range_to_negative_infinity_helper( + a: &str, + mean_stripe_numerator: u64, + mean_stripe_denominator: u64, + mean_bits_numerator: u64, + mean_bits_denominator: u64, + out: &str, +) { + let mut bit_source = StripedBitSource::new( + EXAMPLE_SEED.fork("bs"), + mean_stripe_numerator, + mean_stripe_denominator, + ); + let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")); + let xs = (0..10) + .map(|_| { + get_striped_random_integer_from_range_to_negative_infinity( + &mut bit_source, + &mut vrg, + Integer::from_str(a).unwrap(), + mean_bits_numerator, + mean_bits_denominator, + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); +} + +#[test] +fn test_get_striped_random_integer_from_range_to_negative_infinity() { + get_striped_random_integer_from_range_to_negative_infinity_helper( + "0", + 10, + 1, + 1, + 1, + "[0, -1, -4, -1, -3, -1, -1, 0, 0, 0]", + ); + get_striped_random_integer_from_range_to_negative_infinity_helper( + "0", + 10, + 1, + 10, + 1, + "[-7, -4126, -511, -255, -1, -248, -15, 0, -7, -8191]", + ); + get_striped_random_integer_from_range_to_negative_infinity_helper( + "0", + 10, + 1, + 100, + 1, + "[-2920647185518839672075671782293383, -1048576, -4739083809502202445823, \ + -52881249693939267460543734043540867155861295152331915605467750832281057293232876651442515\ + 08429219658089743953085078238920703, -170472354644468060339516718901910044671, \ + -1099511627776, -1864155699627791716808549365426730850182777525827580465975886163118124479\ + 4885996525825572366927316848155197439, -137436864511, \ + -187077834941321271646236832607563322963774152898535, \ + -897560034344005936431766292731307813053258931074478508157776167326430855104]", + ); + get_striped_random_integer_from_range_to_negative_infinity_helper( + "1000", + 10, + 1, + 11, + 1, + "[-8071, -4, 127, -1, 3, -2, -2147484671, -1, -32775, 515]", + ); + get_striped_random_integer_from_range_to_negative_infinity_helper( + "1000", + 10, + 1, + 100, + 1, + "[-2151677831, 767, -2269323280383999, 1, -5008327044809161965583, \ + -466786749337581235991134723080519000284817084727848060138773225560246511976448, \ + -140672846790145, -29360131, -283605347598335, -2096896]", + ); + get_striped_random_integer_from_range_to_negative_infinity_helper( + "-1000", + 10, + 1, + 11, + 1, + "[-1020, -2040, -4351, -1087, -4095, -1536, -2047, -1023, -1022, -1007]", + ); + get_striped_random_integer_from_range_to_negative_infinity_helper( + "-1000", + 10, + 1, + 100, + 1, + "[-973535863568279311376735658835847, -268435456, -151115988660057280545023, \ + -78804162148071191216516082357891447914487966356096522578354327251352959924343880239689167\ + 596389234574457387517706367, -61144487963324812669777136988278751233, -35184372088704, \ + -10895890978264955623462498507774930172227024735034037509048522869011439846881182062714689\ + 50192652287, -34084862300097, -2922291218836765780501982453037225347447510761475, \ + -113055782260031715275206575103088333621424376204588378848515940842185162750]", + ); +} + +#[test] +#[should_panic] +fn get_striped_random_integer_from_range_to_negative_infinity_fail_1() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); + get_striped_random_integer_from_range_to_negative_infinity( + &mut bit_source, + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), + Integer::ZERO, + 1, + 0, + ); +} + +#[test] +#[should_panic] +fn get_striped_random_integer_from_range_to_negative_infinity_fail_2() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); + get_striped_random_integer_from_range_to_negative_infinity( + &mut bit_source, + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), + Integer::ZERO, + 2, + 0, + ); +} + +#[test] +#[should_panic] +fn get_striped_random_integer_from_range_to_negative_infinity_fail_3() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); + get_striped_random_integer_from_range_to_negative_infinity( + &mut bit_source, + &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), + -Integer::from(10).pow(100), + 10, + 1, + ); +} diff --git a/malachite-nz/tests/integer/random/get_uniform_random_integer_from_inclusive_range.rs b/malachite-nz/tests/integer/random/get_uniform_random_integer_from_inclusive_range.rs new file mode 100644 index 000000000..241fa4c25 --- /dev/null +++ b/malachite-nz/tests/integer/random/get_uniform_random_integer_from_inclusive_range.rs @@ -0,0 +1,64 @@ +// 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::num::random::random_primitive_ints; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; +use malachite_nz::integer::random::get_uniform_random_integer_from_inclusive_range; +use malachite_nz::integer::Integer; +use std::str::FromStr; + +fn get_uniform_random_integer_from_inclusive_range_helper(a: &str, b: &str, out: &str) { + let mut xs = random_primitive_ints(EXAMPLE_SEED.fork("ints")); + let xs = (0..10) + .map(|_| { + get_uniform_random_integer_from_inclusive_range( + &mut xs, + Integer::from_str(a).unwrap(), + Integer::from_str(b).unwrap(), + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); +} + +#[test] +fn test_get_uniform_random_integer_from_inclusive_range() { + get_uniform_random_integer_from_inclusive_range_helper( + "0", + "0", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_uniform_random_integer_from_inclusive_range_helper( + "1950", + "2019", + "[1965, 1958, 1994, 1952, 1963, 1953, 1999, 1971, 1970, 2011]", + ); + get_uniform_random_integer_from_inclusive_range_helper( + "-10", + "9", + "[5, -2, 2, -8, 3, -8, -7, 4, 9, 7]", + ); + get_uniform_random_integer_from_inclusive_range_helper( + "-10", + "-1", + "[-2, -8, -8, -7, -7, -9, -7, -5, -3, -6]", + ); +} + +#[test] +#[should_panic] +fn get_uniform_random_integer_from_inclusive_range_fail() { + get_uniform_random_integer_from_inclusive_range( + &mut random_primitive_ints(EXAMPLE_SEED), + Integer::ONE, + Integer::ZERO, + ); +} diff --git a/malachite-nz/tests/integer/random/get_uniform_random_integer_from_range.rs b/malachite-nz/tests/integer/random/get_uniform_random_integer_from_range.rs new file mode 100644 index 000000000..a2874c7d1 --- /dev/null +++ b/malachite-nz/tests/integer/random/get_uniform_random_integer_from_range.rs @@ -0,0 +1,56 @@ +// 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::Zero; +use malachite_base::num::random::random_primitive_ints; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; +use malachite_nz::integer::random::get_uniform_random_integer_from_range; +use malachite_nz::integer::Integer; +use std::str::FromStr; + +fn get_uniform_random_integer_from_range_helper(a: &str, b: &str, out: &str) { + let mut xs = random_primitive_ints(EXAMPLE_SEED.fork("ints")); + let xs = (0..10) + .map(|_| { + get_uniform_random_integer_from_range( + &mut xs, + Integer::from_str(a).unwrap(), + Integer::from_str(b).unwrap(), + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); +} + +#[test] +fn test_get_uniform_random_integer_from_range() { + get_uniform_random_integer_from_range_helper("0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_uniform_random_integer_from_range_helper( + "1950", + "2020", + "[1965, 1958, 1994, 1952, 1963, 1953, 1999, 1971, 1970, 2011]", + ); + get_uniform_random_integer_from_range_helper("-10", "10", "[5, -2, 2, -8, 3, -8, -7, 4, 9, 7]"); + get_uniform_random_integer_from_range_helper( + "-10", + "0", + "[-2, -8, -8, -7, -7, -9, -7, -5, -3, -6]", + ); +} + +#[test] +#[should_panic] +fn get_uniform_random_integer_from_range_fail() { + get_uniform_random_integer_from_range( + &mut random_primitive_ints(EXAMPLE_SEED), + Integer::ZERO, + Integer::ZERO, + ); +} diff --git a/malachite-nz/tests/integer/random/get_uniform_random_integer_in_inclusive_range.rs b/malachite-nz/tests/integer/random/get_uniform_random_integer_in_inclusive_range.rs deleted file mode 100644 index 405515faa..000000000 --- a/malachite-nz/tests/integer/random/get_uniform_random_integer_in_inclusive_range.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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::random::random_primitive_ints; -use malachite_base::random::EXAMPLE_SEED; -use malachite_nz::integer::random::get_uniform_random_integer_in_inclusive_range; -use malachite_nz::integer::Integer; -use std::str::FromStr; - -fn get_uniform_random_integer_in_inclusive_range_helper(a: &str, b: &str, out: &str) { - assert_eq!( - get_uniform_random_integer_in_inclusive_range( - &mut random_primitive_ints(EXAMPLE_SEED), - Integer::from_str(a).unwrap(), - Integer::from_str(b).unwrap() - ) - .to_string(), - out - ); -} - -#[test] -fn test_get_uniform_random_integer_in_inclusive_range() { - get_uniform_random_integer_in_inclusive_range_helper("0", "0", "0"); - get_uniform_random_integer_in_inclusive_range_helper("1950", "2019", "1957"); - get_uniform_random_integer_in_inclusive_range_helper("-10", "9", "7"); - get_uniform_random_integer_in_inclusive_range_helper("-10", "-1", "-9"); -} - -#[test] -#[should_panic] -fn get_uniform_random_integer_in_inclusive_range_fail() { - get_uniform_random_integer_in_inclusive_range( - &mut random_primitive_ints(EXAMPLE_SEED), - Integer::ONE, - Integer::ZERO, - ); -} diff --git a/malachite-nz/tests/integer/random/get_uniform_random_integer_in_range.rs b/malachite-nz/tests/integer/random/get_uniform_random_integer_in_range.rs deleted file mode 100644 index 49e712ccc..000000000 --- a/malachite-nz/tests/integer/random/get_uniform_random_integer_in_range.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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::Zero; -use malachite_base::num::random::random_primitive_ints; -use malachite_base::random::EXAMPLE_SEED; -use malachite_nz::integer::random::get_uniform_random_integer_in_range; -use malachite_nz::integer::Integer; -use std::str::FromStr; - -fn get_uniform_random_integer_in_range_helper(a: &str, b: &str, out: &str) { - assert_eq!( - get_uniform_random_integer_in_range( - &mut random_primitive_ints(EXAMPLE_SEED), - Integer::from_str(a).unwrap(), - Integer::from_str(b).unwrap() - ) - .to_string(), - out - ); -} - -#[test] -fn test_get_uniform_random_integer_in_range() { - get_uniform_random_integer_in_range_helper("0", "1", "0"); - get_uniform_random_integer_in_range_helper("1950", "2020", "1957"); - get_uniform_random_integer_in_range_helper("-10", "10", "7"); - get_uniform_random_integer_in_range_helper("-10", "0", "-9"); -} - -#[test] -#[should_panic] -fn get_uniform_random_integer_in_range_fail() { - get_uniform_random_integer_in_range( - &mut random_primitive_ints(EXAMPLE_SEED), - Integer::ZERO, - Integer::ZERO, - ); -} diff --git a/malachite-nz/tests/lib.rs b/malachite-nz/tests/lib.rs index b9a1c3d1b..7243d52f4 100644 --- a/malachite-nz/tests/lib.rs +++ b/malachite-nz/tests/lib.rs @@ -190,8 +190,12 @@ pub mod integer { pub mod random { pub mod get_random_integer_from_range_to_infinity; pub mod get_random_integer_from_range_to_negative_infinity; - pub mod get_uniform_random_integer_in_inclusive_range; - pub mod get_uniform_random_integer_in_range; + pub mod get_striped_random_integer_from_inclusive_range; + pub mod get_striped_random_integer_from_range; + pub mod get_striped_random_integer_from_range_to_infinity; + pub mod get_striped_random_integer_from_range_to_negative_infinity; + pub mod get_uniform_random_integer_from_inclusive_range; + pub mod get_uniform_random_integer_from_range; pub mod random_integer_inclusive_range; pub mod random_integer_range; pub mod random_integer_range_to_infinity; @@ -371,6 +375,8 @@ pub mod natural { pub mod get_random_natural_less_than; pub mod get_random_natural_with_bits; pub mod get_random_natural_with_up_to_bits; + pub mod get_striped_random_natural_from_inclusive_range; + pub mod get_striped_random_natural_from_range; pub mod get_striped_random_natural_with_bits; pub mod get_striped_random_natural_with_up_to_bits; pub mod random_natural_inclusive_range; diff --git a/malachite-nz/tests/natural/random/get_random_natural_less_than.rs b/malachite-nz/tests/natural/random/get_random_natural_less_than.rs index 3d63fb794..0f8ff9d90 100644 --- a/malachite-nz/tests/natural/random/get_random_natural_less_than.rs +++ b/malachite-nz/tests/natural/random/get_random_natural_less_than.rs @@ -6,35 +6,52 @@ // 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::Zero; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_random_natural_less_than; use malachite_nz::natural::Natural; use std::str::FromStr; fn get_random_natural_less_than_helper(limit: &str, out: &str) { - assert_eq!( - get_random_natural_less_than( - &mut random_primitive_ints(EXAMPLE_SEED), - &Natural::from_str(limit).unwrap() - ) - .to_string(), - out - ); + let mut xs = random_primitive_ints(EXAMPLE_SEED); + let xs = (0..10) + .map(|_| get_random_natural_less_than(&mut xs, &Natural::from_str(limit).unwrap())) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_natural_less_than() { - get_random_natural_less_than_helper("1", "0"); - get_random_natural_less_than_helper("10", "1"); - get_random_natural_less_than_helper("100", "87"); - get_random_natural_less_than_helper("1000", "881"); + get_random_natural_less_than_helper("1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_random_natural_less_than_helper("10", "[1, 7, 5, 7, 9, 2, 8, 2, 4, 6]"); + get_random_natural_less_than_helper("100", "[87, 93, 7, 84, 27, 46, 93, 22, 86, 1]"); + get_random_natural_less_than_helper("1000", "[881, 87, 93, 629, 519, 626, 360, 242, 491, 84]"); get_random_natural_less_than_helper( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000", - "65136961652069212043112615237392696010837604314202102958615643812057836484425634981051963\ - 29975541617", + "[6513696165206921204311261523739269601083760431420210295861564381205783648442563498105196\ + 329975541617, \ + 868400879467069938866982772480181142332366549281254507368280851531146621198387695461761814\ + 2446877811, \ + 454890116058063209121711848211479855802275293374032067837601343116564901989251772312271223\ + 8643735453, \ + 221953236727409585623978519825787712675415538807055958167887436471257145918881448806179877\ + 2042912434, \ + 156597062580980418852701766729202981599785596117178894442015894874216386954905163169649546\ + 2984128417, \ + 775809396529562140517641222093832263868653173407259880967133743504333426167140950839221651\ + 5440206577, \ + 194588045371630389938122892550032325836127322381120175893002672149553900804839171978848159\ + 3900827375, \ + 681710429818657256239982130308509711765427303233424706691965226432442255381734547395128615\ + 696717955, \ + 525885978270298534580002381561976404877189873292849476887431075456216366244793235854298324\ + 5431956916, \ + 314957843714266314102082575313210347468784454645937249947829551130804781109663224113983528\ + 7147185026]", ); } diff --git a/malachite-nz/tests/natural/random/get_random_natural_with_bits.rs b/malachite-nz/tests/natural/random/get_random_natural_with_bits.rs index 28ef36c27..6ff8f7ff9 100644 --- a/malachite-nz/tests/natural/random/get_random_natural_with_bits.rs +++ b/malachite-nz/tests/natural/random/get_random_natural_with_bits.rs @@ -6,28 +6,74 @@ // 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::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_random_natural_with_bits; fn get_random_natural_with_bits_helper(bits: u64, out: &str) { - assert_eq!( - get_random_natural_with_bits(&mut random_primitive_ints(EXAMPLE_SEED), bits).to_string(), - out - ); + let mut xs = random_primitive_ints(EXAMPLE_SEED); + let xs = (0..10) + .map(|_| get_random_natural_with_bits(&mut xs, bits)) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_natural_with_bits() { - get_random_natural_with_bits_helper(0, "0"); - get_random_natural_with_bits_helper(1, "1"); - get_random_natural_with_bits_helper(10, "881"); - get_random_natural_with_bits_helper(100, "976558340558744279591984426865"); + get_random_natural_with_bits_helper(0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_random_natural_with_bits_helper(1, "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); + get_random_natural_with_bits_helper(10, "[881, 599, 605, 629, 519, 1001, 626, 872, 754, 1003]"); + get_random_natural_with_bits_helper( + 100, + "[976558340558744279591984426865, 1210743526759830339060468402269, \ + 987622786528174742128034915847, 1028849241887437545987236408946, \ + 636224214690002338734404794610, 1084022137993299669433275842644, \ + 651260491393393331452592307118, 938596277659014096812502469654, \ + 1027696177399334210658775892715, 1215526897097077179887043345523]", + ); get_random_natural_with_bits_helper( 1000, - "987155559331138858373066802857294797227337039158487316682786744595637977633186240361413701\ - 0240679811389700642404293916880391529744438580436267309669605743557526364970431150933385398\ - 3656197605680428663668911754185572635377576510237140480985253354471771499012869776666692287\ - 34508013967448659203593727857" + "[9871555593311388583730668028572947972273370391584873166827867445956379776331862403614137\ + 010240679811389700642404293916880391529744438580436267309669605743557526364970431150933385\ + 398365619760568042866366891175418557263537757651023714048098525335447177149901286977666669\ + 228734508013967448659203593727857, \ + 791294226283400338116725266395415668811492351726967595517985462290683501988325067570154247\ + 916466497696906715377685810324362572568643782805454526919199743597748426287793605950177843\ + 400312249716517544116781742042345757038219051016833597591532327578014535369800683425719501\ + 1222552384008059606354106024683, \ + 603141122347678493875935496567523539943016200607299929590987513666029676151877700615600993\ + 558206489004992870361727816768285331691513429048943961969079262017872532249009221429690429\ + 173396464673970587747514162246269540847510994058348422653339211911977412158645139435582116\ + 2135683154777550054864806973191, \ + 918979157591718364955430394079794967293887473404422985188351315968507884008710649189160051\ + 696207222829134675903387190115731463781015558345121417040971370267174581281652951730760301\ + 188537459504910504772462880811654819707300024255167639013890736171444647445349859763886702\ + 2577615653562903750479807977377, \ + 647326991054871401446391652220147139977257585074930117822971968152242235080123828418477499\ + 122643194996280709533149340353864776491291597713840972420179000074772311437377760180051433\ + 385038047440481754027985595280436007381332471223783461841596113991149106848191431176197419\ + 2844525526720830095389487497409, \ + 949041077003843738114763478589507012307507968570578492234472107314902412716521187076156469\ + 160317707751627684700609080913827492307622771744874629743335821135555462576657380263807543\ + 487753886476772373626981873033661206968177922749550215130614548300918947578733522250796129\ + 5744371969372939814739027796839, \ + 989922815195092012407533508457902337326088523136116587955882587433938614841443439968917681\ + 506531942296074930018264941258097700513177676253997511008000381073449050985414240650516825\ + 818652374821129290720209582447241803904618161996066094314560522095909158341055892421259319\ + 6555994763897951379745163707947, \ + 560430875586881451021986079137268355719860392640168705312566874574524151511315309194440525\ + 432541907755646531766496361640227195372967955930947529029583706599432734589617900554403438\ + 972135775666804402920199247213229036374355559526777099281829864834361213138370127732279617\ + 7830548383897263545487627313816, \ + 607760857698629857675370920711285763610351243179869812617321508384537069997121877063755036\ + 502176965392609298699890321897240768662430762687034745512362659852305512122877940314598630\ + 179328920839572409651612938305899406030180626695355189902602551915007303361897784538043083\ + 9825515983752933214916509907962, \ + 104802773115609428879259254484528372112963320559423798212143117675970187076769475019659710\ + 589902898294520178185617889833116138928807499798445230962192076044779146948376974924138017\ + 275574706437699501177855375574899794972601656611168235082869924333910214914822287693744357\ + 49828269999407972362285090280006]", ); } diff --git a/malachite-nz/tests/natural/random/get_random_natural_with_up_to_bits.rs b/malachite-nz/tests/natural/random/get_random_natural_with_up_to_bits.rs index b48a64ef9..0f3162589 100644 --- a/malachite-nz/tests/natural/random/get_random_natural_with_up_to_bits.rs +++ b/malachite-nz/tests/natural/random/get_random_natural_with_up_to_bits.rs @@ -6,29 +6,77 @@ // 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::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_random_natural_with_up_to_bits; fn get_random_natural_with_up_to_bits_helper(bits: u64, out: &str) { - assert_eq!( - get_random_natural_with_up_to_bits(&mut random_primitive_ints(EXAMPLE_SEED), bits) - .to_string(), - out - ); + let mut xs = random_primitive_ints(EXAMPLE_SEED); + let xs = (0..10) + .map(|_| get_random_natural_with_up_to_bits(&mut xs, bits)) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_natural_with_up_to_bits() { - get_random_natural_with_up_to_bits_helper(0, "0"); - get_random_natural_with_up_to_bits_helper(1, "1"); - get_random_natural_with_up_to_bits_helper(10, "881"); - get_random_natural_with_up_to_bits_helper(100, "976558340558744279591984426865"); + get_random_natural_with_up_to_bits_helper(0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_random_natural_with_up_to_bits_helper(1, "[1, 1, 1, 1, 1, 1, 0, 0, 0, 1]"); + get_random_natural_with_up_to_bits_helper( + 10, + "[881, 87, 93, 629, 519, 1001, 626, 360, 242, 491]", + ); + get_random_natural_with_up_to_bits_helper( + 100, + "[976558340558744279591984426865, 576918226645715638312116799581, \ + 987622786528174742128034915847, 395023941773322845238884806258, \ + 636224214690002338734404794610, 450196837879184968684924239956, \ + 17435191279278630704240704430, 938596277659014096812502469654, \ + 1027696177399334210658775892715, 581701596982962479138691742835]", + ); get_random_natural_with_up_to_bits_helper( 1000, - "451401255738005197898854278327293891946634633305720512960911550410462452070718179114814511\ - 6162200520751727277816528182754455803315977010218275020882256456155559081083019035440674861\ - 0630885749971038892758146521810654725671239516399344653265522969157198643030481343955853985\ - 19592187655255240600759693169", + "[4514012557380051978988542783272938919466346333057205129609115504104624520707181791148145\ + 116162200520751727277816528182754455803315977010218275020882256456155559081083019035440674\ + 861063088574997103889275814652181065472567123951639934465326552296915719864303048134395585\ + 398519592187655255240600759693169, \ + 791294226283400338116725266395415668811492351726967595517985462290683501988325067570154247\ + 916466497696906715377685810324362572568643782805454526919199743597748426287793605950177843\ + 400312249716517544116781742042345757038219051016833597591532327578014535369800683425719501\ + 1222552384008059606354106024683, \ + 603141122347678493875935496567523539943016200607299929590987513666029676151877700615600993\ + 558206489004992870361727816768285331691513429048943961969079262017872532249009221429690429\ + 173396464673970587747514162246269540847510994058348422653339211911977412158645139435582116\ + 2135683154777550054864806973191, \ + 918979157591718364955430394079794967293887473404422985188351315968507884008710649189160051\ + 696207222829134675903387190115731463781015558345121417040971370267174581281652951730760301\ + 188537459504910504772462880811654819707300024255167639013890736171444647445349859763886702\ + 2577615653562903750479807977377, \ + 111572687461737740972179127690146234696555179222163314101096773967066709517655767171878309\ + 714795265932483373074372766941271203848445440692041743541444071334575583048636548630780379\ + 654784928883387856318877942956686828284269101285405503564398810138003378288367546849089036\ + 2629609700408636676786653462721, \ + 413286773410710077640550954059506107026805562717811688512596913129726887154053125829557279\ + 752469778687830348241832507501233919664776614723075400864600892395358734187916168714536489\ + 757500767919678475917874220709912027871114552811172256853417244447773219018909637923687746\ + 5529456143060746396136193762151, \ + 454168511601958351933320983927901432045386117283349784234007393248763089278975378722318492\ + 098684013232277593559488367845504127870331519232198282129265452333252322596673029101245772\ + 088399256264035393011101930123492624807554792057688136037363218242763429781232008094150936\ + 6341078937585757961142329673259, \ + 560430875586881451021986079137268355719860392640168705312566874574524151511315309194440525\ + 432541907755646531766496361640227195372967955930947529029583706599432734589617900554403438\ + 972135775666804402920199247213229036374355559526777099281829864834361213138370127732279617\ + 7830548383897263545487627313816, \ + 720065541054961972011583961812848583296488373271030088954463141993615444346538158171558470\ + 943290363288119622411137484846471960195846056652355166336277311121087837341367287653275764\ + 490758022824785119425052859821502269331172567569772316254052480618615748020739002109347009\ + 610600157440739796313675873274, \ + 512273427562960628318380020315282815848930799741471178399555982574526345205226688949997916\ + 491181053881404445397402324918567816645228840962653080743185831707594741095028537692109119\ + 025493945819901114069446103425248770628953196173304392551501939485956420588398992610335191\ + 9613354173095778943682256245318]", ); } diff --git a/malachite-nz/tests/natural/random/get_striped_random_natural_from_inclusive_range.rs b/malachite-nz/tests/natural/random/get_striped_random_natural_from_inclusive_range.rs new file mode 100644 index 000000000..038d0bad3 --- /dev/null +++ b/malachite-nz/tests/natural/random/get_striped_random_natural_from_inclusive_range.rs @@ -0,0 +1,118 @@ +// 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::random::striped::StripedBitSource; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; +use malachite_nz::natural::random::get_striped_random_natural_from_inclusive_range; +use malachite_nz::natural::Natural; +use std::str::FromStr; + +fn get_striped_random_natural_from_inclusive_range_helper( + m_numerator: u64, + m_denominator: u64, + a: &str, + b: &str, + out: &str, +) { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); + let xs = (0..10) + .map(|_| { + get_striped_random_natural_from_inclusive_range( + &mut bit_source, + Natural::from_str(a).unwrap(), + Natural::from_str(b).unwrap(), + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); +} + +#[test] +fn test_get_striped_random_natural_from_inclusive_range() { + get_striped_random_natural_from_inclusive_range_helper( + 2, + 1, + "0", + "0", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_striped_random_natural_from_inclusive_range_helper( + 2, + 1, + "1950", + "2023", + "[1950, 1971, 1990, 1962, 2018, 1972, 1952, 1999, 1989, 1987]", + ); + get_striped_random_natural_from_inclusive_range_helper( + 2, + 1, + "1000000", + "2000000", + "[1002694, 1403247, 1036052, 1001215, 1170335, 1510298, 1661478, 1012673, 1005113, \ + 1014065]", + ); + + get_striped_random_natural_from_inclusive_range_helper( + 10, + 1, + "0", + "0", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_striped_random_natural_from_inclusive_range_helper( + 10, + 1, + "1950", + "2023", + "[1950, 1951, 1983, 2016, 1950, 2020, 2016, 1951, 1950, 1983]", + ); + get_striped_random_natural_from_inclusive_range_helper( + 10, + 1, + "1000000", + "2000000", + "[1001471, 1056767, 1032199, 1000432, 1998848, 1040384, 1000000, 1574911, 1981967, \ + 1048574]", + ); + + get_striped_random_natural_from_inclusive_range_helper( + 11, + 10, + "0", + "0", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_striped_random_natural_from_inclusive_range_helper( + 11, + 10, + "1950", + "2023", + "[1962, 1962, 1972, 2019, 2019, 1962, 1962, 1986, 2005, 2005]", + ); + get_striped_random_natural_from_inclusive_range_helper( + 11, + 10, + "1000000", + "2000000", + "[1004885, 1718613, 1027925, 1004874, 1485482, 1397329, 1741994, 1011029, 1004885, \ + 1010346]", + ); +} + +#[test] +#[should_panic] +fn get_striped_random_natural_from_inclusive_range_fail_1() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); + get_striped_random_natural_from_inclusive_range( + &mut bit_source, + Natural::from(10u32), + Natural::from(9u32), + ); +} diff --git a/malachite-nz/tests/natural/random/get_striped_random_natural_from_range.rs b/malachite-nz/tests/natural/random/get_striped_random_natural_from_range.rs new file mode 100644 index 000000000..648ca03be --- /dev/null +++ b/malachite-nz/tests/natural/random/get_striped_random_natural_from_range.rs @@ -0,0 +1,117 @@ +// 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::random::striped::StripedBitSource; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; +use malachite_nz::natural::random::get_striped_random_natural_from_range; +use malachite_nz::natural::Natural; +use std::str::FromStr; + +fn get_striped_random_natural_from_range_helper( + m_numerator: u64, + m_denominator: u64, + a: &str, + b: &str, + out: &str, +) { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); + let xs = (0..10) + .map(|_| { + get_striped_random_natural_from_range( + &mut bit_source, + Natural::from_str(a).unwrap(), + Natural::from_str(b).unwrap(), + ) + }) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); +} + +#[test] +fn test_get_striped_random_natural_from_range() { + get_striped_random_natural_from_range_helper(2, 1, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_natural_from_range_helper( + 2, + 1, + "1950", + "2024", + "[1950, 1971, 1990, 1962, 2018, 1972, 1952, 1999, 1989, 1987]", + ); + get_striped_random_natural_from_range_helper( + 2, + 1, + "1000000", + "2000001", + "[1002694, 1403247, 1036052, 1001215, 1170335, 1510298, 1661478, 1012673, 1005113, \ + 1014065]", + ); + + get_striped_random_natural_from_range_helper(10, 1, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_natural_from_range_helper( + 10, + 1, + "1950", + "2024", + "[1950, 1951, 1983, 2016, 1950, 2020, 2016, 1951, 1950, 1983]", + ); + get_striped_random_natural_from_range_helper( + 10, + 1, + "1000000", + "2000001", + "[1001471, 1056767, 1032199, 1000432, 1998848, 1040384, 1000000, 1574911, 1981967, \ + 1048574]", + ); + + get_striped_random_natural_from_range_helper( + 11, + 10, + "0", + "1", + "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", + ); + get_striped_random_natural_from_range_helper( + 11, + 10, + "1950", + "2024", + "[1962, 1962, 1972, 2019, 2019, 1962, 1962, 1986, 2005, 2005]", + ); + get_striped_random_natural_from_range_helper( + 11, + 10, + "1000000", + "2000001", + "[1004885, 1718613, 1027925, 1004874, 1485482, 1397329, 1741994, 1011029, 1004885, \ + 1010346]", + ); +} + +#[test] +#[should_panic] +fn get_striped_random_natural_from_range_fail_1() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); + get_striped_random_natural_from_range( + &mut bit_source, + Natural::from(10u32), + Natural::from(9u32), + ); +} + +#[test] +#[should_panic] +fn get_striped_random_natural_from_range_fail_2() { + let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); + get_striped_random_natural_from_range( + &mut bit_source, + Natural::from(10u32), + Natural::from(10u32), + ); +} diff --git a/malachite-nz/tests/natural/random/get_striped_random_natural_with_bits.rs b/malachite-nz/tests/natural/random/get_striped_random_natural_with_bits.rs index f44d3cd9f..6ec382350 100644 --- a/malachite-nz/tests/natural/random/get_striped_random_natural_with_bits.rs +++ b/malachite-nz/tests/natural/random/get_striped_random_natural_with_bits.rs @@ -6,8 +6,10 @@ // 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::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_striped_random_natural_with_bits; fn get_striped_random_natural_with_bits_helper( @@ -17,53 +19,203 @@ fn get_striped_random_natural_with_bits_helper( out: &str, ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); - assert_eq!( - get_striped_random_natural_with_bits(&mut bit_source, bits).to_string(), - out - ); + let xs = (0..10) + .map(|_| get_striped_random_natural_with_bits(&mut bit_source, bits)) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_natural_with_bits() { - get_striped_random_natural_with_bits_helper(2, 1, 0, "0"); - get_striped_random_natural_with_bits_helper(2, 1, 1, "1"); - get_striped_random_natural_with_bits_helper(2, 1, 10, "716"); - get_striped_random_natural_with_bits_helper(2, 1, 100, "756308944479610176770360563916"); + get_striped_random_natural_with_bits_helper(2, 1, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_natural_with_bits_helper(2, 1, 1, "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); + get_striped_random_natural_with_bits_helper( + 2, + 1, + 10, + "[716, 684, 662, 763, 798, 829, 768, 732, 536, 541]", + ); + get_striped_random_natural_with_bits_helper( + 2, + 1, + 100, + "[756308944479610176770360563916, 1145718678910746691112769802930, \ + 1080305256857112995037586132048, 807717805879357681845918965159, \ + 1215845349850185248466264185684, 822948728534233460050112643373, \ + 955700757257715004518140113132, 832461439248077413553063350320, \ + 1242643020761038901934578711610, 1122137987246906014371413743505]", + ); get_striped_random_natural_with_bits_helper( 2, 1, 1000, - "106603640182258658206083103566270645700512417336938536408951275387366895485449865320133052\ - 9188610070039476426288535963559977582497470497937854727434805905648395790056513373361685117\ - 0447014047433756921281989047837597391841613716389932684381637088728893046979209497320344797\ - 581420099450165301088751016140", + "[1066036401822586582060831035662706457005124173369385364089512753873668954854498653201330\ + 529188610070039476426288535963559977582497470497937854727434805905648395790056513373361685\ + 117044701404743375692128198904783759739184161371638993268438163708872889304697920949732034\ + 4797581420099450165301088751016140, \ + 987176835967471470631208736450711102640000526855618567465986968908194747303665548783151326\ + 849739186186452340671673297796771266911335225612017707433164734645560965513055402080032340\ + 135474058189238938067890211197448581037553663122597099692488328028757994359299305393973140\ + 7925926109130072336312534438574, \ + 568651645319898625478110927429560819026449278119016593712297801674333004668766652853597774\ + 772681158919761337797730830161503881200296844963400983419113636067755214296565242049691883\ + 922630951084279967424027354828765778295400023859140245298770234805718721051701730000306553\ + 5144184078571910290480368694380, \ + 758830907466434071959666860937945102677771418528458236060516770128040285772163826421306107\ + 069853863334698116336945744601463639747199523669413845254638599625980012214050809846459478\ + 559098934176586233093238956124608709775991202493060441152475782277782012828793855484827036\ + 1411929636489612968071552336405, \ + 980856434133966113634431860230323947967355946268495564634504680787571319483353753543014805\ + 474807358240303253563585951883147532327134463459185707026951902911405729653418676374715955\ + 691096425012748194433199980744016228705422729019166704577441683479974798193714636957924636\ + 2973260186276362799319175133568, \ + 894303548113446750904572507746592793549624231872528102587605556722756026081514290865978856\ + 949605256419586901475129581474267478481820707346973965338715875069463779465480362052962715\ + 102197582459759242950488814694110771040964546445427112279563255714907257699939184423978433\ + 0215727680884042630165644025099, \ + 974492070270890205196098593733513997055807419178419835560661240335358848519651158952303927\ + 871434236017718573182013896425860901259995476236242988456734111274812403199906058941973460\ + 877801690192132645453156214170274198928980236695132799825665804217976367252593838779965803\ + 0607916391896384659714182950628, \ + 645130850234339503642007350857138479917399859387095109454794616985938391311231126744661800\ + 420543794746031491748493862132931262497139684250480230073784453843645088983023718012240528\ + 683824553139343195888019854863909746543574579361265915812174560716242126991285521565613433\ + 2466523138255580920562084028294, \ + 639103284871251403821872209988025331131792409726095776075819070688817857426736537831222024\ + 179652645603869247406404689998157064676469146016517502338483799149248172262554878327272758\ + 174240821091933100132108595935722179262833993962469175972706639648644071967476854878243149\ + 4649776909489103783746916780024, \ + 104643900952018601215342460716610794174551332701220396118082370352258784597041601116915384\ + 664642853384078500349464320717455867749180262488843336424123164153150026841959758704744253\ + 756151269545080362145067323770739682710146919991724449298137503388491656477667755306189744\ + 24803845757396271996047726290589]", ); - get_striped_random_natural_with_bits_helper(10, 1, 0, "0"); - get_striped_random_natural_with_bits_helper(10, 1, 1, "1"); - get_striped_random_natural_with_bits_helper(10, 1, 10, "1016"); - get_striped_random_natural_with_bits_helper(10, 1, 100, "950737912392312175425017102328"); + get_striped_random_natural_with_bits_helper(10, 1, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_natural_with_bits_helper(10, 1, 1, "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); + get_striped_random_natural_with_bits_helper( + 10, + 1, + 10, + "[1016, 992, 1016, 767, 512, 513, 1020, 512, 1016, 1023]", + ); + get_striped_random_natural_with_bits_helper( + 10, + 1, + 100, + "[950737912392312175425017102328, 1109194416875305772521657204608, \ + 648685415698526143125877948414, 1248153346840921551430087606303, \ + 831891172891058554467585867776, 1267650600228229401359297740927, \ + 950739156735808420047682273024, 638776758039873373851420326912, \ + 643690285327603686643074121664, 671543785829629858305590427647]", + ); get_striped_random_natural_with_bits_helper( 10, 1, 1000, - "535816573811028114746842915666558214499888135362831834387264695681575119799994689757287827\ - 8363096783827886911589242856640635533315179867213030979090927223140806482585564866175368333\ - 5984663366032716099765341041735279416091316510062421684707527426682687794404521538192109445\ - 28718553525957103310205894648", + "[5358165738110281147468429156665582144998881353628318343872646956815751197999946897572878\ + 278363096783827886911589242856640635533315179867213030979090927223140806482585564866175368\ + 333598466336603271609976534104173527941609131651006242168470752742668268779440452153819210\ + 944528718553525957103310205894648, \ + 539935796843008525931501938016824825731989695976128079798746287896348626759778818662810517\ + 524977343980885794548702209431866052161353917750190601629912511180434696813340457173208570\ + 976449234006368601336057069020362424176301595236556802947569224730136326560449690301955186\ + 3255474664584713584582999408640, \ + 535754303694423899076935129343771055050259990680670440133208286589122737827790634967047773\ + 700260648071343420497642383540669384404571214562700313160956733565914399913133443167360146\ + 252087697860065532691284023259655546679447897828373290595492357586809871031621268591800199\ + 5164641448720709752408544641022, \ + 535815617678664673230583609293711626429039758128419938980167626717612472897746291934554185\ + 557830869500024824265898785919682260921341384664997061547297321382527299885697935410512118\ + 522746192907474498033052134885264654751340612094587360238549546738016850498598238219826282\ + 5015681391047050153768125472767, \ + 100656671761770967200809514408313411282491427879094391861152015262204431791194203727185921\ + 026045038825035836776620646775627513583957795766207833861462739511509698818541011638004365\ + 409989389341031372058994101918102834059849507520841606970888386863725907172131052360271284\ + 55992101445905914436525739998208, \ + 107149228544600635260212788419695526657434400429968676165634060825808436991969085650247279\ + 650596133663598434482129668133099616635115467318010721467086518060004035373781135234642383\ + 205702114144671525516391055691812453033688242812694582953965743513229924054172419365064495\ + 42173396641692237011907449425727, \ + 107150860693727448661794856915575585277857852731679120989819290845002348669070050613296455\ + 734254692011706809018756806353158106462995138380031851002523766291502961737781576247555759\ + 035185454502873048780305065230433793569807065690804749332353542464565681262222119583879742\ + 48405282741635132994030678311166, \ + 107150835221766756970390016554040088032382955997319930334779105385220088376881426554895494\ + 540316762324972302835401791427607201669829855912974990784820455466307137336628823875387612\ + 135057991945407277136587896193153151600433435164863822917290693842788118252951172684773421\ + 70526384435574180443755489763328, \ + 535754329539033410731721563380478204940555300525204412489285381291927939025074977709123312\ + 566899344374925407384165980119188647505571183538659634788083559269291976584227032503722306\ + 929007576563288991617997079930222315375169710335488132792623698751814518487754242895518611\ + 5084271519939681346646991441912, \ + 535882021406206416670177596158366769032342285663637541146888579315644330411450606808875554\ + 132489833818740595777819456634963853487245325624796744100983558326561831449646070534648278\ + 476260874658721825904285846269922085259057263667571525921657161024153045937468235049728709\ + 2438657975290976181526386966515]", ); - get_striped_random_natural_with_bits_helper(11, 10, 0, "0"); - get_striped_random_natural_with_bits_helper(11, 10, 1, "1"); - get_striped_random_natural_with_bits_helper(11, 10, 10, "682"); - get_striped_random_natural_with_bits_helper(11, 10, 100, "1063803140432100403291953916586"); + get_striped_random_natural_with_bits_helper(11, 10, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_natural_with_bits_helper(11, 10, 1, "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); + get_striped_random_natural_with_bits_helper( + 11, + 10, + 10, + "[682, 842, 668, 853, 862, 853, 850, 852, 682, 853]", + ); + get_striped_random_natural_with_bits_helper( + 11, + 10, + 100, + "[1063803140432100403291953916586, 739462850133133817539732346028, \ + 1056478660679155688751767049562, 848401573590247656481079600469, \ + 1056375500189999764883937602218, 1053067879147533365448711514965, \ + 1056381847001601296578889995602, 1056377112103581910626871170386, \ + 1056375600983290506811020749482, 845074597043259864052961293645]", + ); get_striped_random_natural_with_bits_helper( 11, 10, 1000, - "892923796723010326289072282443350944961207977741857279306817374354286093126437953655146711\ - 1265297962015834728928882271330897607870697615306329567845176199860105934578611877105699420\ - 3611125967040868655526771507387733287135058353581608090744020753841394314031678704513672424\ - 30551069260362892051555117738", + "[8929237967230103262890722824433509449612079777418572793068173743542860931264379536551467\ + 111265297962015834728928882271330897607870697615306329567845176199860105934578611877105699\ + 420361112596704086865552677150738773328713505835358160809074402075384139431403167870451367\ + 242430551069260362892051555117738, \ + 848277807033155886730751542077297974149911088007915913764780956681936845102711155704193533\ + 266937165754352296914790126319848647014472476095156708927462195514313159177074602462717519\ + 349357763529281370152392669738095746762025827796955823134607626270938290494658223672222158\ + 9872232895273605128836243696298, \ + 622256279237828710101116559940449011192577108759402537346355985105564415773311644474958256\ + 085364963664247523046669028723331763456095716282707295047182502032978485452383285604942655\ + 047145606332906731031323587018683298574131563687284576221383367233664334964305026386536472\ + 7120990168388537700787439359354, \ + 893011037585013007271439602956526972024707806627477311937832595287305307343362049808812372\ + 867697432889627779970803417048478482882370003668394928455851950345620310470241544275541047\ + 354242013397873563064543296718018003131524951605807454956556860189105716328731797732674596\ + 4570601733436095071743763633493, \ + 714337697986576114077307239016734314472779437227875536493177724277496357242071140467095878\ + 368847036684840951410204114568419486398409897184525378525275704002748768137539106304824083\ + 362036096433222952552023855753638427465829477635653011302870027782444701974201225532101310\ + 2549204865443174861708377533098, \ + 717129479744396200344184597459955775324063665344347322215427784911546292557185067124997476\ + 300110608871594211005211148242437189627028361260715625731282067311558916993444457603008618\ + 146383526538195175746094394556394170673628321139601154519945289775172095900192878319082649\ + 5453320605634381639129320740181, \ + 712943875305246933549449117163766092515737565613814773068912395757448666817082911895780847\ + 326837660502284270497684787917665238088905925731656976408461765235806743263267139181463148\ + 004431439157535144190810911719314309577264591245575456701925751321667869578190443322813012\ + 0138648732293712628634064954698, \ + 892880942227156526968373917452622274287516410008666161523034951090805186930790904719943631\ + 023279485226392520031870194759074725254789440380488049235603947036487803727696933564597255\ + 812777037968411285945062427246430458697274335300861633278805179074880855146539152265137509\ + 2760519788829492124624878217898, \ + 892945641881431108631973304223007197865627901236713933938944990987439087863487393850263204\ + 926847861908008259701418716838801341585797849737533079786960203576656895262092537802767877\ + 046297885380150024466056272755057031975057975145576287997024449574764798500660830182847012\ + 5379718921376291465124979747542, \ + 712949327932932700218621033804526985196291897563252301818755627637478824989877935042325873\ + 291167136650626866176302303072095225803612799473142905508378017958979111144644566257625076\ + 950893722575069628745776862688326045350363911106097574031678159885821711577125514250680212\ + 9840859041388985930050461586805]", ); } diff --git a/malachite-nz/tests/natural/random/get_striped_random_natural_with_up_to_bits.rs b/malachite-nz/tests/natural/random/get_striped_random_natural_with_up_to_bits.rs index f8d5d678c..a5b32d6b6 100644 --- a/malachite-nz/tests/natural/random/get_striped_random_natural_with_up_to_bits.rs +++ b/malachite-nz/tests/natural/random/get_striped_random_natural_with_up_to_bits.rs @@ -6,8 +6,10 @@ // 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::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; +use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_striped_random_natural_with_up_to_bits; fn get_striped_random_natural_with_up_to_bits_helper( @@ -17,58 +19,203 @@ fn get_striped_random_natural_with_up_to_bits_helper( out: &str, ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); - assert_eq!( - get_striped_random_natural_with_up_to_bits(&mut bit_source, bits).to_string(), - out - ); + let xs = (0..10) + .map(|_| get_striped_random_natural_with_up_to_bits(&mut bit_source, bits)) + .collect_vec(); + assert_eq!(xs.to_debug_string(), out); } #[test] -fn test_get_random_natural_with_up_to_bits() { - get_striped_random_natural_with_up_to_bits_helper(2, 1, 0, "0"); - get_striped_random_natural_with_up_to_bits_helper(2, 1, 1, "0"); - get_striped_random_natural_with_up_to_bits_helper(2, 1, 10, "204"); - get_striped_random_natural_with_up_to_bits_helper(2, 1, 100, "756308944479610176770360563916"); +fn test_get_striped_random_natural_with_up_to_bits() { + get_striped_random_natural_with_up_to_bits_helper(2, 1, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_natural_with_up_to_bits_helper(2, 1, 1, "[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]"); + get_striped_random_natural_with_up_to_bits_helper( + 2, + 1, + 10, + "[204, 684, 662, 251, 286, 317, 768, 732, 24, 541]", + ); + get_striped_random_natural_with_up_to_bits_helper( + 2, + 1, + 100, + "[756308944479610176770360563916, 511893378796631990364418200242, \ + 446479956742998294289234529360, 173892505765242981097567362471, \ + 1215845349850185248466264185684, 189123428420118759301761040685, \ + 955700757257715004518140113132, 832461439248077413553063350320, \ + 1242643020761038901934578711610, 488312687132791313623062140817]", + ); get_striped_random_natural_with_up_to_bits_helper( 2, 1, 1000, - "530282098229452921586618511132705551724421767516618560367637559688493429292030591954731339\ - 7807621409756790898297593901473840098546243409160554985560709769081990616677721618124140633\ - 1444828618628179441909125246001056008709800170061531016096640501974357613809706540492609673\ - 66504273137971882485916981452", + "[5302820982294529215866185111327055517244217675166185603676375596884934292920305919547313\ + 397807621409756790898297593901473840098546243409160554985560709769081990616677721618124140\ + 633144482861862817944190912524600105600870980017006153101609664050197435761380970654049260\ + 967366504273137971882485916981452, \ + 451422532374337810156996211920710197359298121002851763744111774723019221741197487536552137\ + 441891257122655004212896724384177694268489068590218478554429805905364237124314190530761286\ + 405220939632145040358782558873699401940490293184219141415291024175612265799475421066864757\ + 7711010282817878917709700403886, \ + 328973417267649650038984028995599137457468722662497899904226074891574791062985916069985853\ + 648332298559640013389542567489103085574506879416017545403787073275584859078240305004208301\ + 923778325271860697149197025050165991983366539207622870215729309525729924918778456731981704\ + 929268252259716871877534659692, \ + 758830907466434071959666860937945102677771418528458236060516770128040285772163826421306107\ + 069853863334698116336945744601463639747199523669413845254638599625980012214050809846459478\ + 559098934176586233093238956124608709775991202493060441152475782277782012828793855484827036\ + 1411929636489612968071552336405, \ + 445102130540832453160219335700323042686653540415728760912629486602395793920885692296415616\ + 066959429176505917104809378470553959684288306437386478148216974171209001264677464825444901\ + 960843306455654296724092328420267049608359359080788746300244379626829069633890752630816253\ + 2758344359964169380716341098880, \ + 358549244520313090430359983216591888268921826019761298865730362537580500519046229619379667\ + 541757327355789565016353008061673905838974550325174736459980946329267051076739150503691661\ + 371944463902665345241381162370361591943901176507049154002365951861761529140115300096870050\ + 0000811854571849211562809990411, \ + 438737766677756544721886069203513091775105013325653031838786046150183322957183097705704738\ + 463586306953921236723237323013267328617149319214443759577999182534615674811164847392702407\ + 147548571635038747744048561846525019831916866756754841548468500364830638692769954452857420\ + 0393000565584191241111348915940, \ + 645130850234339503642007350857138479917399859387095109454794616985938391311231126744661800\ + 420543794746031491748493862132931262497139684250480230073784453843645088983023718012240528\ + 683824553139343195888019854863909746543574579361265915812174560716242126991285521565613433\ + 2466523138255580920562084028294, \ + 103348981278117743347659685458024425851090003873328972353943876503642331864268476584622834\ + 771804716540071910947628116585563492033622988994718273459748870409051443873813666778001704\ + 443987702534839202423000943611973000165770624024091217695509335795498343407652970551134766\ + 4434861083176910365144082745336, \ + 510684705927052351679212082636107036464810921159437157458948509337412320407947949922554657\ + 238580604776987667035866633761965104848956467866634135362496712791303540030856375498171483\ + 831259576893709723741565585383647648004405829978866534704177730031770836216853668734789059\ + 4588929931084078577444892255901]", ); - get_striped_random_natural_with_up_to_bits_helper(10, 1, 0, "0"); - get_striped_random_natural_with_up_to_bits_helper(10, 1, 1, "0"); - get_striped_random_natural_with_up_to_bits_helper(10, 1, 10, "1016"); - get_striped_random_natural_with_up_to_bits_helper(10, 1, 100, "316912612278197474676665499640"); + get_striped_random_natural_with_up_to_bits_helper(10, 1, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_natural_with_up_to_bits_helper(10, 1, 1, "[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]"); + get_striped_random_natural_with_up_to_bits_helper( + 10, + 1, + 10, + "[1016, 992, 1016, 255, 0, 1, 1020, 0, 1016, 1023]", + ); + get_striped_random_natural_with_up_to_bits_helper( + 10, + 1, + 100, + "[316912612278197474676665499640, 1109194416875305772521657204608, \ + 14860115584411442377526345726, 1248153346840921551430087606303, \ + 198065872776943853719234265088, 1267650600228229401359297740927, \ + 950739156735808420047682273024, 638776758039873373851420326912, \ + 9864985213488985894722518976, 37718485715515157557238824959]", + ); get_striped_random_natural_with_up_to_bits_helper( 10, 1, 1000, - "622702178944542726303911365573092191857295100650306653895014963995942375266285106886384284\ - 6174931899135470014771225146998068867182969950386903035779357388391986981527506826577962959\ - 3515103233263288545758093603615063849795162246258569877970413681149384221331054812711431380\ - 2727213763684707371859960", + "[6227021789445427263039113655730921918572951006503066538950149639959423752662851068863842\ + 846174931899135470014771225146998068867182969950386903035779357388391986981527506826577962\ + 959351510323326328854575809360361506384979516224625856987797041368114938422133105481271143\ + 13802727213763684707371859960, \ + 418149324987486545728941348682392045128729012336127607687109371117310119731075741621132811\ + 712941491708845808992563601927247951850776072839137275117758244023796842459924562393751724\ + 619611544927470362694941669661324507923822529817884467037192087699059800062580597484680330\ + 40558838272520165980165373952, \ + 101290238602722604813770149769557584827903636411333092403947212265322573720448584292412719\ + 007546084038865810128075811761725057540901084282221804825717671524392231618089092521834579\ + 302971634982176370935906367582384527889995332318295053733664142471797384264691816494972562\ + 2408516333805710606334, \ + 613140855310127563710847637107211483373522756531352582924325324369473352782306879549961499\ + 829404362274878071222125070886882784952276431978326685623926423305714969567238612410647924\ + 930743503806003239444825615154756542772421562094019613522428848711219387743538927178994800\ + 765564734856735165291438079, \ + 100656671761770967200809514408313411282491427879094391861152015262204431791194203727185921\ + 026045038825035836776620646775627513583957795766207833861462739511509698818541011638004365\ + 409989389341031372058994101918102834059849507520841606970888386863725907172131052360271284\ + 55992101445905914436525739998208, \ + 107149228544600635260212788419695526657434400429968676165634060825808436991969085650247279\ + 650596133663598434482129668133099616635115467318010721467086518060004035373781135234642383\ + 205702114144671525516391055691812453033688242812694582953965743513229924054172419365064495\ + 42173396641692237011907449425727, \ + 107150860693727448661794856915575585277857852731679120989819290845002348669070050613296455\ + 734254692011706809018756806353158106462995138380031851002523766291502961737781576247555759\ + 035185454502873048780305065230433793569807065690804749332353542464565681262222119583879742\ + 48405282741635132994030678311166, \ + 107150835221766756970390016554040088032382955997319930334779105385220088376881426554895494\ + 540316762324972302835401791427607201669829855912974990784820455466307137336628823875387612\ + 135057991945407277136587896193153151600433435164863822917290693842788118252951172684773421\ + 70526384435574180443755489763328, \ + 259458997502575090388504772996598528946724376087674101871067524134626069164625241231590514\ + 153111280709253894067065950748627250265168604059093486305290952481954858209544512531987544\ + 580061950939088894276064731362781063403971101745154263948986687899279303585684102284869355\ + 693627487928044157407224, \ + 127717813072756195965071628365863751639879810870737425013385130468804848982545562276364724\ + 641904754943259319042883222370280844399168602997515222248629586365103060904858985377224746\ + 007756101627928195178193946172906161993893729193567644459857171007317377644350722620326222\ + 3742148978782762923552931827]", ); - get_striped_random_natural_with_up_to_bits_helper(11, 10, 0, "0"); - get_striped_random_natural_with_up_to_bits_helper(11, 10, 1, "0"); - get_striped_random_natural_with_up_to_bits_helper(11, 10, 10, "682"); + get_striped_random_natural_with_up_to_bits_helper(11, 10, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); + get_striped_random_natural_with_up_to_bits_helper(11, 10, 1, "[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]"); + get_striped_random_natural_with_up_to_bits_helper( + 11, + 10, + 10, + "[682, 842, 668, 341, 350, 341, 338, 340, 682, 341]", + ); get_striped_random_natural_with_up_to_bits_helper( 11, 10, 100, - "1063803140432100403291953916586", + "[1063803140432100403291953916586, 739462850133133817539732346028, \ + 422653360565040988003415446874, 848401573590247656481079600469, \ + 422550200075885064135585999530, 419242579033418664700359912277, \ + 422556546887486595830538392914, 422551811989467209878519567698, \ + 422550300869175806062669146794, 845074597043259864052961293645]", ); get_striped_random_natural_with_up_to_bits_helper( 11, 10, 1000, - "357169493129876665814859757913350039680505571889090475584942180169110567563969892408547521\ - 7186818671377861364341116537204961881442236045088337279057826912458138650691199761612988883\ - 0585814111331478884616006275012815377428721359743812263024290368526821458049290271802834122\ - 15635242948169473448721083050", + "[3571694931298766658148597579133500396805055718890904755849421801691105675639698924085475\ + 217186818671377861364341116537204961881442236045088337279057826912458138650691199761612988\ + 883058581411133147888461600627501281537742872135974381226302429036852682145804929027180283\ + 412215635242948169473448721083050, \ + 312523503440022226256539017547297068869208682155149110042905762496761319540243094457594343\ + 859089236690554960456013552907255074371626319073357480048727266774116430788333390913446465\ + 619104644972187472443285017414346567664962457858577864857410322417792561934834339345113775\ + 9657317068961411710233409661610, \ + 865019756446950496269040354104481059118747029066357336244807909203888902108435832283590666\ + 775170346004501865878924553107381908132495592609080661684475732927817570636420740556716013\ + 168924877758128333222159346949341194770681937489066179441860633805186064044811420594280896\ + 906074342076344282184605324666, \ + 893011037585013007271439602956526972024707806627477311937832595287305307343362049808812372\ + 867697432889627779970803417048478482882370003668394928455851950345620310470241544275541047\ + 354242013397873563064543296718018003131524951605807454956556860189105716328731797732674596\ + 4570601733436095071743763633493, \ + 714337697986576114077307239016734314472779437227875536493177724277496357242071140467095878\ + 368847036684840951410204114568419486398409897184525378525275704002748768137539106304824083\ + 362036096433222952552023855753638427465829477635653011302870027782444701974201225532101310\ + 2549204865443174861708377533098, \ + 717129479744396200344184597459955775324063665344347322215427784911546292557185067124997476\ + 300110608871594211005211148242437189627028361260715625731282067311558916993444457603008618\ + 146383526538195175746094394556394170673628321139601154519945289775172095900192878319082649\ + 5453320605634381639129320740181, \ + 712943875305246933549449117163766092515737565613814773068912395757448666817082911895780847\ + 326837660502284270497684787917665238088905925731656976408461765235806743263267139181463148\ + 004431439157535144190810911719314309577264591245575456701925751321667869578190443322813012\ + 0138648732293712628634064954698, \ + 892880942227156526968373917452622274287516410008666161523034951090805186930790904719943631\ + 023279485226392520031870194759074725254789440380488049235603947036487803727696933564597255\ + 812777037968411285945062427246430458697274335300861633278805179074880855146539152265137509\ + 2760519788829492124624878217898, \ + 357191338288297448157760779693006292584925495383947130217069796802263562301019332603664015\ + 518999932844210923242642143426207768942951692715733850908225274836460166873351326253496823\ + 316044766823056126756948620431307852877994605207198329719827145721619069940836945855738629\ + 5164803095064098046522145712854, \ + 712949327932932700218621033804526985196291897563252301818755627637478824989877935042325873\ + 291167136650626866176302303072095225803612799473142905508378017958979111144644566257625076\ + 950893722575069628745776862688326045350363911106097574031678159885821711577125514250680212\ + 9840859041388985930050461586805]", ); } diff --git a/malachite-q/Cargo.toml b/malachite-q/Cargo.toml index 25540bf5f..848a32b60 100644 --- a/malachite-q/Cargo.toml +++ b/malachite-q/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "malachite-q" -version = "0.4.15" +version = "0.4.16" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true @@ -22,8 +22,8 @@ path = "src/bin.rs" [dependencies] itertools = { version = "0.11.0", default-features = false, features = ["use_alloc"] } -malachite-base = { version = "0.4.15", default-features = false } -malachite-nz = { version = "0.4.15", default-features = false } +malachite-base = { version = "0.4.16", default-features = false } +malachite-nz = { version = "0.4.16", default-features = false } serde = { version = "1.0.188", optional = true, default-features = false, features = ["alloc", "derive"] } serde_json = { version = "1.0.105", optional = true } diff --git a/malachite-q/src/arithmetic/log_base.rs b/malachite-q/src/arithmetic/log_base.rs index 928b644be..5e99edf3b 100644 --- a/malachite-q/src/arithmetic/log_base.rs +++ b/malachite-q/src/arithmetic/log_base.rs @@ -30,7 +30,7 @@ fn approx_log_helper(x: &Rational) -> f64 { impl Rational { /// Calculates the approximate natural logarithm of a positive [`Rational`]. /// - /// $f(x) = (1+\epsilon)(\log x)$, where $|\epsilon| < 2^{-52}.$ + /// $f(x) = (1+\varepsilon)(\log x)$, where $|\varepsilon| < 2^{-52}.$ /// /// # Worst-case complexity /// $T(n) = O(n)$ diff --git a/malachite-q/src/conversion/string/from_sci_string.rs b/malachite-q/src/conversion/string/from_sci_string.rs index 50e3e1d02..6629016b5 100644 --- a/malachite-q/src/conversion/string/from_sci_string.rs +++ b/malachite-q/src/conversion/string/from_sci_string.rs @@ -125,9 +125,9 @@ impl Rational { /// and the literal value of the string (as parsed by /// [`from_sci_string`](Rational::from_sci_string)) is $q$, and the implied scale is $s$ /// (meaning $s$ digits are provided after the point; if the string is `"123.456"`, then $s$ is - /// 3). Then this function computes $\epsilon = b^{-s}/2$ and finds the simplest [`Rational`] in - /// the closed interval $[q - \epsilon, q + \epsilon]$. The simplest [`Rational`] is the one - /// with minimal denominator; if there are multiple such [`Rational`]s, the one with the + /// 3). Then this function computes $\varepsilon = b^{-s}/2$ and finds the simplest [`Rational`] + /// in the closed interval $[q - \varepsilon, q + \varepsilon]$. The simplest [`Rational`] is + /// the one with minimal denominator; if there are multiple such [`Rational`]s, the one with the /// smallest absolute numerator is chosen. /// /// The following discussion assumes base 10. @@ -214,8 +214,8 @@ impl Rational { /// Here's a more precise description of the function's behavior. Suppose that the literal value /// of the string (as parsed by [`from_sci_string`](Rational::from_sci_string)) is $q$, and the /// implied scale is $s$ (meaning $s$ digits are provided after the point; if the string is - /// `"123.456"`, then $s$ is 3). Then this function computes $\epsilon = 10^{-s}/2$ and finds - /// the simplest [`Rational`] in the closed interval $[q - \epsilon, q + \epsilon]$. The + /// `"123.456"`, then $s$ is 3). Then this function computes $\varepsilon = 10^{-s}/2$ and finds + /// the simplest [`Rational`] in the closed interval $[q - \varepsilon, q + \varepsilon]$. The /// simplest [`Rational`] is the one with minimal denominator; if there are multiple such /// [`Rational`]s, the one with the smallest absolute numerator is chosen. /// diff --git a/malachite-q/src/random/mod.rs b/malachite-q/src/random/mod.rs index 614111a63..d74223aea 100644 --- a/malachite-q/src/random/mod.rs +++ b/malachite-q/src/random/mod.rs @@ -22,15 +22,18 @@ use malachite_base::num::logic::traits::SignificantBits; use malachite_base::num::random::geometric::{ geometric_random_unsigneds, GeometricRandomNaturalValues, }; +use malachite_base::num::random::striped::StripedBitSource; use malachite_base::num::random::{ - random_primitive_ints, variable_range_generator, RandomPrimitiveInts, VariableRangeGenerator, + random_primitive_ints, RandomPrimitiveInts, VariableRangeGenerator, }; use malachite_base::random::Seed; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::random::{ get_random_integer_from_range_to_infinity, get_random_integer_from_range_to_negative_infinity, - random_integer_range, random_integer_range_to_infinity, - random_integer_range_to_negative_infinity, RandomIntegerRange, RandomIntegerRangeToInfinity, + get_striped_random_integer_from_range_to_infinity, + get_striped_random_integer_from_range_to_negative_infinity, random_integer_range, + random_integer_range_to_infinity, random_integer_range_to_negative_infinity, + RandomIntegerRange, RandomIntegerRangeToInfinity, }; use malachite_nz::integer::Integer; use malachite_nz::natural::random::{ @@ -391,8 +394,7 @@ pub fn random_rationals( /// /// The output length is infinite. /// -/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information -/// about generating striped random numbers. +/// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ @@ -447,8 +449,7 @@ pub fn striped_random_positive_rationals( /// /// The output length is infinite. /// -/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information -/// about generating striped random numbers. +/// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ @@ -512,8 +513,7 @@ pub fn striped_random_non_negative_rationals( /// /// The output length is infinite. /// -/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information -/// about generating striped random numbers. +/// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ @@ -570,8 +570,7 @@ pub fn striped_random_negative_rationals( /// /// The output length is infinite. /// -/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information -/// about generating striped random numbers. +/// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ @@ -626,8 +625,7 @@ pub fn striped_random_nonzero_rationals( /// /// The output length is infinite. /// -/// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information -/// about generating striped random numbers. +/// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ @@ -1073,7 +1071,7 @@ pub fn random_rational_range_to_infinity( RandomRationalRangeToInfinity { a, limbs: random_primitive_ints(seed.fork("limbs")), - range_generator: variable_range_generator(seed.fork("range generator")), + range_generator: VariableRangeGenerator::new(seed.fork("range generator")), mean_bits_numerator, mean_bits_denominator, denominators: random_positive_naturals( @@ -1175,7 +1173,7 @@ pub fn random_rational_range_to_negative_infinity( RandomRationalRangeToNegativeInfinity { a, limbs: random_primitive_ints(seed.fork("limbs")), - range_generator: variable_range_generator(seed.fork("range generator")), + range_generator: VariableRangeGenerator::new(seed.fork("range generator")), mean_bits_numerator, mean_bits_denominator, denominators: random_positive_naturals( @@ -1459,3 +1457,239 @@ pub fn random_rational_inclusive_range( ), }) } + +/// Generates striped random [`Rational`]s greater than or equal to a lower bound. See +/// [`striped_random_rational_range_to_infinity`] for more details. +#[derive(Clone, Debug)] +pub struct StripedRandomRationalRangeToInfinity { + a: Rational, + xs: StripedBitSource, + range_generator: VariableRangeGenerator, + mean_bits_numerator: u64, + mean_bits_denominator: u64, + denominators: StripedRandomNaturals>, +} + +impl Iterator for StripedRandomRationalRangeToInfinity { + type Item = Rational; + + fn next(&mut self) -> Option { + let d = self.denominators.next().unwrap(); + let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Ceiling).0; + let (numerator, denominator) = (Rational::from(d.significant_bits()) + + Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator)) + .into_numerator_and_denominator(); + let numerator = u64::exact_from(&numerator); + let denominator = u64::exact_from(&denominator); + loop { + let n = get_striped_random_integer_from_range_to_infinity( + &mut self.xs, + &mut self.range_generator, + numerator_bound.clone(), + numerator, + denominator, + ); + if n.unsigned_abs_ref().coprime_with(&d) { + return Some(Rational { + sign: n >= 0, + numerator: n.unsigned_abs(), + denominator: d, + }); + } + } + } +} + +/// Generates striped random [`Rational`]s greater than or equal to a lower bound $a$. +/// +/// The actual numerator and denominator bit lengths are chosen from a geometric distribution with +/// mean $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than +/// `1`. A striped bit sequence with the given stripe parameter is generated and truncated at the +/// bit lengths to produce the numerators and denominators. The highest bits are forced to be `1`. +/// Finally, the [`Rational`] is reduced. +/// +/// The output length is infinite. +/// +/// See [`StripedBitSource`] for information about generating striped random numbers. +/// +/// # Expected complexity per iteration +/// $T(n) = O(n (\log n)^2 \log\log n)$ +/// +/// $M(n) = O(n \log n)$ +/// +/// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / +/// mean_numerator_bits_denominator`. +/// +/// # Panics +/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < +/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > +/// 0$ and their ratio is less than or equal to the bit length of $a$, or if they are too large and +/// manipulating them leads to arithmetic overflow. +/// +/// # Examples +/// ``` +/// use malachite_base::iterators::prefix_to_string; +/// use malachite_base::random::EXAMPLE_SEED; +/// use malachite_q::random::striped_random_rational_range_to_infinity; +/// use malachite_q::Rational; +/// +/// assert_eq!( +/// prefix_to_string( +/// striped_random_rational_range_to_infinity( +/// EXAMPLE_SEED, +/// Rational::from_signeds(-3i32, 2), +/// 10, +/// 1, +/// 3, +/// 1 +/// ), +/// 10 +/// ), +/// "[3/2, 39, 239/2, -32/63, 127/16, 16383/4, -1/2, 1, 583664, 1, ...]" +/// ) +/// ``` +pub fn striped_random_rational_range_to_infinity( + seed: Seed, + a: Rational, + mean_stripe_numerator: u64, + mean_stripe_denominator: u64, + mean_bits_numerator: u64, + mean_bits_denominator: u64, +) -> StripedRandomRationalRangeToInfinity { + StripedRandomRationalRangeToInfinity { + a, + xs: StripedBitSource::new( + seed.fork("xs"), + mean_stripe_numerator, + mean_stripe_denominator, + ), + range_generator: VariableRangeGenerator::new(seed.fork("range generator")), + mean_bits_numerator, + mean_bits_denominator, + denominators: striped_random_positive_naturals( + seed.fork("denominators"), + mean_stripe_numerator, + mean_stripe_denominator, + mean_bits_numerator, + mean_bits_denominator, + ), + } +} + +/// Generates random striped [`Rational`]s less than or equal to a lower bound. See +/// [`striped_random_rational_range_to_negative_infinity`] for more details. +#[derive(Clone, Debug)] +pub struct StripedRandomRationalRangeToNegativeInfinity { + a: Rational, + xs: StripedBitSource, + range_generator: VariableRangeGenerator, + mean_bits_numerator: u64, + mean_bits_denominator: u64, + denominators: StripedRandomNaturals>, +} + +impl Iterator for StripedRandomRationalRangeToNegativeInfinity { + type Item = Rational; + + fn next(&mut self) -> Option { + let d = self.denominators.next().unwrap(); + let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Floor).0; + let (numerator, denominator) = (Rational::from(d.significant_bits()) + + Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator)) + .into_numerator_and_denominator(); + let numerator = u64::exact_from(&numerator); + let denominator = u64::exact_from(&denominator); + loop { + let n = get_striped_random_integer_from_range_to_negative_infinity( + &mut self.xs, + &mut self.range_generator, + numerator_bound.clone(), + numerator, + denominator, + ); + if n.unsigned_abs_ref().coprime_with(&d) { + return Some(Rational { + sign: n >= 0, + numerator: n.unsigned_abs(), + denominator: d, + }); + } + } + } +} + +/// Generates striped random [`Rational`]s less than or equal to a lower bound $a$. +/// +/// The actual numerator and denominator bit lengths are chosen from a geometric distribution with +/// mean $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than +/// `1`. A striped bit sequence with the given stripe parameter is generated and truncated at the +/// bit lengths to produce the numerators and denominators. The highest bits are forced to be `1`. +/// Finally, the [`Rational`] is reduced. +/// +/// The output length is infinite. +/// +/// See [`StripedBitSource`] for information about generating striped random numbers. +/// +/// # Expected complexity per iteration +/// $T(n) = O(n (\log n)^2 \log\log n)$ +/// +/// $M(n) = O(n \log n)$ +/// +/// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / +/// mean_numerator_bits_denominator`. +/// +/// # Panics +/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < +/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a < +/// 0$ and their ratio is less than or equal to the bit length of $a$, or if they are too large and +/// manipulating them leads to arithmetic overflow. +/// +/// # Examples +/// ``` +/// use malachite_base::iterators::prefix_to_string; +/// use malachite_base::random::EXAMPLE_SEED; +/// use malachite_q::random::striped_random_rational_range_to_negative_infinity; +/// use malachite_q::Rational; +/// +/// assert_eq!( +/// prefix_to_string( +/// striped_random_rational_range_to_negative_infinity( +/// EXAMPLE_SEED, +/// Rational::from_signeds(-3i32, 2), +/// 10, +/// 1, +/// 3, +/// 1 +/// ), +/// 10 +/// ), +/// "[-79/2, -7, -1051/2, -95/63, -255/16, -159/4, -3/2, -16, -2, -22, ...]" +/// ) +/// ``` +pub fn striped_random_rational_range_to_negative_infinity( + seed: Seed, + a: Rational, + mean_stripe_numerator: u64, + mean_stripe_denominator: u64, + mean_bits_numerator: u64, + mean_bits_denominator: u64, +) -> StripedRandomRationalRangeToNegativeInfinity { + StripedRandomRationalRangeToNegativeInfinity { + a, + xs: StripedBitSource::new( + seed.fork("xs"), + mean_stripe_numerator, + mean_stripe_denominator, + ), + range_generator: VariableRangeGenerator::new(seed.fork("range generator")), + mean_bits_numerator, + mean_bits_denominator, + denominators: striped_random_positive_naturals( + seed.fork("denominators"), + mean_stripe_numerator, + mean_stripe_denominator, + mean_bits_numerator, + mean_bits_denominator, + ), + } +} diff --git a/malachite-q/src/test_util/generators/random.rs b/malachite-q/src/test_util/generators/random.rs index e593290be..42730a7a7 100644 --- a/malachite-q/src/test_util/generators/random.rs +++ b/malachite-q/src/test_util/generators/random.rs @@ -1273,7 +1273,6 @@ pub fn random_rational_triple_gen_var_1(config: &GenConfig) -> It<(Rational, Rat } pub fn random_rational_triple_gen_var_2(config: &GenConfig) -> It<(Rational, Rational, Rational)> { - // TODO Box::new(random_ordered_unique_triples(random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), diff --git a/malachite-q/tests/lib.rs b/malachite-q/tests/lib.rs index 2e303513e..2a1554951 100644 --- a/malachite-q/tests/lib.rs +++ b/malachite-q/tests/lib.rs @@ -195,5 +195,7 @@ pub mod random { pub mod striped_random_non_negative_rationals; pub mod striped_random_nonzero_rationals; pub mod striped_random_positive_rationals; + pub mod striped_random_rational_range_to_infinity; + pub mod striped_random_rational_range_to_negative_infinity; pub mod striped_random_rationals; } diff --git a/malachite-q/tests/random/striped_random_rational_range_to_infinity.rs b/malachite-q/tests/random/striped_random_rational_range_to_infinity.rs new file mode 100644 index 000000000..2823baa20 --- /dev/null +++ b/malachite-q/tests/random/striped_random_rational_range_to_infinity.rs @@ -0,0 +1,429 @@ +// 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 core::f64; +use malachite_base::num::float::NiceFloat; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::test_util::stats::moments::MomentStats; +use malachite_q::random::striped_random_rational_range_to_infinity; +use malachite_q::test_util::random::random_rationals_helper_helper; +use malachite_q::Rational; +use std::str::FromStr; + +fn striped_random_rational_range_to_infinity_helper( + a: &str, + mean_stripe_numerator: u64, + mean_stripe_denominator: u64, + mean_bits_numerator: u64, + mean_bits_denominator: u64, + expected_values: &[&str], + expected_common_values: &[(&str, usize)], + expected_sample_median: (&str, Option<&str>), + expected_sample_moment_stats: MomentStats, +) { + random_rationals_helper_helper( + striped_random_rational_range_to_infinity( + EXAMPLE_SEED, + Rational::from_str(a).unwrap(), + mean_stripe_numerator, + mean_stripe_denominator, + mean_bits_numerator, + mean_bits_denominator, + ), + expected_values, + expected_common_values, + expected_sample_median, + expected_sample_moment_stats, + ); +} + +#[test] +fn test_striped_random_rational_range_to_infinity() { + let values = &[ + "271/512", + "6171", + "566935683071/512", + "76/3", + "15/64", + "255/2", + "4", + "48127/16", + "11/2048", + "3/2", + "515", + "17242800127/1024", + "1048703/124", + "234881024/15", + "128/31", + "8796218851359/8388544", + "533112815615/2112", + "2/2047", + "56/163839", + "35840/67108639", + ]; + let common_values = &[ + ("0", 8352), + ("1", 7761), + ("1/2", 6447), + ("1/3", 4862), + ("1/4", 4784), + ("1/8", 3643), + ("2", 3520), + ("3", 3478), + ("1/15", 3148), + ("1/7", 3059), + ]; + let sample_median = ("32", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(4.409358732383749e152), + standard_deviation: NiceFloat(f64::INFINITY), + skewness: NiceFloat(f64::NAN), + excess_kurtosis: NiceFloat(f64::NAN), + }; + striped_random_rational_range_to_infinity_helper( + "0", + 10, + 1, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "67625999/512", + "255", + "65535/512", + "64/3", + "15359/64", + "127/2", + "4", + "51/16", + "6447/2048", + "12884903935/2", + "16", + "507907/1024", + "481238123007/124", + "240652386176/15", + "259/31", + "8796092760095/8388544", + "137438953471/2112", + "8127456/2047", + "4195072/163839", + "34359685144/67108639", + ]; + let common_values = &[ + ("7/2", 8188), + ("4", 5039), + ("7", 5016), + ("8", 4043), + ("15", 3931), + ("13/4", 3381), + ("16", 3288), + ("15/4", 3136), + ("31", 3076), + ("15/2", 2959), + ]; + let sample_median = ("2175/16", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(7.744407957000211e34), + standard_deviation: NiceFloat(7.744259426671135e37), + skewness: NiceFloat(999.9984995429722), + excess_kurtosis: NiceFloat(999994.9993924203), + }; + striped_random_rational_range_to_infinity_helper( + "245850922/78256779", + 10, + 1, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "4593671619918423055/512", + "-1", + "18371/512", + "4193840/3", + "262207/64", + "35/2", + "512", + "5/16", + "15/2048", + "1/2", + "3", + "8796025921535/1024", + "32383/124", + "2097152/15", + "520617983/31", + "281473298997247/8388544", + "753727/2112", + "1/2047", + "316922321454532762194950488064/163839", + "140737572241392/67108639", + ]; + let common_values = &[ + ("0", 7263), + ("-1", 6723), + ("1", 6665), + ("1/2", 5349), + ("-1/2", 5279), + ("-1/4", 3876), + ("-1/3", 3821), + ("1/4", 3789), + ("1/3", 3702), + ("3", 3112), + ]; + let sample_median = ("1", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(1.9587800502633983e137), + standard_deviation: NiceFloat(1.9506593605642805e140), + skewness: NiceFloat(f64::NAN), + excess_kurtosis: NiceFloat(f64::NAN), + }; + striped_random_rational_range_to_infinity_helper( + "-245850922/78256779", + 10, + 1, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "425/682", + "5417", + "915560901293/682", + "106/3", + "13/106", + "213/2", + "6", + "43605/26", + "1/2730", + "53/2", + "30042", + "2022571682517/1354", + "3413/122", + "29320310074197/13", + "10/27", + "1365/6728362", + "421/3402", + "218/1365", + "10/187029", + "123120293/47535445", + ]; + let common_values = &[ + ("0", 8397), + ("1", 7518), + ("1/6", 7132), + ("1/2", 6454), + ("1/3", 5083), + ("1/10", 4786), + ("2", 3565), + ("3", 3511), + ("1/42", 3475), + ("1/5", 3333), + ]; + let sample_median = ("168/5", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(1.94013873735947e225), + standard_deviation: NiceFloat(f64::INFINITY), + skewness: NiceFloat(f64::NAN), + excess_kurtosis: NiceFloat(f64::NAN), + }; + striped_random_rational_range_to_infinity_helper( + "0", + 11, + 10, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "86693545/682", + "213", + "89461/682", + "86/3", + "13485/106", + "85/2", + "5", + "85/26", + "58640620148053/2730", + "85/2", + "1791306", + "3515733/1354", + "5461/122", + "5546/13", + "425022890/27", + "28644288853/6728362", + "11605/3402", + "218278/1365", + "14316545365/187029", + "447042218/47535445", + ]; + let common_values = &[ + ("7/2", 8241), + ("5", 5118), + ("6", 5008), + ("10", 4145), + ("13", 4037), + ("53/6", 3903), + ("21", 3250), + ("26", 3189), + ("13/3", 3159), + ("85/6", 3149), + ]; + let sample_median = ("170", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(3.679955500231244e31), + standard_deviation: NiceFloat(3.5472081267359855e34), + skewness: NiceFloat(997.8746442700499), + excess_kurtosis: NiceFloat(997092.4918116309), + }; + striped_random_rational_range_to_infinity_helper( + "245850922/78256779", + 11, + 10, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "3075190078489417385/682", + "-1", + "13653/682", + "2796202/3", + "174677/106", + "43/2", + "938", + "5/26", + "611669/2730", + "5/2", + "298", + "1365/1354", + "240299/122", + "-2/13", + "3002582332429654/27", + "3582613/6728362", + "1/3402", + "55923893/1365", + "22906516820/187029", + "-3418/47535445", + ]; + let common_values = &[ + ("0", 7243), + ("1", 6768), + ("-1", 6595), + ("-1/2", 5212), + ("1/6", 5110), + ("-1/6", 5064), + ("1/2", 4972), + ("1/3", 4057), + ("-1/3", 4026), + ("-1/10", 3488), + ]; + let sample_median = ("5/6", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(3.188107796101159e165), + standard_deviation: NiceFloat(f64::INFINITY), + skewness: NiceFloat(f64::NAN), + excess_kurtosis: NiceFloat(f64::NAN), + }; + striped_random_rational_range_to_infinity_helper( + "-245850922/78256779", + 11, + 10, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_infinity_fail_1() { + striped_random_rational_range_to_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 10, + 1, + 10, + 0, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_infinity_fail_2() { + striped_random_rational_range_to_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 10, + 1, + 0, + 0, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_infinity_fail_3() { + striped_random_rational_range_to_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 10, + 1, + 2, + 3, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_infinity_fail_4() { + striped_random_rational_range_to_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 1, + 0, + 10, + 1, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_infinity_fail_5() { + striped_random_rational_range_to_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 2, + 3, + 10, + 1, + ); +} diff --git a/malachite-q/tests/random/striped_random_rational_range_to_negative_infinity.rs b/malachite-q/tests/random/striped_random_rational_range_to_negative_infinity.rs new file mode 100644 index 000000000..5d75a1393 --- /dev/null +++ b/malachite-q/tests/random/striped_random_rational_range_to_negative_infinity.rs @@ -0,0 +1,429 @@ +// 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 core::f64; +use malachite_base::num::float::NiceFloat; +use malachite_base::random::EXAMPLE_SEED; +use malachite_base::test_util::stats::moments::MomentStats; +use malachite_q::random::striped_random_rational_range_to_negative_infinity; +use malachite_q::test_util::random::random_rationals_helper_helper; +use malachite_q::Rational; +use std::str::FromStr; + +fn striped_random_rational_range_to_negative_infinity_helper( + a: &str, + mean_stripe_numerator: u64, + mean_stripe_denominator: u64, + mean_bits_numerator: u64, + mean_bits_denominator: u64, + expected_values: &[&str], + expected_common_values: &[(&str, usize)], + expected_sample_median: (&str, Option<&str>), + expected_sample_moment_stats: MomentStats, +) { + random_rationals_helper_helper( + striped_random_rational_range_to_negative_infinity( + EXAMPLE_SEED, + Rational::from_str(a).unwrap(), + mean_stripe_numerator, + mean_stripe_denominator, + mean_bits_numerator, + mean_bits_denominator, + ), + expected_values, + expected_common_values, + expected_sample_median, + expected_sample_moment_stats, + ); +} + +#[test] +fn test_striped_random_rational_range_to_negative_infinity() { + let values = &[ + "-271/512", + "-6171", + "-566935683071/512", + "-76/3", + "-15/64", + "-255/2", + "-4", + "-48127/16", + "-11/2048", + "-3/2", + "-515", + "-17242800127/1024", + "-1048703/124", + "-234881024/15", + "-128/31", + "-8796218851359/8388544", + "-533112815615/2112", + "-2/2047", + "-56/163839", + "-35840/67108639", + ]; + let common_values = &[ + ("0", 8352), + ("-1", 7761), + ("-1/2", 6447), + ("-1/3", 4862), + ("-1/4", 4784), + ("-1/8", 3643), + ("-2", 3520), + ("-3", 3478), + ("-1/15", 3148), + ("-1/7", 3059), + ]; + let sample_median = ("-32", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(-4.409358732383749e152), + standard_deviation: NiceFloat(f64::INFINITY), + skewness: NiceFloat(f64::NAN), + excess_kurtosis: NiceFloat(f64::NAN), + }; + striped_random_rational_range_to_negative_infinity_helper( + "0", + 10, + 1, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "-4503599627887631/512", + "-135235075", + "-262115/512", + "-4198396/3", + "-7/64", + "1/2", + "-37588312048", + "1/16", + "-11/2048", + "-3/2", + "-1", + "-63/1024", + "259/124", + "-8191/15", + "-8796093022177/31", + "-4095/8388544", + "-1/2112", + "-8/2047", + "-67108867/163839", + "2/67108639", + ]; + let common_values = &[ + ("0", 7327), + ("-1", 6761), + ("1", 6713), + ("1/2", 5344), + ("-1/2", 5234), + ("-1/3", 3833), + ("1/3", 3826), + ("1/4", 3810), + ("-1/4", 3726), + ("3", 3159), + ]; + let sample_median = ("-1", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(-5.615673330944999e205), + standard_deviation: NiceFloat(f64::INFINITY), + skewness: NiceFloat(f64::NAN), + excess_kurtosis: NiceFloat(f64::NAN), + }; + striped_random_rational_range_to_negative_infinity_helper( + "245850922/78256779", + 10, + 1, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "-67625999/512", + "-255", + "-65535/512", + "-64/3", + "-15359/64", + "-127/2", + "-4", + "-51/16", + "-6447/2048", + "-12884903935/2", + "-16", + "-507907/1024", + "-481238123007/124", + "-240652386176/15", + "-259/31", + "-8796092760095/8388544", + "-137438953471/2112", + "-8127456/2047", + "-4195072/163839", + "-34359685144/67108639", + ]; + let common_values = &[ + ("-7/2", 8188), + ("-4", 5039), + ("-7", 5016), + ("-8", 4043), + ("-15", 3931), + ("-13/4", 3381), + ("-16", 3288), + ("-15/4", 3136), + ("-31", 3076), + ("-15/2", 2959), + ]; + let sample_median = ("-2175/16", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(-7.744407957000211e34), + standard_deviation: NiceFloat(7.744259426671135e37), + skewness: NiceFloat(-999.9984995429722), + excess_kurtosis: NiceFloat(999994.9993924203), + }; + striped_random_rational_range_to_negative_infinity_helper( + "-245850922/78256779", + 10, + 1, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "-425/682", + "-5417", + "-915560901293/682", + "-106/3", + "-13/106", + "-213/2", + "-6", + "-43605/26", + "-1/2730", + "-53/2", + "-30042", + "-2022571682517/1354", + "-3413/122", + "-29320310074197/13", + "-10/27", + "-1365/6728362", + "-421/3402", + "-218/1365", + "-10/187029", + "-123120293/47535445", + ]; + let common_values = &[ + ("0", 8397), + ("-1", 7518), + ("-1/6", 7132), + ("-1/2", 6454), + ("-1/3", 5083), + ("-1/10", 4786), + ("-2", 3565), + ("-3", 3511), + ("-1/42", 3475), + ("-1/5", 3333), + ]; + let sample_median = ("-168/5", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(-1.94013873735947e225), + standard_deviation: NiceFloat(f64::INFINITY), + skewness: NiceFloat(f64::NAN), + excess_kurtosis: NiceFloat(f64::NAN), + }; + striped_random_rational_range_to_negative_infinity_helper( + "0", + 11, + 10, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "-3735132622739113/682", + "-223696213", + "-218453/682", + "-5416618/3", + "-5/106", + "1/2", + "-57355358890", + "-25/26", + "-5960819038131541/2730", + "-27317/2", + "-1453", + "853/1354", + "-223696213/122", + "-42/13", + "1/27", + "-53/6728362", + "-43/3402", + "-693673/1365", + "-2863311530/187029", + "21802/47535445", + ]; + let common_values = &[ + ("0", 7227), + ("1", 6794), + ("-1", 6488), + ("1/2", 5198), + ("1/6", 5142), + ("-1/2", 5003), + ("-1/6", 4997), + ("-1/3", 4098), + ("1/3", 3964), + ("1/10", 3535), + ]; + let sample_median = ("-5/6", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(-4.8115651702518996e170), + standard_deviation: NiceFloat(f64::INFINITY), + skewness: NiceFloat(f64::NAN), + excess_kurtosis: NiceFloat(f64::NAN), + }; + striped_random_rational_range_to_negative_infinity_helper( + "245850922/78256779", + 11, + 10, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); + + let values = &[ + "-86693545/682", + "-213", + "-89461/682", + "-86/3", + "-13485/106", + "-85/2", + "-5", + "-85/26", + "-58640620148053/2730", + "-85/2", + "-1791306", + "-3515733/1354", + "-5461/122", + "-5546/13", + "-425022890/27", + "-28644288853/6728362", + "-11605/3402", + "-218278/1365", + "-14316545365/187029", + "-447042218/47535445", + ]; + let common_values = &[ + ("-7/2", 8241), + ("-5", 5118), + ("-6", 5008), + ("-10", 4145), + ("-13", 4037), + ("-53/6", 3903), + ("-21", 3250), + ("-26", 3189), + ("-13/3", 3159), + ("-85/6", 3149), + ]; + let sample_median = ("-170", None); + let sample_moment_stats = MomentStats { + mean: NiceFloat(-3.679955500231244e31), + standard_deviation: NiceFloat(3.5472081267359855e34), + skewness: NiceFloat(-997.8746442700499), + excess_kurtosis: NiceFloat(997092.4918116309), + }; + striped_random_rational_range_to_negative_infinity_helper( + "-245850922/78256779", + 11, + 10, + 10, + 1, + values, + common_values, + sample_median, + sample_moment_stats, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_negative_infinity_fail_1() { + striped_random_rational_range_to_negative_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 10, + 1, + 10, + 0, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_negative_infinity_fail_2() { + striped_random_rational_range_to_negative_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 10, + 1, + 0, + 0, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_negative_infinity_fail_3() { + striped_random_rational_range_to_negative_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 10, + 1, + 2, + 3, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_negative_infinity_fail_4() { + striped_random_rational_range_to_negative_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 1, + 0, + 10, + 1, + ); +} + +#[test] +#[should_panic] +fn striped_random_rational_range_to_negative_infinity_fail_5() { + striped_random_rational_range_to_negative_infinity( + EXAMPLE_SEED, + Rational::from_unsigneds(1u32, 3), + 2, + 3, + 10, + 1, + ); +} diff --git a/malachite/Cargo.toml b/malachite/Cargo.toml index c095fa92b..8f15e03b2 100644 --- a/malachite/Cargo.toml +++ b/malachite/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "malachite" -version = "0.4.15" +version = "0.4.16" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true @@ -13,10 +13,10 @@ keywords = ["mathematics", "math", "numerics", "bignum"] categories = ["mathematics"] [dependencies] -malachite-base = { version = "0.4.15", default-features = false } -malachite-nz = { version = "0.4.15", default-features = false, optional = true } -malachite-q = { version = "0.4.15", default-features = false, optional = true } -malachite-float = { version = "0.4.15", default-features = false, optional = true } +malachite-base = { version = "0.4.16", default-features = false } +malachite-nz = { version = "0.4.16", default-features = false, optional = true } +malachite-q = { version = "0.4.16", default-features = false, optional = true } +malachite-float = { version = "0.4.16", default-features = false, optional = true } serde = { version = "1.0.188", optional = true, features = ["derive"] } embed-doc-image = { version = "0.1.4", optional = true }