#![allow(clippy::approx_constant)]
use approx::AbsDiffEq;
pub const ACC: f64 = 10e-11;
#[must_use]
pub fn almost_eq(a: f64, b: f64, acc: f64) -> bool {
if a.is_infinite() && b.is_infinite() {
return a == b;
}
a.abs_diff_eq(&b, acc)
}
#[must_use]
pub fn convergence(x: &mut f64, x_new: f64) -> bool {
let res = approx::relative_eq!(*x, x_new, max_relative = ACC);
*x = x_new;
res
}
#[cfg(test)]
mod tests {
use super::*;
use crate::assert_almost_eq;
#[test]
fn almost_eq_within_tolerance() {
let a = 1.0;
let b = 1.0 + 0.5e-11;
assert!(almost_eq(a, b, ACC));
}
#[test]
fn almost_eq_outside_tolerance() {
let a = 1.0;
let b = 1.0 + 2e-10;
assert!(!almost_eq(a, b, ACC));
}
#[test]
fn almost_eq_infinities() {
assert!(almost_eq(f64::INFINITY, f64::INFINITY, ACC));
assert!(almost_eq(f64::NEG_INFINITY, f64::NEG_INFINITY, ACC));
assert!(!almost_eq(f64::INFINITY, f64::NEG_INFINITY, ACC));
}
#[test]
fn convergence_updates_and_compares() {
let mut x = 100.0;
assert!(convergence(&mut x, 100.0));
assert_eq!(x, 100.0);
let x_new = x * (1.0 + 0.5 * ACC);
assert!(convergence(&mut x, x_new));
assert_eq!(x, x_new);
let x_new2 = x * (1.0 + 2.0 * ACC);
assert!(!convergence(&mut x, x_new2));
assert_eq!(x, x_new2);
}
#[test]
fn assert_almost_eq_macro_passes() {
assert_almost_eq!(3.14159265, 3.14159264, 1e-7);
}
#[test]
#[should_panic(expected = "assertion failed")]
fn assert_almost_eq_macro_panics() {
assert_almost_eq!(1.0, 1.001, 1e-4);
}
}