chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"5479f71d6bd2a999c466271314d18e606315b2d0f518690678d7ee2a6c8cd3d0",".github/workflows/tests.yaml":"8d68ea5bdc2d02f460e3f1f7e3f58c3f0a3fef8bbaf47572cf9699dcce54fe2a",".travis.yml":"98891ee16c3b83705019d24f51b84a01e6041c7682c5057714bdf492adc7cd95","Cargo.toml":"7ce7bb08b51de5ad0b0b94d830d7573fe78f5e7fb72425cdec86a3543ce658e2","Cargo.toml.orig":"6d193eee9b57ace6bb0c76a5f341e5041128a4d2953abb16923c1c8b2c7123c6","LICENSE-MIT":"f7715d38a3fa1b4ac97c5729740752505a39cb92ee83ab5b102aeb5eaa7cdea4","README.md":"f38ad2ec742e6c867cf9fca31026a4baf174f03b3b2f89c74dfcead90c28ea35","rustfmt.toml":"d72fafaea8c9695f74c40bc666ada205b935bec3f02488bb33e5994e2831bffb","src/lib.rs":"7ef19f59e6870da4a3ddb958f2eb976278704f21f68cf6a59507574dbc5e7715","tests/test.rs":"39049fc96151f42aa3c5f8cfff5d40ff62efae234096825a186ecc0abe5bb1ee"},"package":"68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"}

View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "6e1992ca094d93c839554e9dfeb90850b9274b98"
},
"path_in_vcs": ""
}

View File

@@ -0,0 +1,55 @@
on: [push, pull_request]
name: Tests
jobs:
test:
name: Tests
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- 1.36.0
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- name: Test (default features)
uses: actions-rs/cargo@v1
with:
command: test
- name: Test (no default features)
uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features
- name: Test (schema features subset)
if: matrix.rust == 'stable'
uses: actions-rs/cargo@v1
with:
command: test
args: --features "std,schemars"
- name: Test (rand features subset)
if: matrix.rust == 'stable'
uses: actions-rs/cargo@v1
with:
command: test
args: --features "rand,randtest"
- name: Test (all features)
if: matrix.rust == 'stable'
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features

15
vendor/ordered-float/.travis.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
language: rust
rust:
- 1.34.0
- nightly
- beta
- stable
sudo: false
env:
matrix:
- FEATURES=""
- FEATURES="std"
- FEATURES="serde"
- FEATURES="std,serde"
script:
- cargo test -v --no-default-features --features "$FEATURES"

78
vendor/ordered-float/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,78 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "ordered-float"
version = "2.10.1"
authors = [
"Jonathan Reem <jonathan.reem@gmail.com>",
"Matt Brubeck <mbrubeck@limpet.net>",
]
description = "Wrappers for total ordering on floats"
readme = "README.md"
keywords = [
"no_std",
"ord",
"f64",
"f32",
"sort",
]
categories = [
"science",
"rust-patterns",
"no-std",
]
license = "MIT"
repository = "https://github.com/reem/rust-ordered-float"
[dependencies.arbitrary]
version = "1.0.0"
optional = true
[dependencies.num-traits]
version = "0.2.1"
default-features = false
[dependencies.proptest]
version = "1.0.0"
optional = true
[dependencies.rand]
version = "0.8.3"
optional = true
default-features = false
[dependencies.rkyv]
version = "0.7"
features = ["size_32"]
optional = true
default-features = false
[dependencies.schemars]
version = "0.6.5"
optional = true
[dependencies.serde]
version = "1.0"
optional = true
default-features = false
[dev-dependencies.serde_test]
version = "1.0"
[features]
default = ["std"]
randtest = [
"rand/std",
"rand/std_rng",
]
std = ["num-traits/std"]

25
vendor/ordered-float/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2015 Jonathan Reem
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

38
vendor/ordered-float/README.md vendored Normal file
View File

