1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use crate::cgmath64::*;
use cgmath::AbsDiffEq;
use std::fmt::Debug;
pub const TOLERANCE: f64 = 1.0e-6;
pub const TOLERANCE2: f64 = TOLERANCE * TOLERANCE;
pub trait Tolerance: AbsDiffEq<Epsilon = f64> + Debug {
fn near(&self, other: &Self) -> bool { self.abs_diff_eq(other, TOLERANCE) }
fn near2(&self, other: &Self) -> bool { self.abs_diff_eq(other, TOLERANCE2) }
}
impl<T: AbsDiffEq<Epsilon = f64> + Debug> Tolerance for T {}
#[macro_export]
macro_rules! assert_near {
($left: expr, $right: expr $(,)?) => {
assert!($left.near(&$right), "assertion failed: `left` is near `right`
left: {:?},
right: {:?}", $left, $right)
};
($left: expr, $right: expr, $($arg: tt)+) => {
assert!($left.near(&$right), "assertion failed: `left` is near `right`
left: {:?},
right: {:?}: {}", $left, $right, format_args!($($arg)+))
};
}
#[test]
#[should_panic]
fn assert_near_without_msg() {
assert_near!(1.0, 2.0);
}
#[test]
#[should_panic]
fn assert_near_with_msg() {
assert_near!(1.0, 2.0, "{}", "test OK");
}
#[macro_export]
macro_rules! assert_near2 {
($left: expr, $right: expr $(,)?) => {
assert!($left.near2(&$right), "assertion failed: `left` is near `right`
left: {:?},
right: {:?}", $left, $right)
};
($left: expr, $right: expr, $($arg: tt)+) => {
assert!($left.near2(&$right), "assertion failed: `left` is near `right`
left: {:?},
right: {:?}: {}", $left, $right, format_args!($($arg)+))
};
}
#[test]
#[should_panic]
fn assert_near2_without_msg() {
assert_near2!(1.0, 2.0);
}
#[test]
#[should_panic]
fn assert_near2_with_msg() {
assert_near2!(1.0, 2.0, "{}", "test OK");
}
pub trait Origin: Tolerance + Zero {
#[inline(always)]
fn so_small(&self) -> bool { self.near(&Self::zero()) }
#[inline(always)]
fn so_small2(&self) -> bool { self.near2(&Self::zero()) }
}
impl<T: Tolerance + Zero> Origin for T {}