|
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 } |