impl_euclidean with fixed field dev

Thu, 01 May 2025 01:05:00 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Thu, 01 May 2025 01:05:00 -0500
branch
dev
changeset 114
b53806de0be0
parent 113
d97fcf22a61c
child 115
f9aec20d0286

impl_euclidean with fixed field

src/direct_product.rs file | annotate | diff | comparison | revisions
--- a/src/direct_product.rs	Thu May 01 00:08:09 2025 -0500
+++ b/src/direct_product.rs	Thu May 01 01:05:00 2025 -0500
@@ -320,44 +320,57 @@
 
 type PairOutput<F, A, B> = Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output>;
 
-impl<A, B, F> Euclidean<F> for Pair<A, B>
-where
-    A: Euclidean<F>,
-    B: Euclidean<F>,
-    F: Float,
-    PairOutput<F, A, B>: Euclidean<F>,
-    Self: Sized
-        + Mul<F, Output = PairOutput<F, A, B>>
-        + MulAssign<F>
-        + Div<F, Output = PairOutput<F, A, B>>
-        + DivAssign<F>
-        + Add<Self, Output = PairOutput<F, A, B>>
-        + Sub<Self, Output = PairOutput<F, A, B>>
-        + for<'b> Add<&'b Self, Output = PairOutput<F, A, B>>
-        + for<'b> Sub<&'b Self, Output = PairOutput<F, A, B>>
-        + AddAssign<Self>
-        + for<'b> AddAssign<&'b Self>
-        + SubAssign<Self>
-        + for<'b> SubAssign<&'b Self>
-        + Neg<Output = PairOutput<F, A, B>>,
-{
-    type Output = PairOutput<F, A, B>;
+/// We need to restrict `A` and `B` as [`Euclidean`] to have closed `Output`
+/// to avoid compiler overflows that the requirement
+/// ```
+/// Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output> : Euclidean<F>
+/// ```
+/// would generate.
 
-    fn dot<I: Instance<Self>>(&self, other: I) -> F {
-        let Pair(u, v) = other.decompose();
-        self.0.dot(u) + self.1.dot(v)
-    }
+macro_rules! impl_euclidean {
+    ($field:ty) => {
+        impl<A, B> Euclidean<$field> for Pair<A, B>
+        where
+            A: Euclidean<$field>,
+            B: Euclidean<$field>,
+            PairOutput<$field, A, B>: Euclidean<$field>,
+            Self: Sized
+                + Mul<$field, Output = PairOutput<$field, A, B>>
+                + MulAssign<$field>
+                + Div<$field, Output = PairOutput<$field, A, B>>
+                + DivAssign<$field>
+                + Add<Self, Output = PairOutput<$field, A, B>>
+                + Sub<Self, Output = PairOutput<$field, A, B>>
+                + for<'b> Add<&'b Self, Output = PairOutput<$field, A, B>>
+                + for<'b> Sub<&'b Self, Output = PairOutput<$field, A, B>>
+                + AddAssign<Self>
+                + for<'b> AddAssign<&'b Self>
+                + SubAssign<Self>
+                + for<'b> SubAssign<&'b Self>
+                + Neg<Output = PairOutput<$field, A, B>>,
+        {
+            type Output = PairOutput<$field, A, B>;
 
-    fn norm2_squared(&self) -> F {
-        self.0.norm2_squared() + self.1.norm2_squared()
-    }
+            fn dot<I: Instance<Self>>(&self, other: I) -> $field {
+                let Pair(u, v) = other.decompose();
+                self.0.dot(u) + self.1.dot(v)
+            }
+
+            fn norm2_squared(&self) -> $field {
+                self.0.norm2_squared() + self.1.norm2_squared()
+            }
 
-    fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F {
-        let Pair(u, v) = other.decompose();
-        self.0.dist2_squared(u) + self.1.dist2_squared(v)
-    }
+            fn dist2_squared<I: Instance<Self>>(&self, other: I) -> $field {
+                let Pair(u, v) = other.decompose();
+                self.0.dist2_squared(u) + self.1.dist2_squared(v)
+            }
+        }
+    };
 }
 
+impl_euclidean!(f32);
+impl_euclidean!(f64);
+
 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B>
 where
     U: Space,

mercurial