summaryrefslogtreecommitdiffstats
path: root/third_party/rust/float-cmp/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/float-cmp/src
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/float-cmp/src')
-rw-r--r--third_party/rust/float-cmp/src/eq.rs284
-rw-r--r--third_party/rust/float-cmp/src/lib.rs196
-rw-r--r--third_party/rust/float-cmp/src/macros.rs77
-rw-r--r--third_party/rust/float-cmp/src/ratio.rs142
-rw-r--r--third_party/rust/float-cmp/src/ulps.rs240
-rw-r--r--third_party/rust/float-cmp/src/ulps_eq.rs119
6 files changed, 1058 insertions, 0 deletions
diff --git a/third_party/rust/float-cmp/src/eq.rs b/third_party/rust/float-cmp/src/eq.rs
new file mode 100644
index 0000000000..d39535c95a
--- /dev/null
+++ b/third_party/rust/float-cmp/src/eq.rs
@@ -0,0 +1,284 @@
+// Copyright 2014-2018 Optimal Computing (NZ) Ltd.
+// Licensed under the MIT license. See LICENSE for details.
+
+use std::{f32,f64};
+use super::Ulps;
+
+/// ApproxEq is a trait for approximate equality comparisons.
+pub trait ApproxEq: Sized {
+ /// The Margin type defines a margin within which two values are to be
+ /// considered approximately equal. It must implement Default so that
+ /// approx_eq() can be called on unknown types.
+ type Margin: Copy + Default;
+
+ /// This method tests for `self` and `other` values to be approximately equal
+ /// within `margin`.
+ fn approx_eq<M: Into<Self::Margin>>(self, other: Self, margin: M) -> bool;
+
+ /// This method tests for `self` and `other` values to be not approximately
+ /// equal within `margin`.
+ fn approx_ne<M: Into<Self::Margin>>(self, other: Self, margin: M) -> bool {
+ !self.approx_eq(other, margin)
+ }
+}
+
+/// This type defines a margin within two f32s might be considered equal
+/// and is intended as the associated type for the `ApproxEq` trait.
+///
+/// Two methods are used to determine approximate equality.
+///
+/// First an epsilon method is used, considering them approximately equal if they
+/// differ by <= `epsilon`. This will only succeed for very small numbers.
+/// Note that it may succeed even if the parameters are of differing signs straddling
+/// zero.
+///
+/// The second method considers how many ULPs (units of least precision, units in
+/// the last place, which is the integer number of floating point representations
+/// that the parameters are separated by) different the parameters are and considers
+/// them approximately equal if this is <= `ulps`. For large floating point numbers,
+/// an ULP can be a rather large gap, but this kind of comparison is necessary
+/// because floating point operations must round to the nearest representable value
+/// and so larger floating point values accumulate larger errors.
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct F32Margin {
+ pub epsilon: f32,
+ pub ulps: i32
+}
+impl Default for F32Margin {
+ #[inline]
+ fn default() -> F32Margin {
+ F32Margin {
+ epsilon: f32::EPSILON,
+ ulps: 4
+ }
+ }
+}
+impl F32Margin {
+ #[inline]
+ pub fn zero() -> F32Margin {
+ F32Margin {
+ epsilon: 0.0,
+ ulps: 0
+ }
+ }
+ pub fn epsilon(self, epsilon: f32) -> Self {
+ F32Margin {
+ epsilon: epsilon,
+ ..self
+ }
+ }
+ pub fn ulps(self, ulps: i32) -> Self {
+ F32Margin {
+ ulps: ulps,
+ ..self
+ }
+ }
+}
+impl From<(f32, i32)> for F32Margin {
+ fn from(m: (f32, i32)) -> F32Margin {
+ F32Margin {
+ epsilon: m.0,
+ ulps: m.1
+ }
+ }
+}
+
+impl ApproxEq for f32 {
+ type Margin = F32Margin;
+
+ fn approx_eq<M: Into<Self::Margin>>(self, other: f32, margin: M) -> bool {
+ let margin = margin.into();
+
+ // Check for exact equality first. This is often true, and so we get the
+ // performance benefit of only doing one compare in most cases.
+ self==other ||
+
+ // Perform epsilon comparison next
+ ((self - other).abs() <= margin.epsilon) ||
+
+ {
+ // Perform ulps comparion last
+ let diff: i32 = self.ulps(&other);
+ saturating_abs_i32!(diff) <= margin.ulps
+ }
+ }
+}
+
+#[test]
+fn f32_approx_eq_test1() {
+ let f: f32 = 0.0_f32;
+ let g: f32 = -0.0000000000000005551115123125783_f32;
+ assert!(f != g); // Should not be directly equal
+ assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
+}
+#[test]
+fn f32_approx_eq_test2() {
+ let f: f32 = 0.0_f32;
+ let g: f32 = -0.0_f32;
+ assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
+}
+#[test]
+fn f32_approx_eq_test3() {
+ let f: f32 = 0.0_f32;
+ let g: f32 = 0.00000000000000001_f32;
+ assert!(f.approx_eq(g, (f32::EPSILON, 0)) == true);
+}
+#[test]
+fn f32_approx_eq_test4() {
+ let f: f32 = 0.00001_f32;
+ let g: f32 = 0.00000000000000001_f32;
+ assert!(f.approx_eq(g, (f32::EPSILON, 0)) == false);
+}
+#[test]
+fn f32_approx_eq_test5() {
+ let f: f32 = 0.1_f32;
+ let mut sum: f32 = 0.0_f32;
+ for _ in 0_isize..10_isize { sum += f; }
+ let product: f32 = f * 10.0_f32;
+ assert!(sum != product); // Should not be directly equal:
+ println!("Ulps Difference: {}",sum.ulps(&product));
+ assert!(sum.approx_eq(product, (f32::EPSILON, 1)) == true);
+ assert!(sum.approx_eq(product, F32Margin::zero()) == false);
+}
+#[test]
+fn f32_approx_eq_test6() {
+ let x: f32 = 1000000_f32;
+ let y: f32 = 1000000.1_f32;
+ assert!(x != y); // Should not be directly equal
+ assert!(x.approx_eq(y, (0.0, 2)) == true); // 2 ulps does it
+ // epsilon method no good here:
+ assert!(x.approx_eq(y, (1000.0 * f32::EPSILON, 0)) == false);
+}
+
+/// This type defines a margin within two f32s might be considered equal
+/// and is intended as the associated type for the `ApproxEq` trait.
+///
+/// Two methods are used to determine approximate equality.
+///
+/// First an epsilon method is used, considering them approximately equal if they
+/// differ by <= `epsilon`. This will only succeed for very small numbers.
+/// Note that it may succeed even if the parameters are of differing signs straddling
+/// zero.
+///
+/// The second method considers how many ULPs (units of least precision, units in
+/// the last place, which is the integer number of floating point representations
+/// that the parameters are separated by) different the parameters are and considers
+/// them approximately equal if this <= `ulps`. For large floating point numbers,
+/// an ULP can be a rather large gap, but this kind of comparison is necessary
+/// because floating point operations must round to the nearest representable value
+/// and so larger floating point values accumulate larger errors.
+#[derive(Debug, Clone, Copy)]
+pub struct F64Margin {
+ pub epsilon: f64,
+ pub ulps: i64
+}
+impl Default for F64Margin {
+ #[inline]
+ fn default() -> F64Margin {
+ F64Margin {
+ epsilon: f64::EPSILON,
+ ulps: 4
+ }
+ }
+}
+impl F64Margin {
+ #[inline]
+ pub fn zero() -> F64Margin {
+ F64Margin {
+ epsilon: 0.0,
+ ulps: 0
+ }
+ }
+ pub fn epsilon(self, epsilon: f64) -> Self {
+ F64Margin {
+ epsilon: epsilon,
+ ..self
+ }
+ }
+ pub fn ulps(self, ulps: i64) -> Self {
+ F64Margin {
+ ulps: ulps,
+ ..self
+ }
+ }
+}
+impl From<(f64, i64)> for F64Margin {
+ fn from(m: (f64, i64)) -> F64Margin {
+ F64Margin {
+ epsilon: m.0,
+ ulps: m.1
+ }
+ }
+}
+
+impl ApproxEq for f64 {
+ type Margin = F64Margin;
+
+ fn approx_eq<M: Into<Self::Margin>>(self, other: f64, margin: M) -> bool {
+ let margin = margin.into();
+
+ // Check for exact equality first. This is often true, and so we get the
+ // performance benefit of only doing one compare in most cases.
+ self==other ||
+
+ // Perform epsilon comparison next
+ ((self - other).abs() <= margin.epsilon) ||
+
+ {
+ // Perform ulps comparion last
+ let diff: i64 = self.ulps(&other);
+ saturating_abs_i64!(diff) <= margin.ulps
+ }
+ }
+}
+
+#[test]
+fn f64_approx_eq_test1() {
+ let f: f64 = 0.0_f64;
+ let g: f64 = -0.0000000000000005551115123125783_f64;
+ assert!(f != g); // Should not be directly equal
+ assert!(f.approx_eq(g, (3.0 * f64::EPSILON, 0)) == true); // 3e is enough
+ // ulps test wont ever call these equal
+}
+#[test]
+fn f64_approx_eq_test2() {
+ let f: f64 = 0.0_f64;
+ let g: f64 = -0.0_f64;
+ assert!(f.approx_eq(g, (f64::EPSILON, 0)) == true);
+}
+#[test]
+fn f64_approx_eq_test3() {
+ let f: f64 = 0.0_f64;
+ let g: f64 = 1e-17_f64;
+ assert!(f.approx_eq(g, (f64::EPSILON, 0)) == true);
+}
+#[test]
+fn f64_approx_eq_test4() {
+ let f: f64 = 0.00001_f64;
+ let g: f64 = 0.00000000000000001_f64;
+ assert!(f.approx_eq(g, (f64::EPSILON, 0)) == false);
+}
+#[test]
+fn f64_approx_eq_test5() {
+ let f: f64 = 0.1_f64;
+ let mut sum: f64 = 0.0_f64;
+ for _ in 0_isize..10_isize { sum += f; }
+ let product: f64 = f * 10.0_f64;
+ assert!(sum != product); // Should not be directly equal:
+ println!("Ulps Difference: {}",sum.ulps(&product));
+ assert!(sum.approx_eq(product, (f64::EPSILON, 0)) == true);
+ assert!(sum.approx_eq(product, (0.0, 1)) == true);
+}
+#[test]
+fn f64_approx_eq_test6() {
+ let x: f64 = 1000000_f64;
+ let y: f64 = 1000000.0000000003_f64;
+ assert!(x != y); // Should not be directly equal
+ println!("Ulps Difference: {}",x.ulps(&y));
+ assert!(x.approx_eq(y, (0.0, 3)) == true);
+}
+#[test]
+fn f64_code_triggering_issue_20() {
+ assert_eq!((-25.0f64).approx_eq(25.0, (0.00390625, 1)), false);
+}
diff --git a/third_party/rust/float-cmp/src/lib.rs b/third_party/rust/float-cmp/src/lib.rs
new file mode 100644
index 0000000000..16ad9d1cef
--- /dev/null
+++ b/third_party/rust/float-cmp/src/lib.rs
@@ -0,0 +1,196 @@
+// Copyright 2014-2018 Optimal Computing (NZ) Ltd.
+// Licensed under the MIT license. See LICENSE for details.
+
+//! # float-cmp
+//!
+//! float-cmp defines and implements traits for approximate comparison of floating point types
+//! which have fallen away from exact equality due to the limited precision available within
+//! floating point representations. Implementations of these traits are provided for `f32`
+//! and `f64` types.
+//!
+//! When I was a kid in the '80s, the programming rule was "Never compare floating point
+//! numbers". If you can follow that rule and still get the outcome you desire, then more
+//! power to you. However, if you really do need to compare them, this crate provides a
+//! reasonable way to do so.
+//!
+//! Another crate `efloat` offers another solution by providing a floating point type that
+//! tracks its error bounds as operations are performed on it, and thus can implement the
+//! `ApproxEq` trait in this crate more accurately, without specifying a `Margin`.
+//!
+//! The recommended go-to solution (although it may not be appropriate in all cases) is the
+//! `approx_eq()` function in the `ApproxEq` trait (or better yet, the macros). For `f32`
+//! and `f64`, the `F32Margin` and `F64Margin` types are provided for specifying margins as
+//! both an epsilon value and an ULPs value, and defaults are provided via `Default`
+//! (although there is no perfect default value that is always appropriate, so beware).
+//!
+//! Several other traits are provided including `Ulps`, `ApproxEqUlps`, `ApproxOrdUlps`, and
+//! `ApproxEqRatio`.
+//!
+//! ## The problem
+//!
+//! Floating point operations must round answers to the nearest representable number. Multiple
+//! operations may result in an answer different from what you expect. In the following example,
+//! the assert will fail, even though the printed output says "0.45 == 0.45":
+//!
+//! ```should_panic
+//! # extern crate float_cmp;
+//! # use float_cmp::ApproxEq;
+//! # fn main() {
+//! let a: f32 = 0.15 + 0.15 + 0.15;
+//! let b: f32 = 0.1 + 0.1 + 0.25;
+//! println!("{} == {}", a, b);
+//! assert!(a==b) // Fails, because they are not exactly equal
+//! # }
+//! ```
+//!
+//! This fails because the correct answer to most operations isn't exactly representable, and so
+//! your computer's processor chooses to represent the answer with the closest value it has
+//! available. This introduces error, and this error can accumulate as multiple operations are
+//! performed.
+//!
+//! ## The solution
+//!
+//! With `ApproxEq`, we can get the answer we intend:
+//!
+//! ```
+//! # #[macro_use]
+//! # extern crate float_cmp;
+//! # use float_cmp::{ApproxEq, F32Margin};
+//! # fn main() {
+//! let a: f32 = 0.15 + 0.15 + 0.15;
+//! let b: f32 = 0.1 + 0.1 + 0.25;
+//! println!("{} == {}", a, b);
+//! // They are equal, within 2 ulps
+//! assert!( approx_eq!(f32, a, b, ulps = 2) );
+//! # }
+//! ```
+//!
+//! ## Some explanation
+//!
+//! We use the term ULP (units of least precision, or units in the last place) to mean the
+//! difference between two adjacent floating point representations (adjacent meaning that there is
+//! no floating point number between them). This term is borrowed from prior work (personally I
+//! would have chosen "quanta"). The size of an ULP (measured as a float) varies
+//! depending on the exponents of the floating point numbers in question. That is a good thing,
+//! because as numbers fall away from equality due to the imprecise nature of their representation,
+//! they fall away in ULPs terms, not in absolute terms. Pure epsilon-based comparisons are
+//! absolute and thus don't map well to the nature of the additive error issue. They work fine
+//! for many ranges of numbers, but not for others (consider comparing -0.0000000028
+//! to +0.00000097).
+//!
+//! ## Using this crate
+//!
+//! You can use the `ApproxEq` trait directly like so:
+//!
+//! ```
+//! # extern crate float_cmp;
+//! # use float_cmp::{ApproxEq, F32Margin};
+//! # fn main() {
+//! # let a: f32 = 0.15 + 0.15 + 0.15;
+//! # let b: f32 = 0.1 + 0.1 + 0.25;
+//! assert!( a.approx_eq(b, F32Margin { ulps: 2, epsilon: 0.0 }) );
+//! # }
+//! ```
+//!
+//! We have implemented `From<(f32,i32)>` for `F32Margin` (and similarly for `F64Margin`)
+//! so you can use this shorthand:
+//!
+//! ```
+//! # extern crate float_cmp;
+//! # use float_cmp::{ApproxEq, F32Margin};
+//! # fn main() {
+//! # let a: f32 = 0.15 + 0.15 + 0.15;
+//! # let b: f32 = 0.1 + 0.1 + 0.25;
+//! assert!( a.approx_eq(b, (0.0, 2)) );
+//! # }
+//! ```
+//!
+//! With macros, it is easier to be explicit about which type of margin you wish to set,
+//! without mentioning the other one (the other one will be zero). But the downside is
+//! that you have to specify the type you are dealing with:
+//!
+//! ```
+//! # #[macro_use]
+//! # extern crate float_cmp;
+//! # use float_cmp::{ApproxEq, F32Margin};
+//! # fn main() {
+//! # let a: f32 = 0.15 + 0.15 + 0.15;
+//! # let b: f32 = 0.1 + 0.1 + 0.25;
+//! assert!( approx_eq!(f32, a, b, ulps = 2) );
+//! assert!( approx_eq!(f32, a, b, epsilon = 0.00000003) );
+//! assert!( approx_eq!(f32, a, b, epsilon = 0.00000003, ulps = 2) );
+//! assert!( approx_eq!(f32, a, b, (0.0, 2)) );
+//! assert!( approx_eq!(f32, a, b, F32Margin { epsilon: 0.0, ulps: 2 }) );
+//! assert!( approx_eq!(f32, a, b, F32Margin::default()) );
+//! assert!( approx_eq!(f32, a, b) ); // uses the default
+//! # }
+//! ```
+//!
+//! For most cases, I recommend you use a smallish integer for the `ulps` parameter (1 to 5
+//! or so), and a similar small multiple of the floating point's EPSILON constant (1.0 to 5.0
+//! or so), but there are *plenty* of cases where this is insufficient.
+//!
+//! ## Implementing these traits
+//!
+//! You can implement `ApproxEq` for your own complex types like shown below.
+//! The floating point type `F` must be `Copy`, but for large types you can implement
+//! it for references to your type as shown.
+//!
+//! ```
+//! use float_cmp::ApproxEq;
+//!
+//! pub struct Vec2<F> {
+//! pub x: F,
+//! pub y: F,
+//! }
+//!
+//! impl<'a, M: Copy + Default, F: Copy + ApproxEq<Margin=M>> ApproxEq for &'a Vec2<F> {
+//! type Margin = M;
+//!
+//! fn approx_eq<T: Into<Self::Margin>>(self, other: Self, margin: T) -> bool {
+//! let margin = margin.into();
+//! self.x.approx_eq(other.x, margin)
+//! && self.y.approx_eq(other.y, margin)
+//! }
+//! }
+//! ```
+//!
+//! ## Non floating-point types
+//!
+//! `ApproxEq` can be implemented for non floating-point types as well, since `Margin` is
+//! an associated type.
+//!
+//! The `efloat` crate implements (or soon will implement) `ApproxEq` for a compound type
+//! that tracks floating point error bounds by checking if the error bounds overlap.
+//! In that case `type Margin = ()`.
+//!
+//! ## Inspiration
+//!
+//! This crate was inspired by this Random ASCII blog post:
+//!
+//! [https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/)
+
+#[cfg(feature="num-traits")]
+extern crate num_traits;
+
+#[macro_use]
+mod macros;
+
+pub fn trials() {
+ println!("are they approximately equal?: {:?}",
+ approx_eq!(f32, 1.0, 1.0000001));
+}
+
+mod ulps;
+pub use self::ulps::Ulps;
+
+mod ulps_eq;
+pub use self::ulps_eq::ApproxEqUlps;
+
+mod eq;
+pub use self::eq::{ApproxEq, F32Margin, F64Margin};
+
+#[cfg(feature="num-traits")]
+mod ratio;
+#[cfg(feature="num-traits")]
+pub use self::ratio::ApproxEqRatio;
diff --git a/third_party/rust/float-cmp/src/macros.rs b/third_party/rust/float-cmp/src/macros.rs
new file mode 100644
index 0000000000..7eeaa30fd9
--- /dev/null
+++ b/third_party/rust/float-cmp/src/macros.rs
@@ -0,0 +1,77 @@
+
+#[macro_export]
+macro_rules! approx_eq {
+ ($typ:ty, $lhs:expr, $rhs:expr) => {
+ {
+ let m: <$typ as $crate::ApproxEq>::Margin = Default::default();
+ <$typ as $crate::ApproxEq>::approx_eq($lhs, $rhs, m)
+ }
+ };
+ ($typ:ty, $lhs:expr, $rhs:expr $(, $set:ident = $val:expr)*) => {
+ {
+ let m = <$typ as $crate::ApproxEq>::Margin::zero()$(.$set($val))*;
+ <$typ as $crate::ApproxEq>::approx_eq($lhs, $rhs, m)
+ }
+ };
+ ($typ:ty, $lhs:expr, $rhs:expr, $marg:expr) => {
+ {
+ <$typ as $crate::ApproxEq>::approx_eq($lhs, $rhs, $marg)
+ }
+ };
+}
+
+// Until saturating_abs() comes out of nightly, we have to code it ourselves.
+macro_rules! saturating_abs_i32 {
+ ($val:expr) => {
+ if $val.is_negative() {
+ match $val.checked_neg() {
+ Some(v) => v,
+ None => std::i32::MAX
+ }
+ } else {
+ $val
+ }
+ };
+}
+macro_rules! saturating_abs_i64 {
+ ($val:expr) => {
+ if $val.is_negative() {
+ match $val.checked_neg() {
+ Some(v) => v,
+ None => std::i64::MAX
+ }
+ } else {
+ $val
+ }
+ };
+}
+
+#[test]
+fn test_macro() {
+ let a: f32 = 0.15 + 0.15 + 0.15;
+ let b: f32 = 0.1 + 0.1 + 0.25;
+ assert!( approx_eq!(f32, a, b) ); // uses the default
+ assert!( approx_eq!(f32, a, b, ulps = 2) );
+ assert!( approx_eq!(f32, a, b, epsilon = 0.00000003) );
+ assert!( approx_eq!(f32, a, b, epsilon = 0.00000003, ulps = 2) );
+ assert!( approx_eq!(f32, a, b, (0.0, 2)) );
+}
+
+#[test]
+fn test_macro_2() {
+ assert!( approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64) );
+ assert!( approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, ulps=3) );
+ assert!( approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, epsilon=0.0000000004) );
+ assert!( approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, (0.0000000004, 0)) );
+ assert!( approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, (0.0, 3)) );
+}
+
+#[test]
+fn test_macro_3() {
+ use crate::F32Margin;
+
+ let a: f32 = 0.15 + 0.15 + 0.15;
+ let b: f32 = 0.1 + 0.1 + 0.25;
+ assert!( approx_eq!(f32, a, b, F32Margin { epsilon: 0.0, ulps: 2 }) );
+ assert!( approx_eq!(f32, a, b, F32Margin::default()) );
+}
diff --git a/third_party/rust/float-cmp/src/ratio.rs b/third_party/rust/float-cmp/src/ratio.rs
new file mode 100644
index 0000000000..0a8654bba8
--- /dev/null
+++ b/third_party/rust/float-cmp/src/ratio.rs
@@ -0,0 +1,142 @@
+// Copyright 2014-2018 Optimal Computing (NZ) Ltd.
+// Licensed under the MIT license. See LICENSE for details.
+
+use std::cmp::PartialOrd;
+use std::ops::{Sub,Div,Neg};
+use num_traits::Zero;
+
+/// ApproxEqRatio is a trait for approximate equality comparisons bounding the ratio
+/// of the difference to the larger.
+pub trait ApproxEqRatio : Div<Output = Self> + Sub<Output = Self> + Neg<Output = Self>
+ + PartialOrd + Zero + Sized + Copy
+{
+ /// This method tests if `self` and `other` are nearly equal by bounding the
+ /// difference between them to some number much less than the larger of the two.
+ /// This bound is set as the ratio of the difference to the larger.
+ fn approx_eq_ratio(&self, other: &Self, ratio: Self) -> bool {
+
+ // Not equal if signs are not equal
+ if *self < Self::zero() && *other > Self::zero() { return false; }
+ if *self > Self::zero() && *other < Self::zero() { return false; }
+
+ // Handle all zero cases
+ match (*self == Self::zero(), *other == Self::zero()) {
+ (true,true) => return true,
+ (true,false) => return false,
+ (false,true) => return false,
+ _ => { }
+ }
+
+ // abs
+ let (s,o) = if *self < Self::zero() {
+ (-*self, -*other)
+ } else {
+ (*self, *other)
+ };
+
+ let (smaller,larger) = if s < o {
+ (s,o)
+ } else {
+ (o,s)
+ };
+ let difference: Self = larger.sub(smaller);
+ let actual_ratio: Self = difference.div(larger);
+ actual_ratio < ratio
+ }
+
+ /// This method tests if `self` and `other` are not nearly equal by bounding the
+ /// difference between them to some number much less than the larger of the two.
+ /// This bound is set as the ratio of the difference to the larger.
+ #[inline]
+ fn approx_ne_ratio(&self, other: &Self, ratio: Self) -> bool {
+ !self.approx_eq_ratio(other, ratio)
+ }
+}
+
+impl ApproxEqRatio for f32 { }
+
+#[test]
+fn f32_approx_eq_ratio_test1() {
+ let x: f32 = 0.00004_f32;
+ let y: f32 = 0.00004001_f32;
+ assert!(x.approx_eq_ratio(&y, 0.00025));
+ assert!(y.approx_eq_ratio(&x, 0.00025));
+ assert!(x.approx_ne_ratio(&y, 0.00024));
+ assert!(y.approx_ne_ratio(&x, 0.00024));
+}
+
+#[test]
+fn f32_approx_eq_ratio_test2() {
+ let x: f32 = 0.00000000001_f32;
+ let y: f32 = 0.00000000005_f32;
+ assert!(x.approx_eq_ratio(&y, 0.81));
+ assert!(y.approx_ne_ratio(&x, 0.79));
+}
+
+#[test]
+fn f32_approx_eq_ratio_test_zero_eq_zero_returns_true() {
+ let x: f32 = 0.0_f32;
+ assert!(x.approx_eq_ratio(&x,0.1) == true);
+}
+
+#[test]
+fn f32_approx_eq_ratio_test_zero_ne_zero_returns_false() {
+ let x: f32 = 0.0_f32;
+ assert!(x.approx_ne_ratio(&x,0.1) == false);
+}
+
+#[test]
+fn f32_approx_eq_ratio_test_against_a_zero_is_false() {
+ let x: f32 = 0.0_f32;
+ let y: f32 = 0.1_f32;
+ assert!(x.approx_eq_ratio(&y,0.1) == false);
+ assert!(y.approx_eq_ratio(&x,0.1) == false);
+}
+
+#[test]
+fn f32_approx_eq_ratio_test_negative_numbers() {
+ let x: f32 = -3.0_f32;
+ let y: f32 = -4.0_f32;
+ // -3 and -4 should not be equal at a ratio of 0.1
+ assert!(x.approx_eq_ratio(&y,0.1) == false);
+}
+
+impl ApproxEqRatio for f64 { }
+
+#[test]
+fn f64_approx_eq_ratio_test1() {
+ let x: f64 = 0.000000004_f64;
+ let y: f64 = 0.000000004001_f64;
+ assert!(x.approx_eq_ratio(&y, 0.00025));
+ assert!(y.approx_eq_ratio(&x, 0.00025));
+ assert!(x.approx_ne_ratio(&y, 0.00024));
+ assert!(y.approx_ne_ratio(&x, 0.00024));
+}
+
+#[test]
+fn f64_approx_eq_ratio_test2() {
+ let x: f64 = 0.0000000000000001_f64;
+ let y: f64 = 0.0000000000000005_f64;
+ assert!(x.approx_eq_ratio(&y, 0.81));
+ assert!(y.approx_ne_ratio(&x, 0.79));
+}
+
+#[test]
+fn f64_approx_eq_ratio_test_zero_eq_zero_returns_true() {
+ let x: f64 = 0.0_f64;
+ assert!(x.approx_eq_ratio(&x,0.1) == true);
+}
+
+#[test]
+fn f64_approx_eq_ratio_test_zero_ne_zero_returns_false() {
+ let x: f64 = 0.0_f64;
+ assert!(x.approx_ne_ratio(&x,0.1) == false);
+}
+
+#[test]
+fn f64_approx_eq_ratio_test_negative_numbers() {
+ let x: f64 = -3.0_f64;
+ let y: f64 = -4.0_f64;
+ // -3 and -4 should not be equal at a ratio of 0.1
+ assert!(x.approx_eq_ratio(&y,0.1) == false);
+}
diff --git a/third_party/rust/float-cmp/src/ulps.rs b/third_party/rust/float-cmp/src/ulps.rs
new file mode 100644
index 0000000000..51f186f94e
--- /dev/null
+++ b/third_party/rust/float-cmp/src/ulps.rs
@@ -0,0 +1,240 @@
+// Copyright 2014-2018 Optimal Computing (NZ) Ltd.
+// Licensed under the MIT license. See LICENSE for details.
+
+#[cfg(feature="num_traits")]
+use num_traits::NumCast;
+
+/// A trait for floating point numbers which computes the number of representable
+/// values or ULPs (Units of Least Precision) that separate the two given values.
+#[cfg(feature="num_traits")]
+pub trait Ulps {
+ type U: Copy + NumCast;
+
+ /// The number of representable values or ULPs (Units of Least Precision) that
+ /// separate `self` and `other`. The result `U` is an integral value, and will
+ /// be zero if `self` and `other` are exactly equal.
+ fn ulps(&self, other: &Self) -> <Self as Ulps>::U;
+
+ /// The next representable number above this one
+ fn next(&self) -> Self;
+
+ /// The previous representable number below this one
+ fn prev(&self) -> Self;
+}
+
+#[cfg(not(feature="num_traits"))]
+pub trait Ulps {
+ type U: Copy;
+
+ /// The number of representable values or ULPs (Units of Least Precision) that
+ /// separate `self` and `other`. The result `U` is an integral value, and will
+ /// be zero if `self` and `other` are exactly equal.
+ fn ulps(&self, other: &Self) -> <Self as Ulps>::U;
+
+ /// The next representable number above this one
+ fn next(&self) -> Self;
+
+ /// The previous representable number below this one
+ fn prev(&self) -> Self;
+}
+
+impl Ulps for f32 {
+ type U = i32;
+
+ fn ulps(&self, other: &f32) -> i32 {
+
+ // IEEE754 defined floating point storage representation to
+ // maintain their order when their bit patterns are interpreted as
+ // integers. This is a huge boon to the task at hand, as we can
+ // reinterpret them as integers to find out how many ULPs apart any
+ // two floats are
+
+ // Setup integer representations of the input
+ let ai32: i32 = self.to_bits() as i32;
+ let bi32: i32 = other.to_bits() as i32;
+
+ ai32.wrapping_sub(bi32)
+ }
+
+ fn next(&self) -> Self {
+ if self.is_infinite() && *self > 0.0 {
+ *self
+ } else if *self == -0.0 && self.is_sign_negative() {
+ 0.0
+ } else {
+ let mut u = self.to_bits();
+ if *self >= 0.0 {
+ u += 1;
+ } else {
+ u -= 1;
+ }
+ f32::from_bits(u)
+ }
+ }
+
+ fn prev(&self) -> Self {
+ if self.is_infinite() && *self < 0.0 {
+ *self
+ } else if *self == 0.0 && self.is_sign_positive() {
+ -0.0
+ } else {
+ let mut u = self.to_bits();
+ if *self <= -0.0 {
+ u += 1;
+ } else {
+ u -= 1;
+ }
+ f32::from_bits(u)
+ }
+ }
+}
+
+#[test]
+fn f32_ulps_test1() {
+ let x: f32 = 1000000_f32;
+ let y: f32 = 1000000.1_f32;
+ println!("DIST IS {}",x.ulps(&y));
+ assert!(x.ulps(&y) == -2);
+}
+
+#[test]
+fn f32_ulps_test2() {
+ let pzero: f32 = f32::from_bits(0x00000000_u32);
+ let nzero: f32 = f32::from_bits(0x80000000_u32);
+ println!("DIST IS {}",pzero.ulps(&nzero));
+ assert!(pzero.ulps(&nzero) == -2147483648);
+}
+#[test]
+fn f32_ulps_test3() {
+ let pinf: f32 = f32::from_bits(0x7f800000_u32);
+ let ninf: f32 = f32::from_bits(0xff800000_u32);
+ println!("DIST IS {}",pinf.ulps(&ninf));
+ assert!(pinf.ulps(&ninf) == -2147483648);
+}
+
+#[test]
+fn f32_ulps_test4() {
+ let x: f32 = f32::from_bits(0x63a7f026_u32);
+ let y: f32 = f32::from_bits(0x63a7f023_u32);
+ println!("DIST IS {}",x.ulps(&y));
+ assert!(x.ulps(&y) == 3);
+}
+
+#[test]
+fn f32_ulps_test5() {
+ let x: f32 = 2.0;
+ let ulps: i32 = x.to_bits() as i32;
+ let x2: f32 = <f32>::from_bits(ulps as u32);
+ assert_eq!(x, x2);
+}
+
+#[test]
+fn f32_ulps_test6() {
+ let negzero: f32 = -0.;
+ let zero: f32 = 0.;
+ assert_eq!(negzero.next(), zero);
+ assert_eq!(zero.prev(), negzero);
+ assert!(negzero.prev() < 0.0);
+ assert!(zero.next() > 0.0);
+}
+
+impl Ulps for f64 {
+ type U = i64;
+
+ fn ulps(&self, other: &f64) -> i64 {
+
+ // IEEE754 defined floating point storage representation to
+ // maintain their order when their bit patterns are interpreted as
+ // integers. This is a huge boon to the task at hand, as we can
+ // reinterpret them as integers to find out how many ULPs apart any
+ // two floats are
+
+ // Setup integer representations of the input
+ let ai64: i64 = self.to_bits() as i64;
+ let bi64: i64 = other.to_bits() as i64;
+
+ ai64.wrapping_sub(bi64)
+ }
+
+ fn next(&self) -> Self {
+ if self.is_infinite() && *self > 0.0 {
+ *self
+ } else if *self == -0.0 && self.is_sign_negative() {
+ 0.0
+ } else {
+ let mut u = self.to_bits();
+ if *self >= 0.0 {
+ u += 1;
+ } else {
+ u -= 1;
+ }
+ f64::from_bits(u)
+ }
+ }
+
+ fn prev(&self) -> Self {
+ if self.is_infinite() && *self < 0.0 {
+ *self
+ } else if *self == 0.0 && self.is_sign_positive() {
+ -0.0
+ } else {
+ let mut u = self.to_bits();
+ if *self <= -0.0 {
+ u += 1;
+ } else {
+ u -= 1;
+ }
+ f64::from_bits(u)
+ }
+ }
+}
+
+#[test]
+fn f64_ulps_test1() {
+ let x: f64 = 1000000_f64;
+ let y: f64 = 1000000.00000001_f64;
+ println!("DIST IS {}",x.ulps(&y));
+ assert!(x.ulps(&y) == -86);
+}
+
+#[test]
+fn f64_ulps_test2() {
+ let pzero: f64 = f64::from_bits(0x0000000000000000_u64);
+ let nzero: f64 = f64::from_bits(0x8000000000000000_u64);
+ println!("DIST IS {}",pzero.ulps(&nzero));
+ assert!(pzero.ulps(&nzero) == -9223372036854775808i64);
+}
+#[test]
+fn f64_ulps_test3() {
+ let pinf: f64 = f64::from_bits(0x7f80000000000000_u64);
+ let ninf: f64 = f64::from_bits(0xff80000000000000_u64);
+ println!("DIST IS {}",pinf.ulps(&ninf));
+ assert!(pinf.ulps(&ninf) == -9223372036854775808i64);
+}
+
+#[test]
+fn f64_ulps_test4() {
+ let x: f64 = f64::from_bits(0xd017f6cc63a7f026_u64);
+ let y: f64 = f64::from_bits(0xd017f6cc63a7f023_u64);
+ println!("DIST IS {}",x.ulps(&y));
+ assert!(x.ulps(&y) == 3);
+}
+
+#[test]
+fn f64_ulps_test5() {
+ let x: f64 = 2.0;
+ let ulps: i64 = x.to_bits() as i64;
+ let x2: f64 = <f64>::from_bits(ulps as u64);
+ assert_eq!(x, x2);
+}
+
+#[test]
+fn f64_ulps_test6() {
+ let negzero: f64 = -0.;
+ let zero: f64 = 0.;
+ assert_eq!(negzero.next(), zero);
+ assert_eq!(zero.prev(), negzero);
+ assert!(negzero.prev() < 0.0);
+ assert!(zero.next() > 0.0);
+}
+
diff --git a/third_party/rust/float-cmp/src/ulps_eq.rs b/third_party/rust/float-cmp/src/ulps_eq.rs
new file mode 100644
index 0000000000..9dc0c37f40
--- /dev/null
+++ b/third_party/rust/float-cmp/src/ulps_eq.rs
@@ -0,0 +1,119 @@
+// Copyright 2014-2018 Optimal Computing (NZ) Ltd.
+// Licensed under the MIT license. See LICENSE for details.
+
+use super::Ulps;
+
+/// ApproxEqUlps is a trait for approximate equality comparisons.
+/// The associated type Flt is a floating point type which implements Ulps, and is
+/// required so that this trait can be implemented for compound types (e.g. vectors),
+/// not just for the floats themselves.
+pub trait ApproxEqUlps {
+ type Flt: Ulps;
+
+ /// This method tests for `self` and `other` values to be approximately equal
+ /// within ULPs (Units of Least Precision) floating point representations.
+ /// Differing signs are always unequal with this method, and zeroes are only
+ /// equal to zeroes. Use approx_eq() from the ApproxEq trait if that is more
+ /// appropriate.
+ fn approx_eq_ulps(&self, other: &Self, ulps: <Self::Flt as Ulps>::U) -> bool;
+
+ /// This method tests for `self` and `other` values to be not approximately
+ /// equal within ULPs (Units of Least Precision) floating point representations.
+ /// Differing signs are always unequal with this method, and zeroes are only
+ /// equal to zeroes. Use approx_eq() from the ApproxEq trait if that is more
+ /// appropriate.
+ #[inline]
+ fn approx_ne_ulps(&self, other: &Self, ulps: <Self::Flt as Ulps>::U) -> bool {
+ !self.approx_eq_ulps(other, ulps)
+ }
+}
+
+impl ApproxEqUlps for f32 {
+ type Flt = f32;
+
+ fn approx_eq_ulps(&self, other: &f32, ulps: i32) -> bool {
+ // -0 and +0 are drastically far in ulps terms, so
+ // we need a special case for that.
+ if *self==*other { return true; }
+
+ // Handle differing signs as a special case, even if
+ // they are very close, most people consider them
+ // unequal.
+ if self.is_sign_positive() != other.is_sign_positive() { return false; }
+
+ let diff: i32 = self.ulps(other);
+ diff >= -ulps && diff <= ulps
+ }
+}
+
+#[test]
+fn f32_approx_eq_ulps_test1() {
+ let f: f32 = 0.1_f32;
+ let mut sum: f32 = 0.0_f32;
+ for _ in 0_isize..10_isize { sum += f; }
+ let product: f32 = f * 10.0_f32;
+ assert!(sum != product); // Should not be directly equal:
+ println!("Ulps Difference: {}",sum.ulps(&product));
+ assert!(sum.approx_eq_ulps(&product,1) == true); // But should be close
+ assert!(sum.approx_eq_ulps(&product,0) == false);
+}
+#[test]
+fn f32_approx_eq_ulps_test2() {
+ let x: f32 = 1000000_f32;
+ let y: f32 = 1000000.1_f32;
+ assert!(x != y); // Should not be directly equal
+ println!("Ulps Difference: {}",x.ulps(&y));
+ assert!(x.approx_eq_ulps(&y,2) == true);
+ assert!(x.approx_eq_ulps(&y,1) == false);
+}
+#[test]
+fn f32_approx_eq_ulps_test_zeroes() {
+ let x: f32 = 0.0_f32;
+ let y: f32 = -0.0_f32;
+ assert!(x.approx_eq_ulps(&y,0) == true);
+}
+
+impl ApproxEqUlps for f64 {
+ type Flt = f64;
+
+ fn approx_eq_ulps(&self, other: &f64, ulps: i64) -> bool {
+ // -0 and +0 are drastically far in ulps terms, so
+ // we need a special case for that.
+ if *self==*other { return true; }
+
+ // Handle differing signs as a special case, even if
+ // they are very close, most people consider them
+ // unequal.
+ if self.is_sign_positive() != other.is_sign_positive() { return false; }
+
+ let diff: i64 = self.ulps(other);
+ diff >= -ulps && diff <= ulps
+ }
+}
+
+#[test]
+fn f64_approx_eq_ulps_test1() {
+ let f: f64 = 0.1_f64;
+ let mut sum: f64 = 0.0_f64;
+ for _ in 0_isize..10_isize { sum += f; }
+ let product: f64 = f * 10.0_f64;
+ assert!(sum != product); // Should not be directly equal:
+ println!("Ulps Difference: {}",sum.ulps(&product));
+ assert!(sum.approx_eq_ulps(&product,1) == true); // But should be close
+ assert!(sum.approx_eq_ulps(&product,0) == false);
+}
+#[test]
+fn f64_approx_eq_ulps_test2() {
+ let x: f64 = 1000000_f64;
+ let y: f64 = 1000000.0000000003_f64;
+ assert!(x != y); // Should not be directly equal
+ println!("Ulps Difference: {}",x.ulps(&y));
+ assert!(x.approx_eq_ulps(&y,3) == true);
+ assert!(x.approx_eq_ulps(&y,2) == false);
+}
+#[test]
+fn f64_approx_eq_ulps_test_zeroes() {
+ let x: f64 = 0.0_f64;
+ let y: f64 = -0.0_f64;
+ assert!(x.approx_eq_ulps(&y,0) == true);
+}