[−][src]Trait float_eq::FloatDiff
Algorithms to compute the difference between IEEE floating point values.
This trait is used by the family of assert_float_eq!
macros to provide
debug context information when they fail, but may also be called directly.
Types are displayed to the user with fmt::Debug
.
By default this trait is implemented on f32
and f64
, and for arrays of
compatible type which have size 0 to 32 (inclusive).
How can I implement FloatDiff
?
Implementing FloatDiff
on your types is straightfoward if they're already
composed of compatible fields. You will need some way to represent difference in
ULPs for your type, probably following the same structure as the type itself.
For example, MyComplex32
here has re
and im
fields and MyComplex32UlpsDiff
follows that layout. Once you have this type, implementing the methods is a case
of calling through to the underlying implementation:
struct MyComplex32 { re: f32, im: f32, } struct MyComplex32UlpsDiff { re: <f32 as FloatDiff>::UlpsDiff, im: <f32 as FloatDiff>::UlpsDiff, } impl FloatDiff for MyComplex32 { type AbsDiff = Self; type UlpsDiff = MyComplex32UlpsDiff; fn abs_diff(&self, other: &Self) -> Self::AbsDiff { MyComplex32 { re: self.re.abs_diff(&other.re), im: self.im.abs_diff(&other.im), } } fn ulps_diff(&self, other: &Self) -> Self::UlpsDiff { MyComplex32UlpsDiff { re: self.re.ulps_diff(&other.re), im: self.im.ulps_diff(&other.im), } } } let a = MyComplex32 { re: 1.0, im: 2.0000036, }; let b = MyComplex32 { re: 1.0000001, im: 2.0, }; let abs_diff = a.abs_diff(&b); assert_eq!(abs_diff.re, 0.00000011920929); assert_eq!(abs_diff.im, 0.0000035762787); let ulps_diff = a.ulps_diff(&b); assert_eq!(ulps_diff.re, 1); assert_eq!(ulps_diff.im, 15);
If your type does not already have an underlying implementation of FloatDiff
,
then you will need to take a close look at the descriptions of the algorithms on
a method by method basis.
How can I compare two different types?
The type you can diff
with is controlled by FloatDiff
's parameter. Following
on from our previous example, if we wanted to treat f32
as a complex number
with an imaginary component of 0.0
:
struct MyComplex32 { re: f32, im: f32, } struct MyComplex32UlpsDiff { re: <f32 as FloatDiff>::UlpsDiff, im: <f32 as FloatDiff>::UlpsDiff, } impl FloatDiff<f32> for MyComplex32 { type AbsDiff = MyComplex32; type UlpsDiff = MyComplex32UlpsDiff; fn abs_diff(&self, other: &f32) -> Self::AbsDiff { MyComplex32 { re: self.re.abs_diff(other), im: self.im.abs_diff(&0.0), } } fn ulps_diff(&self, other: &f32) -> Self::UlpsDiff { MyComplex32UlpsDiff { re: self.re.ulps_diff(other), im: self.im.ulps_diff(&0.0), } } } impl FloatDiff<MyComplex32> for f32 { type AbsDiff = <MyComplex32 as FloatDiff<f32>>::AbsDiff; type UlpsDiff = <MyComplex32 as FloatDiff<f32>>::UlpsDiff; fn abs_diff(&self, other: &MyComplex32) -> Self::AbsDiff { other.abs_diff(self) } fn ulps_diff(&self, other: &MyComplex32) -> Self::UlpsDiff { other.ulps_diff(self) } } let a = 1.0000001_f32; let b = MyComplex32 { re: 1.0, im: 2.0000036, }; let abs_diff = a.abs_diff(&b); assert_eq!(abs_diff.re, 0.00000011920929); assert_eq!(abs_diff.im, 2.0000036); let ulps_diff = a.ulps_diff(&b); assert_eq!(ulps_diff.re, 1); assert_eq!(ulps_diff.im, 1_073_741_839);
Examples
assert_eq!(1.0_f32.abs_diff(&-1.0), 2.0); assert_eq!(1.0_f64.abs_diff(&-1.0), 2.0); assert_eq!(1.0_f32.ulps_diff(&1.0000001), 1); assert_eq!(1.0_f64.ulps_diff(&1.0000000000000002), 1); let a = [0.0_f32, 2.0, -2.0]; let b = [0.0_f32, -1.0, 2.0]; assert_eq!(a.abs_diff(&b), [0.0, 3.0, 4.0]);
Associated Types
type AbsDiff
Type of the absolute difference between two values.
This is often Self
, unless comparing two different types. Composite types
should probably use a type that follows the same structure as the inputs,
to make error messages more legible.
type UlpsDiff
Type of the absolute difference between two values in terms of ULPs.
This should be an unsigned integer of the same size as the underlying
floating point type, for example f32
uses u32
. Composite types should
probably use a type that follows the same structure as the inputs, to make
error messages more legible.
Required methods
fn abs_diff(&self, other: &Rhs) -> Self::AbsDiff
Always positive absolute difference between two values.
Implementations should be the equivalent of:
(self - other).abs()
fn ulps_diff(&self, other: &Rhs) -> Self::UlpsDiff
Always positive absolute difference between two values in terms of ULPs
Implementations should be the equivalent of (using f32
as an example):
let a = (self.to_bits()) as u32;
let b = (other.to_bits()) as u32;
let max = a.max(b);
let min = a.min(b);
max - min
Implementations on Foreign Types
impl<T: FloatDiff> FloatDiff<[T; 0]> for [T; 0]
[src]
This is also implemented on other arrays up to size 32 (inclusive).