1#![allow(clippy::approx_constant)]
2use approx::AbsDiffEq;
6
7pub const ACC: f64 = 10e-11;
9
10#[must_use]
13pub fn almost_eq(a: f64, b: f64, acc: f64) -> bool {
14 if a.is_infinite() && b.is_infinite() {
15 return a == b;
16 }
17 a.abs_diff_eq(&b, acc)
18}
19
20#[must_use]
23pub fn convergence(x: &mut f64, x_new: f64) -> bool {
24 let res = approx::relative_eq!(*x, x_new, max_relative = ACC);
25 *x = x_new;
26 res
27}
28
29#[cfg(test)]
31mod tests {
32 use super::*;
33 use crate::assert_almost_eq;
34
35 #[test]
36 fn almost_eq_within_tolerance() {
37 let a = 1.0;
38 let b = 1.0 + 0.5e-11;
39 assert!(almost_eq(a, b, ACC));
41 }
42
43 #[test]
44 fn almost_eq_outside_tolerance() {
45 let a = 1.0;
46 let b = 1.0 + 2e-10;
47 assert!(!almost_eq(a, b, ACC));
49 }
50
51 #[test]
52 fn almost_eq_infinities() {
53 assert!(almost_eq(f64::INFINITY, f64::INFINITY, ACC));
54 assert!(almost_eq(f64::NEG_INFINITY, f64::NEG_INFINITY, ACC));
55 assert!(!almost_eq(f64::INFINITY, f64::NEG_INFINITY, ACC));
56 }
57
58 #[test]
59 fn convergence_updates_and_compares() {
60 let mut x = 100.0;
61 assert!(convergence(&mut x, 100.0));
63 assert_eq!(x, 100.0);
65
66 let x_new = x * (1.0 + 0.5 * ACC);
68 assert!(convergence(&mut x, x_new));
69 assert_eq!(x, x_new);
70
71 let x_new2 = x * (1.0 + 2.0 * ACC);
73 assert!(!convergence(&mut x, x_new2));
74 assert_eq!(x, x_new2);
75 }
76
77 #[test]
78 fn assert_almost_eq_macro_passes() {
79 assert_almost_eq!(3.14159265, 3.14159264, 1e-7);
81 }
82
83 #[test]
84 #[should_panic(expected = "assertion failed")]
85 fn assert_almost_eq_macro_panics() {
86 assert_almost_eq!(1.0, 1.001, 1e-4);
88 }
89}