@@ -0,0 +1,38 @@
# Ordered Floats
Provides several wrapper types for Ord and Eq implementations on f64.
## Usage
Use the crates.io repository; add this to your `Cargo.toml` along
with the rest of your dependencies:
```toml
[dependencies]
ordered-float = "2.0"
```
See the [API documentation](https://docs.rs/ordered-float) for further details.
## no_std
To use `ordered_float` without requiring the Rust standard library, disable
the default `std` feature:
```toml
[dependencies]
ordered-float = { version = "2.0", default-features = false }
```
## Optional features
The following optional features can be enabled in `Cargo.toml`:
* `rand`: Adds implementations for various distribution types provided by the `rand` crate.
* `serde`: Implements the `serde::Serialize` and `serde::Deserialize` traits.
* `schemars`: Implements the `schemars::JsonSchema` trait.
* `proptest`: Implements the `proptest::Arbitrary` trait.
## License
MIT

3
vendor/ordered-float/rustfmt.toml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These two unstable options might improve the layout of the code:
#fn_single_line = true
#where_single_line = true

2055
vendor/ordered-float/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1 @@
{"name":"ordered-float","vers":"2.10.1","deps":[{"name":"arbitrary","req":"^1.0.0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"num-traits","req":"^0.2.1","features":[],"optional":false,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"proptest","req":"^1.0.0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"rand","req":"^0.8.3","features":[],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"rkyv","req":"^0.7","features":["size_32"],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"schemars","req":"^0.6.5","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"serde","req":"^1.0","features":[],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false}],"features":{"default":["std"],"randtest":["rand/std","rand/std_rng"],"std":["num-traits/std"]},"features2":null,"cksum":"558991b40bbf8a97d1bbdc6c05651ebc336f1b24510880a2e52ef4ab557f87bc","yanked":null,"links":null,"rust_version":null,"v":2}

763
vendor/ordered-float/tests/test.rs vendored Normal file
View File

@@ -0,0 +1,763 @@
#![allow(clippy::float_cmp, clippy::eq_op, clippy::op_ref)]
extern crate num_traits;
extern crate ordered_float;
#[cfg(not(feature = "std"))]
pub use num_traits::float::FloatCore as Float;
#[cfg(feature = "std")]
pub use num_traits::Float;
pub use num_traits::{Bounded, FromPrimitive, Num, One, Signed, ToPrimitive, Zero};
pub use ordered_float::*;
pub use std::cmp::Ordering::*;
pub use std::convert::TryFrom;
pub use std::{f32, f64, panic};
pub use std::collections::hash_map::RandomState;
pub use std::collections::HashSet;
pub use std::hash::*;
fn not_nan<T: Float>(x: T) -> NotNan<T> {
NotNan::new(x).unwrap()
}
#[test]
fn test_total_order() {
let numberline = [
(-f32::INFINITY, 0),
(-1.0, 1),
(-0.0, 2),
(0.0, 2),
(1.0, 3),
(f32::INFINITY, 4),
(f32::NAN, 5),
(-f32::NAN, 5),
];
for &(fi, i) in &numberline {
for &(fj, j) in &numberline {
assert_eq!(OrderedFloat(fi) < OrderedFloat(fj), i < j);
assert_eq!(OrderedFloat(fi) > OrderedFloat(fj), i > j);
assert_eq!(OrderedFloat(fi) <= OrderedFloat(fj), i <= j);
assert_eq!(OrderedFloat(fi) >= OrderedFloat(fj), i >= j);
assert_eq!(OrderedFloat(fi) == OrderedFloat(fj), i == j);
assert_eq!(OrderedFloat(fi) != OrderedFloat(fj), i != j);
assert_eq!(OrderedFloat(fi).cmp(&OrderedFloat(fj)), i.cmp(&j));
}
}
}
#[test]
fn ordered_f32_compare_regular_floats() {
assert_eq!(OrderedFloat(7.0f32).cmp(&OrderedFloat(7.0)), Equal);
assert_eq!(OrderedFloat(8.0f32).cmp(&OrderedFloat(7.0)), Greater);
assert_eq!(OrderedFloat(4.0f32).cmp(&OrderedFloat(7.0)), Less);
}
#[test]
fn ordered_f32_compare_regular_floats_op() {
assert!(OrderedFloat(7.0f32) == OrderedFloat(7.0));
assert!(OrderedFloat(7.0f32) <= OrderedFloat(7.0));
assert!(OrderedFloat(7.0f32) >= OrderedFloat(7.0));
assert!(OrderedFloat(8.0f32) > OrderedFloat(7.0));
assert!(OrderedFloat(8.0f32) >= OrderedFloat(7.0));
assert!(OrderedFloat(4.0f32) < OrderedFloat(7.0));
assert!(OrderedFloat(4.0f32) <= OrderedFloat(7.0));
}
#[test]
fn ordered_f32_compare_nan() {
let f32_nan: f32 = Float::nan();
assert_eq!(
OrderedFloat(f32_nan).cmp(&OrderedFloat(Float::nan())),
Equal
);
assert_eq!(
OrderedFloat(f32_nan).cmp(&OrderedFloat(-100000.0f32)),
Greater
);
assert_eq!(
OrderedFloat(-100.0f32).cmp(&OrderedFloat(Float::nan())),
Less
);
}
#[test]
fn ordered_f32_compare_nan_op() {
let f32_nan: OrderedFloat<f32> = OrderedFloat(Float::nan());
assert!(f32_nan == f32_nan);
assert!(f32_nan <= f32_nan);
assert!(f32_nan >= f32_nan);
assert!(f32_nan > OrderedFloat(-100000.0f32));
assert!(f32_nan >= OrderedFloat(-100000.0f32));
assert!(OrderedFloat(-100.0f32) < f32_nan);
assert!(OrderedFloat(-100.0f32) <= f32_nan);
assert!(f32_nan > OrderedFloat(Float::infinity()));
assert!(f32_nan >= OrderedFloat(Float::infinity()));
assert!(f32_nan > OrderedFloat(Float::neg_infinity()));
assert!(f32_nan >= OrderedFloat(Float::neg_infinity()));
}
#[test]
fn ordered_f64_compare_regular_floats() {
assert_eq!(OrderedFloat(7.0f64).cmp(&OrderedFloat(7.0)), Equal);
assert_eq!(OrderedFloat(8.0f64).cmp(&OrderedFloat(7.0)), Greater);
assert_eq!(OrderedFloat(4.0f64).cmp(&OrderedFloat(7.0)), Less);
}
#[test]
fn not_nan32_zero() {
assert_eq!(NotNan::<f32>::zero(), 0.0f32);
assert!(NotNan::<f32>::zero().is_zero());
}
#[test]
fn not_nan32_one() {
assert_eq!(NotNan::<f32>::one(), 1.0f32)
}
#[test]
fn not_nan32_bounded() {
assert_eq!(NotNan::<f32>::min_value(), <f32 as Bounded>::min_value());
assert_eq!(NotNan::<f32>::max_value(), <f32 as Bounded>::max_value());
}
#[test]
fn not_nan32_from_primitive() {
assert_eq!(NotNan::<f32>::from_i8(42i8), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_u8(42u8), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_i16(42i16), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_u16(42u16), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_i32(42i32), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_u32(42u32), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_i64(42i64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_u64(42u64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_isize(42isize), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_usize(42usize), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_f32(42f32), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_f32(42f32), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_f64(42f64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_f64(42f64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f32>::from_f32(Float::nan()), None);
assert_eq!(NotNan::<f32>::from_f64(Float::nan()), None);
}
#[test]
fn not_nan32_to_primitive() {
let x = not_nan(42.0f32);
assert_eq!(x.to_u8(), Some(42u8));
assert_eq!(x.to_i8(), Some(42i8));
assert_eq!(x.to_u16(), Some(42u16));
assert_eq!(x.to_i16(), Some(42i16));
assert_eq!(x.to_u32(), Some(42u32));
assert_eq!(x.to_i32(), Some(42i32));
assert_eq!(x.to_u64(), Some(42u64));
assert_eq!(x.to_i64(), Some(42i64));
assert_eq!(x.to_usize(), Some(42usize));
assert_eq!(x.to_isize(), Some(42isize));
assert_eq!(x.to_f32(), Some(42f32));
assert_eq!(x.to_f32(), Some(42f32));
assert_eq!(x.to_f64(), Some(42f64));
assert_eq!(x.to_f64(), Some(42f64));
}
#[test]
fn not_nan32_num() {
assert_eq!(NotNan::<f32>::from_str_radix("42.0", 10).unwrap(), 42.0f32);
assert!(NotNan::<f32>::from_str_radix("NaN", 10).is_err());
}
#[test]
fn not_nan32_signed() {
assert_eq!(not_nan(42f32).abs(), 42f32);
assert_eq!(not_nan(-42f32).abs(), 42f32);
assert_eq!(not_nan(50f32).abs_sub(&not_nan(8f32)), 42f32);
assert_eq!(not_nan(8f32).abs_sub(&not_nan(50f32)), 0f32);
}
#[test]
fn not_nan32_num_cast() {
assert_eq!(
<NotNan<f32> as num_traits::NumCast>::from(42).unwrap(),
42f32
);
assert_eq!(<NotNan<f32> as num_traits::NumCast>::from(f32::nan()), None);
}
#[test]
fn ordered_f64_compare_nan() {
let f64_nan: f64 = Float::nan();
assert_eq!(
OrderedFloat(f64_nan).cmp(&OrderedFloat(Float::nan())),
Equal
);
assert_eq!(
OrderedFloat(f64_nan).cmp(&OrderedFloat(-100000.0f64)),
Greater
);
assert_eq!(
OrderedFloat(-100.0f64).cmp(&OrderedFloat(Float::nan())),
Less
);
}
#[test]
fn ordered_f64_compare_regular_floats_op() {
assert!(OrderedFloat(7.0) == OrderedFloat(7.0));
assert!(OrderedFloat(7.0) <= OrderedFloat(7.0));
assert!(OrderedFloat(7.0) >= OrderedFloat(7.0));
assert!(OrderedFloat(8.0) > OrderedFloat(7.0));
assert!(OrderedFloat(8.0) >= OrderedFloat(7.0));
assert!(OrderedFloat(4.0) < OrderedFloat(7.0));
assert!(OrderedFloat(4.0) <= OrderedFloat(7.0));
}
#[test]
fn ordered_f64_compare_nan_op() {
let f64_nan: OrderedFloat<f64> = OrderedFloat(Float::nan());
assert!(f64_nan == f64_nan);
assert!(f64_nan <= f64_nan);
assert!(f64_nan >= f64_nan);
assert!(f64_nan > OrderedFloat(-100000.0));
assert!(f64_nan >= OrderedFloat(-100000.0));
assert!(OrderedFloat(-100.0) < f64_nan);
assert!(OrderedFloat(-100.0) <= f64_nan);
assert!(f64_nan > OrderedFloat(Float::infinity()));
assert!(f64_nan >= OrderedFloat(Float::infinity()));
assert!(f64_nan > OrderedFloat(Float::neg_infinity()));
assert!(f64_nan >= OrderedFloat(Float::neg_infinity()));
}
#[test]
fn not_nan32_compare_regular_floats() {
assert_eq!(not_nan(7.0f32).cmp(&not_nan(7.0)), Equal);
assert_eq!(not_nan(8.0f32).cmp(&not_nan(7.0)), Greater);
assert_eq!(not_nan(4.0f32).cmp(&not_nan(7.0)), Less);
}
#[test]
fn not_nan32_fail_when_constructing_with_nan() {
let f32_nan: f32 = Float::nan();
assert!(NotNan::new(f32_nan).is_err());
}
#[test]
fn not_nan32_calculate_correctly() {
assert_eq!(*(not_nan(5.0f32) + not_nan(4.0f32)), 5.0f32 + 4.0f32);
assert_eq!(*(not_nan(5.0f32) + 4.0f32), 5.0f32 + 4.0f32);
assert_eq!(*(not_nan(5.0f32) - not_nan(4.0f32)), 5.0f32 - 4.0f32);
assert_eq!(*(not_nan(5.0f32) - 4.0f32), 5.0f32 - 4.0f32);
assert_eq!(*(not_nan(5.0f32) * not_nan(4.0f32)), 5.0f32 * 4.0f32);
assert_eq!(*(not_nan(5.0f32) * 4.0f32), 5.0f32 * 4.0f32);
assert_eq!(*(not_nan(8.0f32) / not_nan(4.0f32)), 8.0f32 / 4.0f32);
assert_eq!(*(not_nan(8.0f32) / 4.0f32), 8.0f32 / 4.0f32);
assert_eq!(*(not_nan(8.0f32) % not_nan(4.0f32)), 8.0f32 % 4.0f32);
assert_eq!(*(not_nan(8.0f32) % 4.0f32), 8.0f32 % 4.0f32);
assert_eq!(*(-not_nan(1.0f32)), -1.0f32);
assert!(panic::catch_unwind(|| not_nan(0.0f32) + f32::NAN).is_err());
assert!(panic::catch_unwind(|| not_nan(0.0f32) - f32::NAN).is_err());
assert!(panic::catch_unwind(|| not_nan(0.0f32) * f32::NAN).is_err());
assert!(panic::catch_unwind(|| not_nan(0.0f32) / f32::NAN).is_err());
assert!(panic::catch_unwind(|| not_nan(0.0f32) % f32::NAN).is_err());
let mut number = not_nan(5.0f32);
number += not_nan(4.0f32);
assert_eq!(*number, 9.0f32);
number -= not_nan(4.0f32);
assert_eq!(*number, 5.0f32);
number *= not_nan(4.0f32);
assert_eq!(*number, 20.0f32);
number /= not_nan(4.0f32);
assert_eq!(*number, 5.0f32);
number %= not_nan(4.0f32);
assert_eq!(*number, 1.0f32);
number = not_nan(5.0f32);
number += 4.0f32;
assert_eq!(*number, 9.0f32);
number -= 4.0f32;
assert_eq!(*number, 5.0f32);
number *= 4.0f32;
assert_eq!(*number, 20.0f32);
number /= 4.0f32;
assert_eq!(*number, 5.0f32);
number %= 4.0f32;
assert_eq!(*number, 1.0f32);
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f32);
tmp += f32::NAN;
})
.is_err());
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f32);
tmp -= f32::NAN;
})
.is_err());
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f32);
tmp *= f32::NAN;
})
.is_err());
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f32);
tmp /= f32::NAN;
})
.is_err());
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f32);
tmp %= f32::NAN;
})
.is_err());
}
#[test]
fn not_nan64_compare_regular_floats() {
assert_eq!(not_nan(7.0f64).cmp(&not_nan(7.0)), Equal);
assert_eq!(not_nan(8.0f64).cmp(&not_nan(7.0)), Greater);
assert_eq!(not_nan(4.0f64).cmp(&not_nan(7.0)), Less);
}
#[test]
fn not_nan64_fail_when_constructing_with_nan() {
let f64_nan: f64 = Float::nan();
assert!(NotNan::new(f64_nan).is_err());
}
#[test]
fn not_nan64_calculate_correctly() {
assert_eq!(*(not_nan(5.0f64) + not_nan(4.0f64)), 5.0f64 + 4.0f64);
assert_eq!(*(not_nan(5.0f64) + 4.0f64), 5.0f64 + 4.0f64);
assert_eq!(*(not_nan(5.0f64) - not_nan(4.0f64)), 5.0f64 - 4.0f64);
assert_eq!(*(not_nan(5.0f64) - 4.0f64), 5.0f64 - 4.0f64);
assert_eq!(*(not_nan(5.0f64) * not_nan(4.0f64)), 5.0f64 * 4.0f64);
assert_eq!(*(not_nan(5.0f64) * 4.0f64), 5.0f64 * 4.0f64);
assert_eq!(*(not_nan(8.0f64) / not_nan(4.0f64)), 8.0f64 / 4.0f64);
assert_eq!(*(not_nan(8.0f64) / 4.0f64), 8.0f64 / 4.0f64);
assert_eq!(*(not_nan(8.0f64) % not_nan(4.0f64)), 8.0f64 % 4.0f64);
assert_eq!(*(not_nan(8.0f64) % 4.0f64), 8.0f64 % 4.0f64);
assert_eq!(*(-not_nan(1.0f64)), -1.0f64);
assert!(panic::catch_unwind(|| not_nan(0.0f64) + f64::NAN).is_err());
assert!(panic::catch_unwind(|| not_nan(0.0f64) - f64::NAN).is_err());
assert!(panic::catch_unwind(|| not_nan(0.0f64) * f64::NAN).is_err());
assert!(panic::catch_unwind(|| not_nan(0.0f64) / f64::NAN).is_err());
assert!(panic::catch_unwind(|| not_nan(0.0f64) % f64::NAN).is_err());
let mut number = not_nan(5.0f64);
number += not_nan(4.0f64);
assert_eq!(*number, 9.0f64);
number -= not_nan(4.0f64);
assert_eq!(*number, 5.0f64);
number *= not_nan(4.0f64);
assert_eq!(*number, 20.0f64);
number /= not_nan(4.0f64);
assert_eq!(*number, 5.0f64);
number %= not_nan(4.0f64);
assert_eq!(*number, 1.0f64);
number = not_nan(5.0f64);
number += 4.0f64;
assert_eq!(*number, 9.0f64);
number -= 4.0f64;
assert_eq!(*number, 5.0f64);
number *= 4.0f64;
assert_eq!(*number, 20.0f64);
number /= 4.0f64;
assert_eq!(*number, 5.0f64);
number %= 4.0f64;
assert_eq!(*number, 1.0f64);
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f64);
tmp += f64::NAN;
})
.is_err());
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f64);
tmp -= f64::NAN;
})
.is_err());
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f64);
tmp *= f64::NAN;
})
.is_err());
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f64);
tmp /= f64::NAN;
})
.is_err());
assert!(panic::catch_unwind(|| {
let mut tmp = not_nan(0.0f64);
tmp %= f64::NAN;
})
.is_err());
}
#[test]
fn not_nan64_zero() {
assert_eq!(NotNan::<f64>::zero(), not_nan(0.0f64));
assert!(NotNan::<f64>::zero().is_zero());
}
#[test]
fn not_nan64_one() {
assert_eq!(NotNan::<f64>::one(), not_nan(1.0f64))
}
#[test]
fn not_nan64_bounded() {
assert_eq!(NotNan::<f64>::min_value(), <f64 as Bounded>::min_value());
assert_eq!(NotNan::<f64>::max_value(), <f64 as Bounded>::max_value());
}
#[test]
fn not_nan64_from_primitive() {
assert_eq!(NotNan::<f64>::from_i8(42i8), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_u8(42u8), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_i16(42i16), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_u16(42u16), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_i32(42i32), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_u32(42u32), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_i64(42i64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_u64(42u64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_isize(42isize), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_usize(42usize), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_f64(42f64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_f64(42f64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_f64(42f64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_f64(42f64), Some(not_nan(42.0)));
assert_eq!(NotNan::<f64>::from_f64(Float::nan()), None);
assert_eq!(NotNan::<f64>::from_f64(Float::nan()), None);
}
#[test]
fn not_nan64_to_primitive() {
let x = not_nan(42.0f64);
assert_eq!(x.to_u8(), Some(42u8));
assert_eq!(x.to_i8(), Some(42i8));
assert_eq!(x.to_u16(), Some(42u16));
assert_eq!(x.to_i16(), Some(42i16));
assert_eq!(x.to_u32(), Some(42u32));
assert_eq!(x.to_i32(), Some(42i32));
assert_eq!(x.to_u64(), Some(42u64));
assert_eq!(x.to_i64(), Some(42i64));
assert_eq!(x.to_usize(), Some(42usize));
assert_eq!(x.to_isize(), Some(42isize));
assert_eq!(x.to_f64(), Some(42f64));
assert_eq!(x.to_f64(), Some(42f64));
assert_eq!(x.to_f64(), Some(42f64));
assert_eq!(x.to_f64(), Some(42f64));
}
#[test]
fn not_nan64_num() {
assert_eq!(
NotNan::<f64>::from_str_radix("42.0", 10).unwrap(),
not_nan(42.0f64)
);
assert!(NotNan::<f64>::from_str_radix("NaN", 10).is_err());
}
#[test]
fn not_nan64_signed() {
assert_eq!(not_nan(42f64).abs(), not_nan(42f64));
assert_eq!(not_nan(-42f64).abs(), not_nan(42f64));
assert_eq!(not_nan(50f64).abs_sub(&not_nan(8f64)), not_nan(42f64));
assert_eq!(not_nan(8f64).abs_sub(&not_nan(50f64)), not_nan(0f64));
}
#[test]
fn not_nan64_num_cast() {
assert_eq!(
<NotNan<f64> as num_traits::NumCast>::from(42),
Some(not_nan(42f64))
);
assert_eq!(<NotNan<f64> as num_traits::NumCast>::from(f64::nan()), None);
}
#[test]
fn hash_zero_and_neg_zero_to_the_same_hc() {
let state = RandomState::new();
let mut h1 = state.build_hasher();
let mut h2 = state.build_hasher();
OrderedFloat::from(0f64).hash(&mut h1);
OrderedFloat::from(-0f64).hash(&mut h2);
assert_eq!(h1.finish(), h2.finish());
}
#[test]
fn hash_inf_and_neg_inf_to_different_hcs() {
let state = RandomState::new();
let mut h1 = state.build_hasher();
let mut h2 = state.build_hasher();
OrderedFloat::from(f64::INFINITY).hash(&mut h1);
OrderedFloat::from(f64::NEG_INFINITY).hash(&mut h2);
assert!(h1.finish() != h2.finish());
}
#[test]
fn hash_is_good_for_whole_numbers() {
let state = RandomState::new();
let limit = 10000;
let mut set = ::std::collections::HashSet::with_capacity(limit);
for i in 0..limit {
let mut h = state.build_hasher();
OrderedFloat::from(i as f64).hash(&mut h);
set.insert(h.finish());
}
// This allows 100 collisions, which is far too
// many, but should guard against transient issues
// that will result from using RandomState
let pct_unique = set.len() as f64 / limit as f64;
assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
}
#[test]
fn hash_is_good_for_fractional_numbers() {
let state = RandomState::new();
let limit = 10000;
let mut set = ::std::collections::HashSet::with_capacity(limit);
for i in 0..limit {
let mut h = state.build_hasher();
OrderedFloat::from(i as f64 * (1f64 / limit as f64)).hash(&mut h);
set.insert(h.finish());
}
// This allows 100 collisions, which is far too
// many, but should guard against transient issues
// that will result from using RandomState
let pct_unique = set.len() as f64 / limit as f64;
assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
}
#[test]
#[should_panic]
fn test_add_fails_on_nan() {
let a = not_nan(std::f32::INFINITY);
let b = not_nan(std::f32::NEG_INFINITY);
let _c = a + b;
}
#[test]
#[should_panic]
fn test_add_fails_on_nan_ref() {
let a = not_nan(std::f32::INFINITY);
let b = not_nan(std::f32::NEG_INFINITY);
let _c = a + &b;
}
#[test]
#[should_panic]
fn test_add_fails_on_nan_ref_ref() {
let a = not_nan(std::f32::INFINITY);
let b = not_nan(std::f32::NEG_INFINITY);
let _c = &a + &b;
}
#[test]
#[should_panic]
fn test_add_fails_on_nan_t_ref() {
let a = not_nan(std::f32::INFINITY);
let b = std::f32::NEG_INFINITY;
let _c = a + &b;
}
#[test]
#[should_panic]
fn test_add_fails_on_nan_ref_t_ref() {
let a = not_nan(std::f32::INFINITY);
let b = std::f32::NEG_INFINITY;
let _c = &a + &b;
}
#[test]
#[should_panic]
fn test_add_fails_on_nan_ref_t() {
let a = not_nan(std::f32::INFINITY);
let b = std::f32::NEG_INFINITY;
let _c = &a + b;
}
#[test]
#[should_panic]
fn test_add_assign_fails_on_nan_ref() {
let mut a = not_nan(std::f32::INFINITY);
let b = not_nan(std::f32::NEG_INFINITY);
a += &b;
}
#[test]
#[should_panic]
fn test_add_assign_fails_on_nan_t_ref() {
let mut a = not_nan(std::f32::INFINITY);
let b = std::f32::NEG_INFINITY;
a += &b;
}
#[test]
#[should_panic]
fn test_add_assign_fails_on_nan_t() {
let mut a = not_nan(std::f32::INFINITY);
let b = std::f32::NEG_INFINITY;
a += b;
}
#[test]
fn add() {
assert_eq!(not_nan(0.0) + not_nan(0.0), 0.0);
assert_eq!(not_nan(0.0) + &not_nan(0.0), 0.0);
assert_eq!(&not_nan(0.0) + not_nan(0.0), 0.0);
assert_eq!(&not_nan(0.0) + &not_nan(0.0), 0.0);
assert_eq!(not_nan(0.0) + 0.0, 0.0);
assert_eq!(not_nan(0.0) + &0.0, 0.0);
assert_eq!(&not_nan(0.0) + 0.0, 0.0);
assert_eq!(&not_nan(0.0) + &0.0, 0.0);
assert_eq!(OrderedFloat(0.0) + OrderedFloat(0.0), 0.0);
assert_eq!(OrderedFloat(0.0) + &OrderedFloat(0.0), 0.0);
assert_eq!(&OrderedFloat(0.0) + OrderedFloat(0.0), 0.0);
assert_eq!(&OrderedFloat(0.0) + &OrderedFloat(0.0), 0.0);
assert_eq!(OrderedFloat(0.0) + 0.0, 0.0);
assert_eq!(OrderedFloat(0.0) + &0.0, 0.0);
assert_eq!(&OrderedFloat(0.0) + 0.0, 0.0);
assert_eq!(&OrderedFloat(0.0) + &0.0, 0.0);
}
#[test]
fn ordered_f32_neg() {
assert_eq!(OrderedFloat(-7.0f32), -OrderedFloat(7.0f32));
}
#[test]
fn ordered_f64_neg() {
assert_eq!(OrderedFloat(-7.0f64), -OrderedFloat(7.0f64));
}
#[test]
#[should_panic]
fn test_sum_fails_on_nan() {
let a = not_nan(std::f32::INFINITY);
let b = not_nan(std::f32::NEG_INFINITY);
let _c: NotNan<_> = [a, b].iter().sum();
}
#[test]
#[should_panic]
fn test_product_fails_on_nan() {
let a = not_nan(std::f32::INFINITY);
let b = not_nan(0f32);
let _c: NotNan<_> = [a, b].iter().product();
}
#[test]
fn not_nan64_sum_product() {
let a = not_nan(2138.1237);
let b = not_nan(132f64);
let c = not_nan(5.1);
assert_eq!(
std::iter::empty::<NotNan<f64>>().sum::<NotNan<_>>(),
NotNan::new(0f64).unwrap()
);
assert_eq!([a].iter().sum::<NotNan<_>>(), a);
assert_eq!([a, b].iter().sum::<NotNan<_>>(), a + b);
assert_eq!([a, b, c].iter().sum::<NotNan<_>>(), a + b + c);
assert_eq!(
std::iter::empty::<NotNan<f64>>().product::<NotNan<_>>(),
NotNan::new(1f64).unwrap()
);
assert_eq!([a].iter().product::<NotNan<_>>(), a);
assert_eq!([a, b].iter().product::<NotNan<_>>(), a * b);
assert_eq!([a, b, c].iter().product::<NotNan<_>>(), a * b * c);
}
#[test]
fn not_nan_usage_in_const_context() {
const A: NotNan<f32> = unsafe { NotNan::new_unchecked(111f32) };
assert_eq!(A, NotNan::new(111f32).unwrap());
}
#[test]
fn not_nan_panic_safety() {
let catch_op = |mut num, op: fn(&mut NotNan<_>)| {
let mut num_ref = panic::AssertUnwindSafe(&mut num);
let _ = panic::catch_unwind(move || op(&mut *num_ref));
num
};
assert!(!catch_op(not_nan(f32::INFINITY), |a| *a += f32::NEG_INFINITY).is_nan());
assert!(!catch_op(not_nan(f32::INFINITY), |a| *a -= f32::INFINITY).is_nan());
assert!(!catch_op(not_nan(0.0), |a| *a *= f32::INFINITY).is_nan());
assert!(!catch_op(not_nan(0.0), |a| *a /= 0.0).is_nan());
assert!(!catch_op(not_nan(0.0), |a| *a %= 0.0).is_nan());
}
#[test]
fn from_ref() {
let f = 1.0f32;
let o: &OrderedFloat<f32> = (&f).into();
assert_eq!(*o, 1.0f32);
let mut f = 1.0f64;
let o: &OrderedFloat<f64> = (&f).into();
assert_eq!(*o, 1.0f64);
let o: &mut OrderedFloat<f64> = (&mut f).into();
assert_eq!(*o, 1.0f64);
*o = OrderedFloat(2.0);
assert_eq!(*o, 2.0f64);
assert_eq!(f, 2.0f64);
}
#[cfg(feature = "arbitrary")]
mod arbitrary_test {
use super::{NotNan, OrderedFloat};
use arbitrary::{Arbitrary, Unstructured};
#[test]
fn exhaustive() {
// Exhaustively search all patterns of sign and exponent bits plus a few mantissa bits.
for high_bytes in 0..=u16::MAX {
let [h1, h2] = high_bytes.to_be_bytes();
// Each of these should not
// * panic,
// * return an error, or
// * need more bytes than given.
let n32: NotNan<f32> = Unstructured::new(&[h1, h2, h1, h2])
.arbitrary()
.expect("NotNan<f32> failure");
let n64: NotNan<f64> = Unstructured::new(&[h1, h2, h1, h2, h1, h2, h1, h2])
.arbitrary()
.expect("NotNan<f64> failure");
let _: OrderedFloat<f32> = Unstructured::new(&[h1, h2, h1, h2])
.arbitrary()
.expect("OrderedFloat<f32> failure");
let _: OrderedFloat<f64> = Unstructured::new(&[h1, h2, h1, h2, h1, h2, h1, h2])
.arbitrary()
.expect("OrderedFloat<f64> failure");
// Check for violation of NotNan's property of never containing a NaN.
assert!(!n32.into_inner().is_nan());
assert!(!n64.into_inner().is_nan());
}
}
#[test]
fn size_hints() {
assert_eq!(NotNan::<f32>::size_hint(0), (4, Some(4)));
assert_eq!(NotNan::<f64>::size_hint(0), (8, Some(8)));
assert_eq!(OrderedFloat::<f32>::size_hint(0), (4, Some(4)));
assert_eq!(OrderedFloat::<f64>::size_hint(0), (8, Some(8)));
}
}