|
1 | 1 | use std::fmt; |
2 | 2 | use std::ops::{Add, Div, Mul, Rem, Sub}; |
3 | 3 |
|
4 | | -/// Verify that floats are within a tolerance of each other, 1.0e-6 by default. |
| 4 | +/// Set the default tolerance for float comparison based on the type. |
| 5 | +trait Approx { |
| 6 | + const LIM: Self; |
| 7 | +} |
| 8 | + |
| 9 | +impl Approx for f16 { |
| 10 | + const LIM: Self = 1e-3; |
| 11 | +} |
| 12 | +impl Approx for f32 { |
| 13 | + const LIM: Self = 1e-6; |
| 14 | +} |
| 15 | +impl Approx for f64 { |
| 16 | + const LIM: Self = 1e-6; |
| 17 | +} |
| 18 | +impl Approx for f128 { |
| 19 | + const LIM: Self = 1e-9; |
| 20 | +} |
| 21 | + |
| 22 | +/// Determine the tolerance for values of the argument type. |
| 23 | +const fn lim_for_ty<T: Approx + Copy>(_x: T) -> T { |
| 24 | + T::LIM |
| 25 | +} |
| 26 | + |
| 27 | +/// Verify that floats are within a tolerance of each other. |
5 | 28 | macro_rules! assert_approx_eq_ { |
6 | | - ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }}; |
| 29 | + ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, $crate::floats::lim_for_ty($a)) }}; |
7 | 30 | ($a:expr, $b:expr, $lim:expr) => {{ |
8 | 31 | let (a, b) = (&$a, &$b); |
9 | 32 | let diff = (*a - *b).abs(); |
@@ -57,15 +80,6 @@ pub(crate) use assert_biteq_ as assert_biteq; |
57 | 80 | mod const_asserts { |
58 | 81 | // Shadow some assert implementations that would otherwise not compile in a const-context. |
59 | 82 | // Every macro added here also needs to be added in the `float_test!` macro below. |
60 | | - macro_rules! assert_eq { |
61 | | - ($left:expr, $right:expr $(,)?) => { |
62 | | - std::assert!($left == $right) |
63 | | - }; |
64 | | - ($left:expr, $right:expr, $($arg:tt)+) => { |
65 | | - std::assert!($left == $right, $($arg)+) |
66 | | - }; |
67 | | - } |
68 | | - pub(crate) use assert_eq; |
69 | 83 |
|
70 | 84 | macro_rules! assert_biteq { |
71 | 85 | (@inner $left:expr, $right:expr, $msg_sep:literal, $($tt:tt)*) => {{ |
@@ -94,7 +108,7 @@ mod const_asserts { |
94 | 108 | pub(crate) use assert_biteq; |
95 | 109 |
|
96 | 110 | macro_rules! assert_approx_eq { |
97 | | - ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }}; |
| 111 | + ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, $crate::floats::lim_for_ty($a)) }}; |
98 | 112 | ($a:expr, $b:expr, $lim:expr) => {{ |
99 | 113 | let (a, b) = (&$a, &$b); |
100 | 114 | let diff = (*a - *b).abs(); |
@@ -171,7 +185,9 @@ macro_rules! float_test { |
171 | 185 | $( $( #[$const_meta] )+ )? |
172 | 186 | mod const_ { |
173 | 187 | #[allow(unused)] |
174 | | - use $crate::floats::const_asserts::{assert_eq, assert_biteq, assert_approx_eq}; |
| 188 | + use super::Approx; |
| 189 | + #[allow(unused)] |
| 190 | + use $crate::floats::const_asserts::{assert_biteq, assert_approx_eq}; |
175 | 191 |
|
176 | 192 | #[test] |
177 | 193 | $( $( #[$f16_const_meta] )+ )? |
@@ -650,15 +666,15 @@ float_test! { |
650 | 666 | }, |
651 | 667 | test<Float> { |
652 | 668 | assert_biteq!((1.0 as Float).fract(), 0.0); |
653 | | - assert_approx_eq!((1.3 as Float).fract(), 0.3, 1e-3); // rounding differs between float types |
| 669 | + assert_approx_eq!((1.3 as Float).fract(), 0.3); // rounding differs between float types |
654 | 670 | assert_biteq!((1.5 as Float).fract(), 0.5); |
655 | 671 | assert_approx_eq!((1.7 as Float).fract(), 0.7); |
656 | 672 | assert_biteq!((0.5 as Float).fract(), 0.5); |
657 | 673 | assert_biteq!((0.0 as Float).fract(), 0.0); |
658 | 674 | assert_biteq!((-0.0 as Float).fract(), 0.0); |
659 | 675 | assert_biteq!((-0.5 as Float).fract(), -0.5); |
660 | 676 | assert_biteq!((-1.0 as Float).fract(), 0.0); |
661 | | - assert_approx_eq!((-1.3 as Float).fract(), -0.3, 1e-3); // rounding differs between float types |
| 677 | + assert_approx_eq!((-1.3 as Float).fract(), -0.3); // rounding differs between float types |
662 | 678 | assert_biteq!((-1.5 as Float).fract(), -0.5); |
663 | 679 | assert_approx_eq!((-1.7 as Float).fract(), -0.7); |
664 | 680 | assert_biteq!(Float::MAX.fract(), 0.0); |
|
0 commit comments