Skip to content

Commit

Permalink
update explanation since a lot of it is not needed any more
Browse files Browse the repository at this point in the history
  • Loading branch information
LorrensP-2158466 committed Feb 15, 2025
1 parent 94d5ba5 commit 10ece47
Showing 1 changed file with 6 additions and 25 deletions.
31 changes: 6 additions & 25 deletions tests/pass/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,12 @@ use std::{f32, f64};
/// First: The ULP of a float 'a' is the smallest possible change at 'a', so the ULP difference represents how
/// many discrete floating-point steps are needed to reach 'b' from 'a'.
///
/// There are 2 techniques we can use to compute the ULP difference of 2 floating-point numbers:
/// ULP(a) is the distance between the 2 closest floating-point numbers `x` and `y` around `a`, satisfying x < a < y, x != y.
/// To use this to calculate the ULP difference we have to halve it (we need it at `a`, but we just went "up" and "down", halving it gives us this ULP).
/// Then take the difference of `b` and `a` and divide it by that ULP and finally round it.
/// We know now how many floating-point changes we have to apply to `a` to get to `b`.
///
/// ULP(a) is the difference between 'a' and the next larger representable floating-point number.
/// So to get the ULP difference of `a` and `b`, we can take the absolute difference of
/// the *unsigned integer* representation of `a` and `b`.
/// For example checking 2 f32's, which in IEEE format looks like this:
///
/// s: sign bit
/// e: exponent bits
/// m: significand bits
/// f32: s | eeee eeee | mmm mmmm mmmm mmmm mmmm mmmm
/// u32: seee eeee emmm mmmm mmmm mmmm mmmm mmmm
///
///
/// So when the sign and exponent are the same, we can compute a reasonable ULP difference.
///
/// But if you know some details of floating-point numbers, it is possible to get 2 values that sit on the border of the exponent,
/// so `a` can have exponent but `b` can have a different exponent while still being approximately equal to `a`. For this we can use
/// John Harrison's definition. Which states that ULP(a) is the distance between the 2 closest floating-point numbers
/// `x` and `y` around `a`, satisfying x < a < y, x != y. This makes the ULP of `a` twice as large as in the previous defintion and so
/// if we want to use this, we have to halve it.
/// This ULP value of `a` can then be used to find the ULP difference of `a` and `b`:
/// Take the difference of `b` and `a` and divide it by that ULP and finally round it. This is the same value as the first definition,
/// but this way can go around that exponent border problem.
///
/// If this ULP difference is less than or equal to our chosen upper bound
/// So if this ULP difference is less than or equal to our chosen upper bound
/// we can say that `a` and `b` are approximately equal, because they lie "close" enough to each other to be considered equal.
///
/// Note: We can see that checking `a` and `b` with different signs has no meaning, but we should not forget
Expand All @@ -58,6 +38,7 @@ use std::{f32, f64};
/// the same amount of "spacing" between all consecutive representable values. So even though 2 very large floating point numbers
/// have a large value difference, their ULP can still be 1, so they are still "approximatly equal",
/// but the EPSILON check would have failed.
///
fn approx_eq_check<F: Float>(
actual: F,
expected: F,
Expand Down

0 comments on commit 10ece47

Please sign in to comment.