Compare IEEE floating point primitives, structs and collections for equality.
This crate provides an API with a focus on making the choices of comparison algorithm(s) and tolerances intuitive to implementers and maintainers, and of providing clear output for debugging and development iteration.
This readme is a quick tour of the crate. For introductory material, guides and discussion see the float_eq guide.
Add this to your cargo.toml:
[dependencies]
float_eq = "1"
And, if you're using the 2015 edition, this to your crate root:
extern crate float_eq;
Then, you can import items with use
:
use float_eq::{assert_float_eq, float_eq};
This crate provides boolean comparison operations:
if (float_eq!(y_pos, 0.0, abs <= 0.000_1)) {
//...
}
And asserts:
const RECIP_REL_TOL: f32 = 0.000_366_210_94;
assert_float_eq!(x.recip(), 10.0, r2nd <= RECIP_REL_TOL);
Using absolute tolerance, relative tolerance or ULPs based [comparison algorithms].
Composite types may implement the provided extension traits to be compared on a field-by-field basis:
let a = Complex32 { re: 2.0, im: 4.000_002 };
let b = Complex32 { re: 2.000_000_5, im: 4.0 };
assert_float_eq!(a, b, ulps <= ComplexUlps32 { re: 2, im: 4 });
...and if they are homogeneous, with a uniformly applied tolerance across all fields:
assert_float_eq!(a, b, ulps_all <= 4);
Arrays of any size are supported:
let a = [1.0, -2.0, 3.0];
let b = [-1.0, 2.0, 3.5];
assert_float_eq!(a, b, abs <= [2.0, 4.0, 0.5]);
assert_float_eq!(a, b, abs_all <= 4.0);
As are tuples up to size 12 (inclusive):
let a = (1.0f32, 2.0f64);
let b = (1.5f32, -2.0f64);
assert_float_eq!(a, b, r2nd <= (0.5, 2.0));
Many standard and core types like Vec
are supported:
let a = vec![1.0, -2.0, 3.0];
let b = vec![-1.0, 2.0, 3.5];
assert_float_eq!(a, b, rmax <= vec![2.0, 2.0, 0.25]);
assert_float_eq!(a, b, rmax_all <= 2.0);
There are blanket trait impls for comparing mutable and immutable reference
types, the contents of Cell
, RefCell
, Rc
, Arc
and Box
instances, as
well as for slices, Option
, Vec
, VecDeque
, LinkedList
, BTreeMap
and
HashMap
.
The extension traits may be derived for non-generic structs and tuple structs:
#[derive_float_eq(
ulps_tol = "PointUlps",
ulps_tol_derive = "Clone, Copy, Debug, PartialEq",
debug_ulps_diff = "PointUlpsDebugUlpsDiff",
debug_ulps_diff_derive = "Clone, Copy, Debug, PartialEq",
all_tol = "f64"
)]
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Point {
pub x: f64,
pub y: f64,
}
let a = Point { x: 1.0, y: -2.0 };
let c = Point {
x: 1.000_000_000_000_000_9,
y: -2.000_000_000_000_001_3
};
assert_float_eq!(a, c, ulps <= PointUlps { x: 4, y: 3 });
assert_float_eq!(a, c, ulps_all <= 4);
Asserts provide additional useful context information. For example:
assert_float_eq!(4.0f32, 4.000_008, rmax <= 0.000_001);
Panics with this error message:
thread 'main' panicked at 'assertion failed: `float_eq!(left, right, rmax <= t)`
left: `4.0`,
right: `4.000008`,
abs_diff: `0.000008106232`,
ulps_diff: `Some(17)`,
[rmax] t: `0.000004000008`', assert_failure.rs:15:5
Where [rmax] t
shows the tolerance value that the absolute difference was
compared against after being appropriately scaled.
This crate can be used without the standard library (#![no_std]
) by disabling
the default std
feature. Use this in Cargo.toml
:
[dependencies.float_eq]
version = "1"
default-features = false
Other optional features:
num::Complex
where it is instanced with a
compatible type.The approx
, float-cmp
, assert_float_eq
and is_close
crates provide
similar floating point comparison capabilities to float_eq
. The almost
crate
divides its API into comparison of floats against zero and non-zero values. The
efloat
crate provides an f32
equivalent type that tracks the maximum
possible error bounds that may have occured due to rounding.
The ieee754
crate is not a comparison library, but provides useful
functionality for decomposing floats into their component parts, iterating over
representable values and working with ULPs directly, amoung other things.
Constructive feedback, suggestions and contributions welcomed, please open an issue.
Release information is available in CHANGELOG.md.
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in float_eq by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.