# HG changeset patch # User Tuomo Valkonen # Date 1756953073 18000 # Node ID 53ab61a41d7092e552208085a743d35fe90f7d4c # Parent 102421d462d1158a054535cfcbfabfb3a31cb37d nalgebra matrix distances diff -r 102421d462d1 -r 53ab61a41d70 src/euclidean/wrap.rs --- a/src/euclidean/wrap.rs Wed Sep 03 21:03:47 2025 -0500 +++ b/src/euclidean/wrap.rs Wed Sep 03 21:31:13 2025 -0500 @@ -135,6 +135,8 @@ $crate::wrap!(impl_scalar_mut $F, $type, std::ops::MulAssign, mul_assign where $($qual)*); $crate::wrap!(impl_scalar_mut $F, $type, std::ops::DivAssign, div_assign where $($qual)*); + $crate::self_ownable!($type where $($qual)*); + impl<$($qual)*> $crate::euclidean::Euclidean<$F> for $type // where // Self: $crate::euclidean::wrap::Wrapped @@ -153,6 +155,8 @@ // + for<'b> std::ops::SubAssign<&'b Self> // + std::ops::Neg::Owned>, { + type PrincipalE = Self; + fn dot>(&self, other: I) -> $F { other.eval_decompose(|x| self.get_view().dot(&x.get_view())) } @@ -166,6 +170,22 @@ } } + impl<$($qual)*> $crate::linops::VectorSpace for $type + // where + // Self : $crate::euclidean::wrap::Wrapped, + // Self::Unwrapped : $crate::linops::AXPY, + // Self: std::ops::MulAssign + std::ops::DivAssign, + // Self::Unwrapped: std::ops::MulAssign + std::ops::DivAssign, + { + type Field = $F; + type PrincipalV = Self; + + /// Return a similar zero as `self`. + fn similar_origin(&self) -> Self::PrincipalV { + Self::wrap(self.get_view().similar_origin()) + } + } + impl<$($qual)*> $crate::linops::AXPY for $type // where // Self : $crate::euclidean::wrap::Wrapped, @@ -173,10 +193,7 @@ // Self: std::ops::MulAssign + std::ops::DivAssign, // Self::Unwrapped: std::ops::MulAssign + std::ops::DivAssign, { - type Field = $F; - type Owned = Self; - - fn axpy>(&mut self, α: $F, x: I, β: $F) { + fn axpy>(&mut self, α: $F, x: I, β: $F) { x.eval_decompose(|v| { self.get_view_mut().axpy(α, v.get_view(), β) }) @@ -194,11 +211,6 @@ }) } - /// Return a similar zero as `self`. - fn similar_origin(&self) -> Self::Owned { - Self::wrap(self.get_view().similar_origin()) - } - /// Set self to zero. fn set_zero(&mut self) { self.get_mut_view().set_zero() @@ -207,6 +219,7 @@ impl<$($qual)*> $crate::instance::Space for $type { type Decomp = <::Unwrapped as $crate::instance::Space>::Decomp; + type Principal = Self; } }; } diff -r 102421d462d1 -r 53ab61a41d70 src/nalgebra_support.rs --- a/src/nalgebra_support.rs Wed Sep 03 21:03:47 2025 -0500 +++ b/src/nalgebra_support.rs Wed Sep 03 21:31:13 2025 -0500 @@ -389,7 +389,7 @@ impl Projection for Vector where - SM: StorageMut + Clone, + SM: StorageMut, M: Dim, E: Scalar + Zero + One + Float + RealField, DefaultAllocator: Allocator, @@ -405,7 +405,7 @@ impl ProjectionMut for Vector where - SM: StorageMut + Clone, + SM: StorageMut, M: Dim, E: Scalar + Zero + One + Copy + Float + RealField, DefaultAllocator: Allocator, @@ -464,26 +464,25 @@ }) } -// TODO: should allow different input storages in `Euclidean`. - -impl Euclidean for Vector +impl Euclidean for Matrix where M: Dim, - S: Storage, + N: Dim, + S: Storage, E: Float + Scalar + Zero + One + RealField, - DefaultAllocator: Allocator, - ShapeConstraint: StridesOk, + DefaultAllocator: Allocator, + ShapeConstraint: StridesOk, { - type PrincipalE = OVector; + type PrincipalE = OMatrix; #[inline] fn dot>(&self, other: I) -> E { - other.eval_ref(|ref r| Vector::::dot(self, r)) + other.eval_ref(|ref r| Matrix::::dot(self, r)) } #[inline] fn norm2_squared(&self) -> E { - Vector::::norm_squared(self) + Matrix::::norm_squared(self) } #[inline] @@ -507,13 +506,14 @@ } /// The default norm for `Vector` is [`L2`]. -impl Normed for Vector +impl Normed for Matrix where M: Dim, - S: Storage, + N: Dim, + S: Storage, E: Float + Scalar + Zero + One + RealField, - DefaultAllocator: Allocator, - ShapeConstraint: StridesOk, + DefaultAllocator: Allocator, + ShapeConstraint: StridesOk, { type NormExp = L2; @@ -524,22 +524,24 @@ #[inline] fn is_zero(&self) -> bool { - Vector::::norm_squared(self) == E::ZERO + Matrix::::norm_squared(self) == E::ZERO } } -impl HasDual for Vector +impl HasDual for Matrix where M: Dim, - S: Storage, + N: Dim, + S: Storage, E: Float + Scalar + Zero + One + RealField, - DefaultAllocator: Allocator, - ShapeConstraint: StridesOk, + DefaultAllocator: Allocator, + ShapeConstraint: StridesOk, { - type DualSpace = OVector; + type DualSpace = OMatrix; - fn dual_origin(&self) -> OVector { - OVector::zeros_generic(M::from_usize(self.len()), Const) + fn dual_origin(&self) -> OMatrix { + let (m, n) = self.shape_generic(); + OMatrix::zeros_generic(m, n) } } @@ -560,7 +562,7 @@ impl Dist for Vector where M: Dim, - S: Storage + Clone, + S: Storage, E: Float + Scalar + Zero + One + RealField, DefaultAllocator: Allocator, ShapeConstraint: StridesOk, @@ -571,13 +573,14 @@ } } -impl Norm for Vector +impl Norm for Matrix where M: Dim, - S: Storage, + N: Dim, + S: Storage, E: Float + Scalar + Zero + One + RealField, - DefaultAllocator: Allocator, - ShapeConstraint: StridesOk, + DefaultAllocator: Allocator, + ShapeConstraint: StridesOk, { #[inline] fn norm(&self, _: L2) -> E { @@ -585,13 +588,14 @@ } } -impl Dist for Vector +impl Dist for Matrix where M: Dim, - S: Storage + Clone, + N: Dim, + S: Storage, E: Float + Scalar + Zero + One + RealField, - DefaultAllocator: Allocator, - ShapeConstraint: StridesOk, + DefaultAllocator: Allocator, + ShapeConstraint: StridesOk, { #[inline] fn dist>(&self, other: I, _: L2) -> E { @@ -599,13 +603,14 @@ } } -impl Norm for Vector +impl Norm for Matrix where M: Dim, - S: Storage, + N: Dim, + S: Storage, E: Float + Scalar + Zero + One + RealField, - DefaultAllocator: Allocator, - ShapeConstraint: StridesOk, + DefaultAllocator: Allocator, + ShapeConstraint: StridesOk, { #[inline] fn norm(&self, _: Linfinity) -> E { @@ -613,13 +618,14 @@ } } -impl Dist for Vector +impl Dist for Matrix where M: Dim, - S: Storage + Clone, + N: Dim, + S: Storage, E: Float + Scalar + Zero + One + RealField, - DefaultAllocator: Allocator, - ShapeConstraint: StridesOk, + DefaultAllocator: Allocator, + ShapeConstraint: StridesOk, { #[inline] fn dist>(&self, other: I, _: Linfinity) -> E {