--- a/src/euclidean.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/euclidean.rs Mon Feb 03 19:22:16 2025 -0500 @@ -2,42 +2,37 @@ Euclidean spaces. */ +use std::ops::{Mul, MulAssign, Div, DivAssign, Add, Sub, AddAssign, SubAssign, Neg}; use crate::types::*; -use std::ops::{Mul, MulAssign, Div, DivAssign, Add, Sub, AddAssign, SubAssign, Neg}; - -/// Space (type) with a defined dot product. -/// -/// `U` is the space of the multiplier, and `F` the space of scalars. -/// Since `U` ≠ `Self`, this trait can also implement dual products. -pub trait Dot<U, F> { - fn dot(&self, other : &U) -> F; -} +use crate::instance::Instance; +use crate::norms::{HasDual, Reflexive}; /// Space (type) with Euclidean and vector space structure /// /// The type should implement vector space operations (addition, subtraction, scalar /// multiplication and scalar division) along with their assignment versions, as well -/// as the [`Dot`] product with respect to `Self`. -pub trait Euclidean<F : Float> : Sized + Dot<Self,F> - + Mul<F, Output=<Self as Euclidean<F>>::Output> + MulAssign<F> - + Div<F, Output=<Self as Euclidean<F>>::Output> + DivAssign<F> - + Add<Self, Output=<Self as Euclidean<F>>::Output> - + Sub<Self, Output=<Self as Euclidean<F>>::Output> - + for<'b> Add<&'b Self, Output=<Self as Euclidean<F>>::Output> - + for<'b> Sub<&'b Self, Output=<Self as Euclidean<F>>::Output> - + AddAssign<Self> + for<'b> AddAssign<&'b Self> - + SubAssign<Self> + for<'b> SubAssign<&'b Self> - + Neg<Output=<Self as Euclidean<F>>::Output> { +/// as an inner product. +pub trait Euclidean<F : Float> : HasDual<F, DualSpace=Self> + Reflexive<F> + + Mul<F, Output=<Self as Euclidean<F>>::Output> + MulAssign<F> + + Div<F, Output=<Self as Euclidean<F>>::Output> + DivAssign<F> + + Add<Self, Output=<Self as Euclidean<F>>::Output> + + Sub<Self, Output=<Self as Euclidean<F>>::Output> + + for<'b> Add<&'b Self, Output=<Self as Euclidean<F>>::Output> + + for<'b> Sub<&'b Self, Output=<Self as Euclidean<F>>::Output> + + AddAssign<Self> + for<'b> AddAssign<&'b Self> + + SubAssign<Self> + for<'b> SubAssign<&'b Self> + + Neg<Output=<Self as Euclidean<F>>::Output> +{ type Output : Euclidean<F>; - /// Returns origin of same dimensions as `self`. - fn similar_origin(&self) -> <Self as Euclidean<F>>::Output; + // Inner product + fn dot<I : Instance<Self>>(&self, other : I) -> F; /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$. - #[inline] - fn norm2_squared(&self) -> F { - self.dot(self) - } + /// + /// This is not automatically implemented to avoid imposing + /// `for <'a> &'a Self : Instance<Self>` trait bound bloat. + fn norm2_squared(&self) -> F; /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$, /// where `self` is $x$. @@ -53,11 +48,11 @@ } /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$. - fn dist2_squared(&self, y : &Self) -> F; + fn dist2_squared<I : Instance<Self>>(&self, y : I) -> F; /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$. #[inline] - fn dist2(&self, y : &Self) -> F { + fn dist2<I : Instance<Self>>(&self, y : I) -> F { self.dist2_squared(y).sqrt() }