flanker_assert_float/
lib.rs

1//! Assertions for floating-point numbers.
2
3#![no_std]
4
5extern crate alloc;
6
7use alloc::format;
8use alloc::string::String;
9
10/// Asserts that the quotient of the difference between the two floats over the largest (by magnitude)
11/// of the two floats, taken as an absolute value, is within the supplied `delta` threshold.
12///
13/// # Panics
14/// If the quotient (`gamma`) exceeds `delta`.
15pub fn assert_relative(left: f64, right: f64, delta: f64) {
16    check_relative(left, right, delta)
17        .map_err(|err| String::from("assertion failed: ") + &err)
18        .unwrap();
19}
20
21/// The absolute value of an `f64`. This is not available in a `no_std` context.
22fn abs(val: f64) -> f64 {
23    if val >= 0.0 {
24        val
25    } else {
26        -val
27    }
28}
29
30/// Checks whether the quotient of the difference between the two floats over the largest (by magnitude)
31/// of the two floats, taken as an absolute value, is within the supplied `delta` threshold.
32///
33/// # Errors
34/// If the quotient (`gamma`) exceeds `delta`.
35pub fn check_relative(left: f64, right: f64, delta: f64) -> Result<(), String> {
36    if left != 0.0 || right != 0.0 {
37        let denom = f64::max(abs(left), abs(right));
38        let gamma = abs((left - right) / denom);
39        if gamma > delta {
40            return Err(format!(
41                "(left ≉ right) left: {}, right: {}, gamma: {}",
42                left, right, gamma
43            ));
44        }
45    }
46    Ok(())
47}
48
49#[cfg(test)]
50mod tests;