src/metaprogramming.rs

branch
dev
changeset 57
1b3b1687b9ed
child 59
9226980e45a7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/metaprogramming.rs	Fri Dec 13 22:37:12 2024 -0500
@@ -0,0 +1,103 @@
+/*!
+Metaprogramming tools
+*/
+
+/// Reference `x` if so indicated by the first parameter.
+/// Typically to be used from another macro. See the implementation of
+/// [power][crate::vectorspace::powerspace] and [product spaces][crate::vectorspace::productspace].
+///
+/// ```ignore
+/// maybe_ref!(ref, V)   // ➡ &V
+/// maybe_ref!(noref, V) // ➡ V
+/// ```
+#[macro_export]
+macro_rules! maybe_ref {
+    (ref, $x:expr) => { &$x };
+    (noref, $x:expr) => { $x };
+    (ref, $x:ty) => { &$x };
+    (noref, $x:ty) => { $x };
+}
+
+/// Choose `a` if first argument is the literal `ref`, otherwise `b`.
+#[macro_export]
+macro_rules! ifref {
+    (noref, $a:expr, $b:expr) => { $b };
+    (ref, $a:expr, $b:expr) => { $a };
+}
+
+
+/// Annotate `x` with a lifetime if the first parameter
+/// Typically to be used from another macro. See the implementation of
+/// [power][crate::vectorspace::powerspace] and [product spaces][crate::vectorspace::productspace].
+///
+/// ```ignore
+/// maybe_ref!(ref, &'a V)    // ➡ &'a V
+/// maybe_ref!(noref, &'a V)  // ➡ V
+/// ```
+#[macro_export]
+macro_rules! maybe_lifetime {
+    (ref, $x:ty) => { $x };
+    (noref, &$lt:lifetime $x:ty) => { $x };
+    (noref, &$x:ty) => { $x };
+}
+
+/// Use as
+/// ```ignore
+/// impl_vectorspace_ops!(impl_binop, impl_assignop, impl_scalarop, impl_scalar_assignop, impl_unaryop);
+/// ```
+/// with `impl_binop`, `impl_assignop`, `impl_scalarop`, and `impl_unaryop` macros provided.
+/// For example usage see the [power][crate::vectorspace::powerspace] and
+/// [product spaces][crate::vectorspace::productspace] implementations.
+#[macro_export]
+macro_rules! impl_vectorspace_ops {
+    ($impl_binop:ident, $impl_assignop:ident, $impl_scalarop:ident, $impl_scalarlhs_op:ident,
+        $impl_scalar_assignop:ident, $impl_unaryop:ident) => {
+        impl_vectorspace_ops!($impl_binop, $impl_assignop, $impl_scalarop, $impl_scalarlhs_op,
+                                $impl_scalar_assignop, $impl_unaryop,
+                                (f32, f64,
+                                num::complex::Complex<f32>,
+                                num::complex::Complex<f64>));
+    };
+    ($impl_binop:ident, $impl_assignop:ident, $impl_scalarop:ident, $impl_scalarlhs_op:ident,
+        $impl_scalar_assignop:ident, $impl_unaryop:ident, ($($field:ty),+)) => {
+        impl_vectorspace_ops!(@binary, $impl_binop, Add, add);
+        impl_vectorspace_ops!(@binary, $impl_binop, Sub, sub);
+        impl_vectorspace_ops!(@assign, $impl_assignop, AddAssign, add_assign);
+        impl_vectorspace_ops!(@assign, $impl_assignop, SubAssign, sub_assign);
+        impl_vectorspace_ops!(@scalar, $impl_scalarop, Mul, mul);
+        impl_vectorspace_ops!(@scalar, $impl_scalarop, Div, div);
+        // Compiler overflow
+        // $(
+        //     impl_vectorspace_ops!(@scalar_lhs, $impl_scalarlhs_op, Mul, mul, $field);
+        // )*
+        impl_vectorspace_ops!(@scalar_assign, $impl_scalar_assignop, MulAssign, mul_assign);
+        impl_vectorspace_ops!(@scalar_assign, $impl_scalar_assignop, DivAssign, div_assign);
+        impl_vectorspace_ops!(@unary, $impl_unaryop, Neg, neg);
+    };
+    (@binary, $impl:ident, $trait : ident, $fn : ident) => {
+        $impl!($trait, $fn, ref, ref);
+        $impl!($trait, $fn, ref, noref);
+        $impl!($trait, $fn, noref, ref);
+        $impl!($trait, $fn, noref, noref);
+    };
+    (@assign, $impl:ident, $trait : ident, $fn :ident) => {
+        $impl!($trait, $fn, ref);
+        $impl!($trait, $fn, noref);
+    };
+    (@scalar, $impl:ident, $trait : ident, $fn :ident) => {
+        $impl!($trait, $fn, ref);
+        $impl!($trait, $fn, noref);
+    };
+    (@scalar_lhs, $impl:ident, $trait : ident, $fn : ident, $field: ty) => {
+        // These operators need workarounds
+        $impl!($trait, $fn, ref, $field);
+        $impl!($trait, $fn, noref, $field);
+    };
+    (@scalar_assign, $impl:ident, $trait : ident, $fn :ident) => {
+        $impl!($trait, $fn);
+    };
+    (@unary, $impl:ident, $trait : ident, $fn :ident) => {
+        $impl!($trait, $fn, ref);
+        $impl!($trait, $fn, noref);
+    };
+}

mercurial