geomath/
macros.rs

1/// Similar to `assert_eq` but with a tolerance interval
2#[macro_export]
3macro_rules! assert_near {
4    ($val: expr, $exp: expr, $tol: expr) => {
5        assert!(
6        ($val - $exp).abs() < $tol,
7        "Approximation failed\nvalue: {}\nexpected: {}\n tolerance: {}",
8        $val, $exp, $tol
9        )
10    }
11}
12
13/// Implementation of basic vector space features
14#[macro_export]
15macro_rules! impl_vector {
16    ($VectorN:ident { $($field:ident),+ }, $n: expr, $label: ident) => {
17        impl From<f64> for $VectorN {
18            fn from(s: f64) -> Self {
19                $VectorN { $($field: s),+ }
20            }
21        }
22
23        impl $VectorN {
24            #[inline]
25            pub const fn new($($field: f64),+) -> Self {
26                $VectorN { $($field: $field),+ }
27            }
28        }
29
30        impl Initializer for $VectorN {
31            #[inline]
32            fn zeros() -> Self {
33                $VectorN { $($field: 0.),+ }
34            }
35
36            #[inline]
37            fn ones() -> Self {
38                $VectorN { $($field: 1.),+ }
39            }
40        }
41
42        impl Reset<$VectorN> for $VectorN {
43            #[inline]
44            fn reset0(&mut self) -> &mut Self {
45                $(self.$field = 0.;)+
46                self
47            }
48
49            #[inline]
50            fn reset1(&mut self) -> &mut Self {
51                $(self.$field = 1.;)+
52                self
53            }
54
55            #[inline]
56            fn reset(&mut self, val: &$VectorN) -> &mut Self {
57                $(self.$field = val.$field;)+
58                self
59            }
60        }
61
62        impl Metric for $VectorN {
63
64            #[inline]
65            fn dot(&self, rhs: &Self) -> f64 {
66                let mut ret = 0.;
67                $(ret += self.$field * rhs.$field;)+
68                ret
69            }
70
71            #[inline]
72            fn magnitude2(&self) -> f64 {
73                let mut ret = 0.;
74                $(ret += self.$field * self.$field;)+
75                ret
76            }
77
78            #[inline]
79            fn magnitude(&self) -> f64 {
80                self.magnitude2().sqrt()
81            }
82
83            #[inline]
84            fn distance2(&self, rhs: &Self) -> f64 {
85                let mut ret = 0.;
86                let mut distance;
87                $(
88                    distance = self.$field - rhs.$field;
89                    ret += distance * distance;
90                )+
91                ret
92            }
93
94            #[inline]
95            fn distance(&self, rhs: &Self) -> f64 {
96                self.distance2(rhs).sqrt()
97            }
98
99            #[inline]
100            fn set_normalized(&mut self) -> &mut Self {
101                let magnitude = self.magnitude();
102                $(self.$field /= magnitude;)+
103                self
104            }
105        }
106
107        impl BitOr<$VectorN> for $VectorN {
108            type Output = f64;
109
110            #[inline]
111            fn bitor(self, rhs: $VectorN) -> Self::Output {
112                self.dot(&rhs)
113            }
114        }
115
116        impl Not for $VectorN {
117            type Output = f64;
118
119            #[inline]
120            fn not(self) -> Self::Output {
121                self.magnitude()
122            }
123        }
124
125        impl Rem<$VectorN> for $VectorN {
126            type Output = f64;
127
128            #[inline]
129            fn rem(self, rhs: Self) -> Self::Output {
130                self.distance(&rhs)
131            }
132        }
133
134        impl PartialEq for $VectorN {
135
136            #[inline]
137            fn eq(&self, other: &Self) -> bool {
138                self.distance2(other) < std::f64::MIN_POSITIVE
139            }
140
141            #[inline]
142            fn ne(&self, other: &Self) -> bool {
143                self.distance2(other) >= std::f64::MIN_POSITIVE
144            }
145        }
146
147        impl Add<$VectorN> for $VectorN {
148            type Output = Self;
149
150            #[inline]
151            fn add(self, rhs: Self) -> Self::Output {
152                $VectorN { $($field: self.$field + rhs.$field),+ }
153            }
154        }
155
156        impl AddAssign<$VectorN> for $VectorN {
157
158            #[inline]
159            fn add_assign(&mut self, rhs: $VectorN) {
160                $(self.$field += rhs.$field;)+
161            }
162        }
163
164        impl Sub<$VectorN> for $VectorN {
165            type Output = Self;
166
167            #[inline]
168            fn sub(self, rhs: Self) -> Self::Output {
169                $VectorN { $($field: self.$field - rhs.$field),+ }
170            }
171        }
172
173        impl SubAssign<$VectorN> for $VectorN {
174
175            #[inline]
176            fn sub_assign(&mut self, rhs: $VectorN) {
177                $(self.$field -= rhs.$field;)+
178            }
179        }
180
181        impl Neg for $VectorN {
182            type Output = Self;
183
184            #[inline]
185            fn neg(self) -> Self::Output {
186                $VectorN { $($field: -self.$field),+ }
187            }
188        }
189
190        impl Mul<f64> for $VectorN {
191            type Output = Self;
192
193            #[inline]
194            fn mul(self, rhs: f64) -> Self::Output {
195                $VectorN { $($field: self.$field * rhs),+ }
196            }
197        }
198
199        impl MulAssign<f64> for $VectorN {
200
201            #[inline]
202            fn mul_assign(&mut self, rhs: f64) {
203                $(self.$field *= rhs;)+
204            }
205        }
206
207        impl Div<f64> for $VectorN {
208            type Output = Self;
209
210            #[inline]
211            fn div(self, rhs: f64) -> Self::Output {
212                $VectorN { $($field: self.$field / rhs),+ }
213            }
214        }
215
216        impl DivAssign<f64> for $VectorN {
217
218            #[inline]
219            fn div_assign(&mut self, rhs: f64) {
220                $(self.$field /= rhs;)+
221            }
222        }
223
224        impl Interpolation for $VectorN {
225            fn set_lerp(&mut self, other: &Self, s: f64) -> &mut Self {
226                $(self.$field += (other.$field - self.$field) * s;)+
227                self
228            }
229
230            fn set_herp(&mut self, other: &Self, other1: &Self, other2: &Self, s: f64) -> &mut Self {
231                let s2 = s * s;
232                let t0 = s2 * (2. * s - 3.) + 1.;
233                let t1 = s2 * (s - 2.) + s;
234                let t2 = s2 * (s - 1.);
235                let t3 = s2 * (3. - 2. * s);
236                $(self.$field = self.$field * t0 + other1.$field * t1 + other2.$field * t2 + other.$field * t3;)+
237                self
238            }
239
240            fn set_berp(&mut self, other: &Self, other1: &Self, other2: &Self, s: f64) -> &mut Self {
241                let s2 = s * s;
242                let inv = 1. - s;
243                let inv2 = inv * inv;
244                let t0 = inv2 * inv;
245                let t1 = 3. * s * inv2;
246                let t2 = 3. * s2 * inv;
247                let t3 = s2 * s;
248                $(self.$field = self.$field * t0 + other1.$field * t1 + other2.$field * t2 + other.$field * t3;)+
249                self
250            }
251        }
252
253        #[inline]
254        pub const fn $label($($field: f64),+) -> $VectorN {
255            $VectorN::new($($field),+)
256        }
257    }
258}
259
260/// Vector debug trait
261#[macro_export]
262macro_rules! impl_debug_vector {
263($VectorN:ident { $($field:ident),+ }) => {
264        impl Debug for $VectorN {
265            fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
266                let mut buffer = String::from("(");
267                if self.magnitude() > 1000. {
268                    $(buffer += format!(" {:.3e} ", self.$field).as_str();)+
269                } else {
270                    $(buffer += format!(" {:.3} ", self.$field).as_str();)+
271                }
272                buffer += ")";
273                write!(f, "{}", buffer)
274            }
275        }
276    }
277}
278
279/// Matrix debug trait
280#[macro_export]
281macro_rules! impl_debug_matrix {
282($MatrixN:ident) => {
283        impl Debug for $MatrixN {
284            fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
285                let rows = self.rows();
286                let mut buffer = String::from("");
287                for row in rows.iter() {
288                    buffer += &format!("\n{:?}", row);
289                }
290                write!(f, "{}", buffer)
291            }
292        }
293    }
294}