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;