--- a/src/euclidean.rs Sun Nov 10 09:02:57 2024 -0500 +++ b/src/euclidean.rs Tue Dec 31 09:12:43 2024 -0500 @@ -4,13 +4,14 @@ use crate::types::*; use std::ops::{Mul, MulAssign, Div, DivAssign, Add, Sub, AddAssign, SubAssign, Neg}; +pub use crate::types::{HasScalarField, HasRealField}; /// 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; +pub trait Dot<U> : HasScalarField { + fn dot(&self, other : U) -> Self::Field; } /// Space (type) with Euclidean and vector space structure @@ -18,59 +19,64 @@ /// 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> +pub trait Euclidean : Sized + + HasRealField + + Dot<Self> + for<'a> Dot<&'a Self> + + Mul<Self::Field, Output=<Self as Euclidean>::Output> + + MulAssign<Self::Field> + + Div<Self::Field, Output=<Self as Euclidean>::Output> + + DivAssign<Self::Field> + + Add<Self, Output=<Self as Euclidean>::Output> + + Sub<Self, Output=<Self as Euclidean>::Output> + + for<'b> Add<&'b Self, Output=<Self as Euclidean>::Output> + + for<'b> Sub<&'b Self, Output=<Self as Euclidean>::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>; + + Neg<Output=<Self as Euclidean>::Output> { + + type Output : Euclidean<Field = Self::Field>; /// Returns origin of same dimensions as `self`. - fn similar_origin(&self) -> <Self as Euclidean<F>>::Output; + fn similar_origin(&self) -> <Self as Euclidean>::Output; /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$. #[inline] - fn norm2_squared(&self) -> F { + fn norm2_squared(&self) -> Self::Field { self.dot(self) } /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$, /// where `self` is $x$. #[inline] - fn norm2_squared_div2(&self) -> F { - self.norm2_squared()/F::TWO + fn norm2_squared_div2(&self) -> Self::Field { + self.norm2_squared()/Self::Field::TWO } /// Calculate the 2-norm $‖x‖_2$, where `self` is $x$. #[inline] - fn norm2(&self) -> F { + fn norm2(&self) -> Self::Field { self.norm2_squared().sqrt() } /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$. - fn dist2_squared(&self, y : &Self) -> F; + fn dist2_squared(&self, y : &Self) -> Self::Field; /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$. #[inline] - fn dist2(&self, y : &Self) -> F { + fn dist2(&self, y : &Self) -> Self::Field { self.dist2_squared(y).sqrt() } /// Projection to the 2-ball. #[inline] - fn proj_ball2(mut self, ρ : F) -> Self { + fn proj_ball2(mut self, ρ : Self::Field) -> Self { self.proj_ball2_mut(ρ); self } /// In-place projection to the 2-ball. #[inline] - fn proj_ball2_mut(&mut self, ρ : F) { + fn proj_ball2_mut(&mut self, ρ : Self::Field) { let r = self.norm2(); if r>ρ { *self *= ρ/r @@ -79,7 +85,7 @@ } /// Trait for [`Euclidean`] spaces with dimensions known at compile time. -pub trait StaticEuclidean<F : Float> : Euclidean<F> { +pub trait StaticEuclidean : Euclidean { /// Returns the origin - fn origin() -> <Self as Euclidean<F>>::Output; + fn origin() -> <Self as Euclidean>::Output; }