[][src]Trait float_eq::FloatDiff

pub trait FloatDiff<Rhs: ?Sized = Self> {
    type AbsDiff;
    type UlpsDiff;
    fn abs_diff(&self, other: &Rhs) -> Self::AbsDiff;
fn ulps_diff(&self, other: &Rhs) -> Self::UlpsDiff; }

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.

Loading content...

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
Loading content...

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).

type AbsDiff = [<T as FloatDiff>::AbsDiff; 0]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 0]

impl FloatDiff<f32> for f32[src]

type AbsDiff = Self

type UlpsDiff = u32

impl FloatDiff<f64> for f64[src]

type AbsDiff = Self

type UlpsDiff = u64

Loading content...

Implementors

Loading content...