1use approx::AbsDiffEq;
5
6pub const ACC: f64 = 10e-11;
8
9#[must_use]
12pub fn almost_eq(a: f64, b: f64, acc: f64) -> bool {
13 if a.is_infinite() && b.is_infinite() {
14 return a == b;
15 }
16 a.abs_diff_eq(&b, acc)
17}
18
19#[must_use]
22pub fn convergence(x: &mut f64, x_new: f64) -> bool {
23 let res = approx::relative_eq!(*x, x_new, max_relative = ACC);
24 *x = x_new;
25 res
26}
27
28#[cfg(test)]
30mod tests {
31 use super::*;
32 use crate::assert_almost_eq;
33
34 #[test]
35 fn almost_eq_within_tolerance() {
36 let a = 1.0;
37 let b = 1.0 + 0.5e-11;
38 assert!(almost_eq(a, b, ACC));
40 }
41
42 #[test]
43 fn almost_eq_outside_tolerance() {
44 let a = 1.0;
45 let b = 1.0 + 2e-10;
46 assert!(!almost_eq(a, b, ACC));
48 }
49
50 #[test]
51 fn almost_eq_infinities() {
52 assert!(almost_eq(f64::INFINITY, f64::INFINITY, ACC));
53 assert!(almost_eq(f64::NEG_INFINITY, f64::NEG_INFINITY, ACC));
54 assert!(!almost_eq(f64::INFINITY, f64::NEG_INFINITY, ACC));
55 }
56
57 #[test]
58 fn convergence_updates_and_compares() {
59 let mut x = 100.0;
60 assert!(convergence(&mut x, 100.0));
62 assert_eq!(x, 100.0);
64
65 let x_new = x * (1.0 + 0.5 * ACC);
67 assert!(convergence(&mut x, x_new));
68 assert_eq!(x, x_new);
69
70 let x_new2 = x * (1.0 + 2.0 * ACC);
72 assert!(!convergence(&mut x, x_new2));
73 assert_eq!(x, x_new2);
74 }
75
76 #[test]
77 #[allow(clippy::approx_constant)]
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}