| |
1 /*! |
| |
2 Metaprogramming tools |
| |
3 */ |
| |
4 |
| |
5 /// Reference `x` if so indicated by the first parameter. |
| |
6 /// Typically to be used from another macro. See the implementation of |
| |
7 /// [power][crate::vectorspace::powerspace] and [product spaces][crate::vectorspace::productspace]. |
| |
8 /// |
| |
9 /// ```ignore |
| |
10 /// maybe_ref!(ref, V) // ➡ &V |
| |
11 /// maybe_ref!(noref, V) // ➡ V |
| |
12 /// ``` |
| |
13 #[macro_export] |
| |
14 macro_rules! maybe_ref { |
| |
15 (ref, $x:expr) => { &$x }; |
| |
16 (noref, $x:expr) => { $x }; |
| |
17 (ref, $x:ty) => { &$x }; |
| |
18 (noref, $x:ty) => { $x }; |
| |
19 } |
| |
20 |
| |
21 /// Choose `a` if first argument is the literal `ref`, otherwise `b`. |
| |
22 #[macro_export] |
| |
23 macro_rules! ifref { |
| |
24 (noref, $a:expr, $b:expr) => { $b }; |
| |
25 (ref, $a:expr, $b:expr) => { $a }; |
| |
26 } |
| |
27 |
| |
28 |
| |
29 /// Annotate `x` with a lifetime if the first parameter |
| |
30 /// Typically to be used from another macro. See the implementation of |
| |
31 /// [power][crate::vectorspace::powerspace] and [product spaces][crate::vectorspace::productspace]. |
| |
32 /// |
| |
33 /// ```ignore |
| |
34 /// maybe_ref!(ref, &'a V) // ➡ &'a V |
| |
35 /// maybe_ref!(noref, &'a V) // ➡ V |
| |
36 /// ``` |
| |
37 #[macro_export] |
| |
38 macro_rules! maybe_lifetime { |
| |
39 (ref, $x:ty) => { $x }; |
| |
40 (noref, &$lt:lifetime $x:ty) => { $x }; |
| |
41 (noref, &$x:ty) => { $x }; |
| |
42 } |
| |
43 |
| |
44 /// Use as |
| |
45 /// ```ignore |
| |
46 /// impl_vectorspace_ops!(impl_binop, impl_assignop, impl_scalarop, impl_scalar_assignop, impl_unaryop); |
| |
47 /// ``` |
| |
48 /// with `impl_binop`, `impl_assignop`, `impl_scalarop`, and `impl_unaryop` macros provided. |
| |
49 /// For example usage see the [power][crate::vectorspace::powerspace] and |
| |
50 /// [product spaces][crate::vectorspace::productspace] implementations. |
| |
51 #[macro_export] |
| |
52 macro_rules! impl_vectorspace_ops { |
| |
53 ($impl_binop:ident, $impl_assignop:ident, $impl_scalarop:ident, $impl_scalarlhs_op:ident, |
| |
54 $impl_scalar_assignop:ident, $impl_unaryop:ident) => { |
| |
55 impl_vectorspace_ops!($impl_binop, $impl_assignop, $impl_scalarop, $impl_scalarlhs_op, |
| |
56 $impl_scalar_assignop, $impl_unaryop, |
| |
57 (f32, f64, |
| |
58 num::complex::Complex<f32>, |
| |
59 num::complex::Complex<f64>)); |
| |
60 }; |
| |
61 ($impl_binop:ident, $impl_assignop:ident, $impl_scalarop:ident, $impl_scalarlhs_op:ident, |
| |
62 $impl_scalar_assignop:ident, $impl_unaryop:ident, ($($field:ty),+)) => { |
| |
63 impl_vectorspace_ops!(@binary, $impl_binop, Add, add); |
| |
64 impl_vectorspace_ops!(@binary, $impl_binop, Sub, sub); |
| |
65 impl_vectorspace_ops!(@assign, $impl_assignop, AddAssign, add_assign); |
| |
66 impl_vectorspace_ops!(@assign, $impl_assignop, SubAssign, sub_assign); |
| |
67 impl_vectorspace_ops!(@scalar, $impl_scalarop, Mul, mul); |
| |
68 impl_vectorspace_ops!(@scalar, $impl_scalarop, Div, div); |
| |
69 // Compiler overflow |
| |
70 // $( |
| |
71 // impl_vectorspace_ops!(@scalar_lhs, $impl_scalarlhs_op, Mul, mul, $field); |
| |
72 // )* |
| |
73 impl_vectorspace_ops!(@scalar_assign, $impl_scalar_assignop, MulAssign, mul_assign); |
| |
74 impl_vectorspace_ops!(@scalar_assign, $impl_scalar_assignop, DivAssign, div_assign); |
| |
75 impl_vectorspace_ops!(@unary, $impl_unaryop, Neg, neg); |
| |
76 }; |
| |
77 (@binary, $impl:ident, $trait : ident, $fn : ident) => { |
| |
78 $impl!($trait, $fn, ref, ref); |
| |
79 $impl!($trait, $fn, ref, noref); |
| |
80 $impl!($trait, $fn, noref, ref); |
| |
81 $impl!($trait, $fn, noref, noref); |
| |
82 }; |
| |
83 (@assign, $impl:ident, $trait : ident, $fn :ident) => { |
| |
84 $impl!($trait, $fn, ref); |
| |
85 $impl!($trait, $fn, noref); |
| |
86 }; |
| |
87 (@scalar, $impl:ident, $trait : ident, $fn :ident) => { |
| |
88 $impl!($trait, $fn, ref); |
| |
89 $impl!($trait, $fn, noref); |
| |
90 }; |
| |
91 (@scalar_lhs, $impl:ident, $trait : ident, $fn : ident, $field: ty) => { |
| |
92 // These operators need workarounds |
| |
93 $impl!($trait, $fn, ref, $field); |
| |
94 $impl!($trait, $fn, noref, $field); |
| |
95 }; |
| |
96 (@scalar_assign, $impl:ident, $trait : ident, $fn :ident) => { |
| |
97 $impl!($trait, $fn); |
| |
98 }; |
| |
99 (@unary, $impl:ident, $trait : ident, $fn :ident) => { |
| |
100 $impl!($trait, $fn, ref); |
| |
101 $impl!($trait, $fn, noref); |
| |
102 }; |
| |
103 } |