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 }