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 std::fmt::Debug;
use crate::cgmath64::*;
use cgmath::AbsDiffEq;
pub const TOLERANCE: f64 = 1.0e-7;
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) }
fn assert_near(one: &Self, other: &Self) {
cgmath::assert_abs_diff_eq!(one, other, epsilon = TOLERANCE)
}
fn assert_near2(one: &Self, other: &Self) {
cgmath::assert_abs_diff_eq!(one, other, epsilon = TOLERANCE2)
}
}
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()) }
}
pub trait RoundByTolerance: Tolerance {
fn round_by_tolerance(&mut self) -> &mut Self;
}
impl Tolerance for f64 {}
impl Tolerance for [f64] {}
impl Origin for f64 {}
impl RoundByTolerance for f64 {
fn round_by_tolerance(&mut self) -> &mut f64 {
*self = (*self / TOLERANCE).floor() * TOLERANCE;
self
}
}
macro_rules! impl_tolerance {
($typename: ty, $($num: expr),+) => {
impl Tolerance for $typename {}
impl Origin for $typename {}
impl RoundByTolerance for $typename {
#[inline(always)]
fn round_by_tolerance(&mut self) -> &mut Self {
$(self[$num].round_by_tolerance();)+
self
}
}
};
}
impl_tolerance!(Vector1, 0);
impl_tolerance!(Vector2, 0, 1);
impl_tolerance!(Vector3, 0, 1, 2);
impl_tolerance!(Vector4, 0, 1, 2, 3);
impl_tolerance!(Matrix2, 0, 1, 2, 3);
impl_tolerance!(Matrix3, 0, 1, 2, 3, 4, 5, 6, 7, 8);
impl_tolerance!(Matrix4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
impl Tolerance for Point1 {}
impl Tolerance for Point2 {}
impl Tolerance for Point3 {}