15 releases (2 stable)
1.0.1 | Oct 12, 2022 |
---|---|
1.0.0 | Jun 2, 2022 |
0.7.0 | Oct 3, 2021 |
0.6.1 | Jul 31, 2021 |
0.4.1 | Jun 22, 2020 |
#18 in Algorithms
121,750 downloads per month
Used in 83 crates
(57 directly)
195KB
4K
SLoC
float_eq
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.
Usage
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};
Comparisons
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
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
.
Derivable
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);
Error messages
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.
Optional features
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:
- derive — provides custom derive macros for all traits.
- num — blanket trait impls for
num::Complex
where it is instanced with a compatible type.
Related efforts
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.
Contributing
Constructive feedback, suggestions and contributions welcomed, please open an issue.
Changelog
Release information is available in CHANGELOG.md.
Dependencies
~0–280KB