1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
# 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:
```rust
extern crate float_eq;
```
Then, you can import items with `use`:
```rust
use float_eq::{assert_float_eq, float_eq};
```
## Comparisons
This crate provides boolean comparison operations:
```rust
if (float_eq!(y_pos, 0.0, abs <= 0.000_1)) {
//...
}
```
And asserts:
```rust
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:
```rust
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:
```rust
assert_float_eq!(a, b, ulps_all <= 4);
```
Arrays of any size are supported:
```rust
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):
```rust
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:
```rust
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:
```rust
#[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:
```rust
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](CHANGELOG.md).
[comparison algorithms]: https://jtempest.github.io/float_eq-rs/book/background/float_comparison_algorithms.html
[open an issue]: https://github.com/jtempest/float_eq-rs/issues/
[the float_eq guide]: https://jtempest.github.io/float_eq-rs/book/introduction.html
[`almost`]: https://crates.io/crates/almost
[`approx`]: https://crates.io/crates/approx
[`assert_float_eq`]: https://crates.io/crates/assert_float_eq
[`efloat`]: https://crates.io/crates/efloat
[`float-cmp`]: https://crates.io/crates/float-cmp
[`ieee754`]: https://crates.io/crates/ieee754
[`is_close`]: https://docs.rs/is_close/latest/is_close/
|