amari_core/
unicode_ops.rs1#[macro_export]
53macro_rules! geo {
54 ($a:expr, $b:expr) => {
55 $a.geometric_product(&$b)
56 };
57}
58
59#[macro_export]
64macro_rules! wedge {
65 ($a:expr, $b:expr) => {
66 $a.outer_product(&$b)
67 };
68}
69
70#[macro_export]
75macro_rules! dot {
76 ($a:expr, $b:expr) => {
77 $a.inner_product(&$b)
78 };
79}
80
81#[macro_export]
86macro_rules! lcon {
87 ($a:expr, $b:expr) => {
88 $a.left_contraction(&$b)
89 };
90}
91
92#[macro_export]
97macro_rules! rcon {
98 ($a:expr, $b:expr) => {
99 $a.right_contraction(&$b)
100 };
101}
102
103#[macro_export]
108macro_rules! dual {
109 ($a:expr) => {
110 $a.hodge_dual()
111 };
112}
113
114#[macro_export]
119macro_rules! rev {
120 ($a:expr) => {
121 $a.reverse()
122 };
123}
124
125#[macro_export]
130macro_rules! grade {
131 ($a:expr, $k:expr) => {
132 $a.grade_projection($k)
133 };
134}
135
136#[macro_export]
141macro_rules! norm {
142 ($a:expr) => {
143 $a.magnitude()
144 };
145}
146
147#[macro_export]
149macro_rules! trop_add {
150 ($a:expr, $b:expr) => {
151 $a.tropical_add(&$b)
152 };
153}
154
155#[macro_export]
157macro_rules! trop_mul {
158 ($a:expr, $b:expr) => {
159 $a.tropical_mul(&$b)
160 };
161}
162
163#[macro_export]
165macro_rules! commutator {
166 ($a:expr, $b:expr) => {{
167 let ab = geo!($a, $b);
168 let ba = geo!($b, $a);
169 (ab - ba) * 0.5
170 }};
171}
172
173#[macro_export]
175macro_rules! anticommutator {
176 ($a:expr, $b:expr) => {{
177 let ab = geo!($a, $b);
178 let ba = geo!($b, $a);
179 (ab + ba) * 0.5
180 }};
181}
182
183#[macro_export]
185macro_rules! norm_squared {
186 ($a:expr) => {
187 $a.norm_squared()
188 };
189}
190
191#[macro_export]
193macro_rules! unit {
194 ($a:expr) => {{
195 $a.normalize().unwrap_or($a.clone())
196 }};
197}
198
199#[cfg(test)]
200mod tests {
201 use crate::{basis::MultivectorBuilder, Vector};
202 use approx::assert_relative_eq;
203
204 #[test]
205 fn test_unicode_geometric_product() {
206 let a = Vector::<3, 0, 0>::e1();
207 let b = Vector::<3, 0, 0>::e2();
208
209 let unicode_result = geo!(a, b);
211
212 let traditional_result = a.geometric_product(&b);
214
215 for i in 0..8 {
217 assert_relative_eq!(unicode_result.get(i), traditional_result.get(i));
218 }
219 }
220
221 #[test]
222 fn test_unicode_wedge_product() {
223 let e1 = Vector::<3, 0, 0>::e1();
224 let e2 = Vector::<3, 0, 0>::e2();
225
226 let wedge_result = wedge!(e1, e2);
227 let traditional = e1.outer_product(&e2);
228
229 assert_relative_eq!(wedge_result.bivector_part().magnitude(), 1.0);
231
232 for i in 0..8 {
234 assert_relative_eq!(wedge_result.get(i), traditional.get(i));
235 }
236 }
237
238 #[test]
239 fn test_unicode_inner_product() {
240 let a = Vector::<3, 0, 0>::from_components(3.0, 4.0, 0.0);
241 let b = Vector::<3, 0, 0>::from_components(1.0, 1.0, 0.0);
242
243 let inner_result = dot!(a, b);
244 let traditional = a.inner_product(&b);
245
246 assert_relative_eq!(inner_result.scalar_part(), 7.0);
248
249 for i in 0..8 {
251 assert_relative_eq!(inner_result.get(i), traditional.get(i));
252 }
253 }
254
255 #[test]
256 fn test_unicode_unary_operations() {
257 let mv = MultivectorBuilder::<3, 0, 0>::new()
258 .scalar(1.0)
259 .e(1, 2.0)
260 .e(3, 3.0) .build();
262
263 let reversed = rev!(mv);
265 let traditional_reverse = mv.reverse();
266
267 for i in 0..8 {
268 assert_relative_eq!(reversed.get(i), traditional_reverse.get(i));
269 }
270
271 let magnitude = norm!(mv);
273 let traditional_magnitude = mv.magnitude();
274
275 assert_relative_eq!(magnitude, traditional_magnitude);
276 }
277
278 #[test]
279 fn test_unicode_grade_projection() {
280 let mv = MultivectorBuilder::<3, 0, 0>::new()
281 .scalar(1.0)
282 .e(1, 2.0)
283 .e(2, 3.0)
284 .e(3, 4.0) .build();
286
287 let grade0 = grade!(mv, 0);
289 let grade1 = grade!(mv, 1);
290 let grade2 = grade!(mv, 2);
291
292 let traditional_grade0 = mv.grade_projection(0);
293 let traditional_grade1 = mv.grade_projection(1);
294 let traditional_grade2 = mv.grade_projection(2);
295
296 for i in 0..8 {
298 assert_relative_eq!(grade0.get(i), traditional_grade0.get(i));
299 assert_relative_eq!(grade1.get(i), traditional_grade1.get(i));
300 assert_relative_eq!(grade2.get(i), traditional_grade2.get(i));
301 }
302 }
303
304 #[test]
305 fn test_extended_unicode_operations() {
306 let a = Vector::<3, 0, 0>::e1();
307 let b = Vector::<3, 0, 0>::e2();
308
309 let commutator_result = commutator!(a, b);
311
312 assert!(commutator_result.bivector_part().magnitude() > 0.0);
314
315 let v = Vector::<3, 0, 0>::from_components(3.0, 4.0, 0.0);
317 let unit_result = unit!(v);
318
319 assert_relative_eq!(unit_result.norm(), 1.0, epsilon = 1e-10);
321
322 let squared_mag = norm_squared!(v);
324 let expected = 3.0 * 3.0 + 4.0 * 4.0;
325 assert_relative_eq!(squared_mag, expected);
326 }
327
328 #[test]
329 fn test_unicode_mathematical_identities() {
330 let a = Vector::<3, 0, 0>::from_components(1.0, 2.0, 3.0);
331 let b = Vector::<3, 0, 0>::from_components(4.0, 5.0, 6.0);
332
333 let geometric = geo!(a, b);
335 let inner = dot!(a, b);
336 let outer = wedge!(a, b);
337 let decomposed = inner + outer;
338
339 for i in 0..8 {
340 assert_relative_eq!(geometric.get(i), decomposed.get(i), epsilon = 1e-10);
341 }
342
343 let left_side = rev!(geometric);
345 let right_side = geo!(rev!(b), rev!(a));
346
347 for i in 0..8 {
348 assert_relative_eq!(left_side.get(i), right_side.get(i), epsilon = 1e-10);
349 }
350 }
351}