--- a/src/loc.rs Thu May 01 08:40:33 2025 -0500 +++ b/src/loc.rs Thu May 01 13:06:58 2025 -0500 @@ -3,44 +3,45 @@ For working with small vectors in $ℝ^2$ or $ℝ^3$. */ -use std::ops::{Add,Sub,AddAssign,SubAssign,Mul,Div,MulAssign,DivAssign,Neg,Index,IndexMut}; -use std::slice::{Iter,IterMut}; +use crate::euclidean::*; +use crate::instance::{BasicDecomposition, Instance}; +use crate::linops::{Linear, Mapping, AXPY}; +use crate::mapping::Space; +use crate::maputil::{map1, map1_mut, map2, map2_mut, FixedLength, FixedLengthMut}; +use crate::norms::*; +use crate::types::{Float, Num, SignedNum}; +use serde::ser::{Serialize, SerializeSeq, Serializer}; use std::fmt::{Display, Formatter}; -use crate::types::{Float,Num,SignedNum}; -use crate::maputil::{FixedLength,FixedLengthMut,map1,map2,map1_mut,map2_mut}; -use crate::euclidean::*; -use crate::norms::*; -use crate::linops::{AXPY, Mapping, Linear}; -use crate::instance::{Instance, BasicDecomposition}; -use crate::mapping::Space; -use serde::ser::{Serialize, Serializer, SerializeSeq}; - +use std::ops::{ + Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, +}; +use std::slice::{Iter, IterMut}; /// A container type for (short) `N`-dimensional vectors of element type `F`. /// /// Supports basic operations of an [`Euclidean`] space, several [`Norm`]s, and /// fused [`AXPY`] operations, among others. -#[derive(Copy,Clone,Debug,PartialEq,Eq)] -pub struct Loc<F, const N : usize>( +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct Loc<const N: usize, F = f64>( /// An array of the elements of the vector - pub [F; N] + pub [F; N], ); -impl<F : Display, const N : usize> Display for Loc<F, N>{ +impl<F: Display, const N: usize> Display for Loc<N, F> { // Required method fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "[")?; - let mut comma = ""; - for e in self.iter() { + write!(f, "[")?; + let mut comma = ""; + for e in self.iter() { write!(f, "{comma}{e}")?; comma = ", "; - } - write!(f, "]") + } + write!(f, "]") } } // Need to manually implement as [F; N] serialisation is provided only for some N. -impl<F, const N : usize> Serialize for Loc<F, N> +impl<F, const N: usize> Serialize for Loc<N, F> where F: Serialize, { @@ -56,10 +57,10 @@ } } -impl<F, const N : usize> Loc<F, N> { +impl<F, const N: usize> Loc<N, F> { /// Creates a new `Loc` vector from an array. #[inline] - pub fn new(arr : [F; N]) -> Self { + pub fn new(arr: [F; N]) -> Self { Loc(arr) } @@ -76,43 +77,44 @@ } } -impl<F : Copy, const N : usize> Loc<F, N> { +impl<F: Copy, const N: usize> Loc<N, F> { /// Maps `g` over the elements of the vector, returning a new [`Loc`] vector #[inline] - pub fn map<H>(&self, g : impl Fn(F) -> H) -> Loc<H, N> { + pub fn map<H>(&self, g: impl Fn(F) -> H) -> Loc<N, H> { Loc::new(map1(self, |u| g(*u))) } /// Maps `g` over pairs of elements of two vectors, retuning a new one. #[inline] - pub fn map2<H>(&self, other : &Self, g : impl Fn(F, F) -> H) -> Loc<H, N> { + pub fn map2<H>(&self, other: &Self, g: impl Fn(F, F) -> H) -> Loc<N, H> { Loc::new(map2(self, other, |u, v| g(*u, *v))) } /// Maps `g` over mutable references to elements of the vector. #[inline] - pub fn map_mut(&mut self, g : impl Fn(&mut F)) { + pub fn map_mut(&mut self, g: impl Fn(&mut F)) { map1_mut(self, g) } /// Maps `g` over pairs of mutable references to elements of `self, and elements /// of `other` vector. #[inline] - pub fn map2_mut(&mut self, other : &Self, g : impl Fn(&mut F, F)) { + pub fn map2_mut(&mut self, other: &Self, g: impl Fn(&mut F, F)) { map2_mut(self, other, |u, v| g(u, *v)) } /// Maps `g` over the elements of `self` and returns the product of the results. #[inline] - pub fn product_map<A : Num>(&self, g : impl Fn(F) -> A) -> A { + pub fn product_map<A: Num>(&self, g: impl Fn(F) -> A) -> A { match N { 1 => g(unsafe { *self.0.get_unchecked(0) }), - 2 => g(unsafe { *self.0.get_unchecked(0) }) * - g(unsafe { *self.0.get_unchecked(1) }), - 3 => g(unsafe { *self.0.get_unchecked(0) }) * - g(unsafe { *self.0.get_unchecked(1) }) * - g(unsafe { *self.0.get_unchecked(2) }), - _ => self.iter().fold(A::ONE, |m, &x| m * g(x)) + 2 => g(unsafe { *self.0.get_unchecked(0) }) * g(unsafe { *self.0.get_unchecked(1) }), + 3 => { + g(unsafe { *self.0.get_unchecked(0) }) + * g(unsafe { *self.0.get_unchecked(1) }) + * g(unsafe { *self.0.get_unchecked(2) }) + } + _ => self.iter().fold(A::ONE, |m, &x| m * g(x)), } } } @@ -130,29 +132,28 @@ ($($x:expr),+ $(,)?) => { Loc::new([$($x),+]) } } - -impl<F, const N : usize> From<[F; N]> for Loc<F, N> { +impl<F, const N: usize> From<[F; N]> for Loc<N, F> { #[inline] - fn from(other: [F; N]) -> Loc<F, N> { + fn from(other: [F; N]) -> Loc<N, F> { Loc(other) } } -/*impl<F : Copy, const N : usize> From<&[F; N]> for Loc<F, N> { +/*impl<F : Copy, const N : usize> From<&[F; N]> for Loc<N, F> { #[inline] - fn from(other: &[F; N]) -> Loc<F, N> { + fn from(other: &[F; N]) -> Loc<N, F> { Loc(*other) } }*/ -impl<F> From<F> for Loc<F, 1> { +impl<F> From<F> for Loc<1, F> { #[inline] - fn from(other: F) -> Loc<F, 1> { + fn from(other: F) -> Loc<1, F> { Loc([other]) } } -impl<F> Loc<F, 1> { +impl<F> Loc<1, F> { #[inline] pub fn flatten1d(self) -> F { let Loc([v]) = self; @@ -160,22 +161,21 @@ } } -impl<F, const N : usize> From<Loc<F, N>> for [F; N] { +impl<F, const N: usize> From<Loc<N, F>> for [F; N] { #[inline] - fn from(other : Loc<F, N>) -> [F; N] { + fn from(other: Loc<N, F>) -> [F; N] { other.0 } } -/*impl<F : Copy, const N : usize> From<&Loc<F, N>> for [F; N] { +/*impl<F : Copy, const N : usize> From<&Loc<N, F>> for [F; N] { #[inline] - fn from(other : &Loc<F, N>) -> [F; N] { + fn from(other : &Loc<N, F>) -> [F; N] { other.0 } }*/ - -impl<F, const N : usize> IntoIterator for Loc<F, N> { +impl<F, const N: usize> IntoIterator for Loc<N, F> { type Item = <[F; N] as IntoIterator>::Item; type IntoIter = <[F; N] as IntoIterator>::IntoIter; @@ -187,20 +187,24 @@ // Indexing -impl<F, Ix, const N : usize> Index<Ix> for Loc<F,N> -where [F; N] : Index<Ix> { +impl<F, Ix, const N: usize> Index<Ix> for Loc<N, F> +where + [F; N]: Index<Ix>, +{ type Output = <[F; N] as Index<Ix>>::Output; #[inline] - fn index(&self, ix : Ix) -> &Self::Output { + fn index(&self, ix: Ix) -> &Self::Output { self.0.index(ix) } } -impl<F, Ix, const N : usize> IndexMut<Ix> for Loc<F,N> -where [F; N] : IndexMut<Ix> { +impl<F, Ix, const N: usize> IndexMut<Ix> for Loc<N, F> +where + [F; N]: IndexMut<Ix>, +{ #[inline] - fn index_mut(&mut self, ix : Ix) -> &mut Self::Output { + fn index_mut(&mut self, ix: Ix) -> &mut Self::Output { self.0.index_mut(ix) } } @@ -209,61 +213,61 @@ macro_rules! make_binop { ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { - impl<F : Num, const N : usize> $trait<Loc<F,N>> for Loc<F, N> { - type Output = Loc<F, N>; + impl<F: Num, const N: usize> $trait<Loc<N, F>> for Loc<N, F> { + type Output = Loc<N, F>; #[inline] - fn $fn(mut self, other : Loc<F, N>) -> Self::Output { + fn $fn(mut self, other: Loc<N, F>) -> Self::Output { self.$fn_assign(other); self } } - impl<'a, F : Num, const N : usize> $trait<&'a Loc<F,N>> for Loc<F, N> { - type Output = Loc<F, N>; + impl<'a, F: Num, const N: usize> $trait<&'a Loc<N, F>> for Loc<N, F> { + type Output = Loc<N, F>; #[inline] - fn $fn(mut self, other : &'a Loc<F, N>) -> Self::Output { + fn $fn(mut self, other: &'a Loc<N, F>) -> Self::Output { self.$fn_assign(other); self } } - impl<'b, F : Num, const N : usize> $trait<Loc<F,N>> for &'b Loc<F, N> { - type Output = Loc<F, N>; + impl<'b, F: Num, const N: usize> $trait<Loc<N, F>> for &'b Loc<N, F> { + type Output = Loc<N, F>; #[inline] - fn $fn(self, other : Loc<F, N>) -> Self::Output { + fn $fn(self, other: Loc<N, F>) -> Self::Output { self.map2(&other, |a, b| a.$fn(b)) } } - impl<'a, 'b, F : Num, const N : usize> $trait<&'a Loc<F,N>> for &'b Loc<F, N> { - type Output = Loc<F, N>; + impl<'a, 'b, F: Num, const N: usize> $trait<&'a Loc<N, F>> for &'b Loc<N, F> { + type Output = Loc<N, F>; #[inline] - fn $fn(self, other : &'a Loc<F, N>) -> Self::Output { + fn $fn(self, other: &'a Loc<N, F>) -> Self::Output { self.map2(other, |a, b| a.$fn(b)) } } - impl<F : Num, const N : usize> $trait_assign<Loc<F,N>> for Loc<F, N> { + impl<F: Num, const N: usize> $trait_assign<Loc<N, F>> for Loc<N, F> { #[inline] - fn $fn_assign(&mut self, other : Loc<F, N>) { + fn $fn_assign(&mut self, other: Loc<N, F>) { self.map2_mut(&other, |a, b| a.$fn_assign(b)) } } - impl<'a, F : Num, const N : usize> $trait_assign<&'a Loc<F,N>> for Loc<F, N> { + impl<'a, F: Num, const N: usize> $trait_assign<&'a Loc<N, F>> for Loc<N, F> { #[inline] - fn $fn_assign(&mut self, other : &'a Loc<F, N>) { + fn $fn_assign(&mut self, other: &'a Loc<N, F>) { self.map2_mut(other, |a, b| a.$fn_assign(b)) } } - } + }; } make_binop!(Add, add, AddAssign, add_assign); make_binop!(Sub, sub, SubAssign, sub_assign); -impl<F : Float, const N : usize> std::iter::Sum for Loc<F, N> { - fn sum<I: Iterator<Item = Loc<F, N>>>(mut iter: I) -> Self { +impl<F: Float, const N: usize> std::iter::Sum for Loc<N, F> { + fn sum<I: Iterator<Item = Loc<N, F>>>(mut iter: I) -> Self { match iter.next() { None => Self::ORIGIN, Some(mut v) => { @@ -278,62 +282,61 @@ macro_rules! make_scalarop_rhs { ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { - impl<F : Num, const N : usize> $trait<F> for Loc<F, N> { - type Output = Loc<F, N>; + impl<F: Num, const N: usize> $trait<F> for Loc<N, F> { + type Output = Loc<N, F>; #[inline] - fn $fn(self, b : F) -> Self::Output { + fn $fn(self, b: F) -> Self::Output { self.map(|a| a.$fn(b)) } } - impl<'a, F : Num, const N : usize> $trait<&'a F> for Loc<F, N> { - type Output = Loc<F, N>; + impl<'a, F: Num, const N: usize> $trait<&'a F> for Loc<N, F> { + type Output = Loc<N, F>; #[inline] - fn $fn(self, b : &'a F) -> Self::Output { + fn $fn(self, b: &'a F) -> Self::Output { self.map(|a| a.$fn(*b)) } } - impl<'b, F : Num, const N : usize> $trait<F> for &'b Loc<F, N> { - type Output = Loc<F, N>; + impl<'b, F: Num, const N: usize> $trait<F> for &'b Loc<N, F> { + type Output = Loc<N, F>; #[inline] - fn $fn(self, b : F) -> Self::Output { + fn $fn(self, b: F) -> Self::Output { self.map(|a| a.$fn(b)) } } - impl<'a, 'b, F : Float, const N : usize> $trait<&'a F> for &'b Loc<F, N> { - type Output = Loc<F, N>; + impl<'a, 'b, F: Float, const N: usize> $trait<&'a F> for &'b Loc<N, F> { + type Output = Loc<N, F>; #[inline] - fn $fn(self, b : &'a F) -> Self::Output { + fn $fn(self, b: &'a F) -> Self::Output { self.map(|a| a.$fn(*b)) } } - impl<F : Num, const N : usize> $trait_assign<F> for Loc<F, N> { + impl<F: Num, const N: usize> $trait_assign<F> for Loc<N, F> { #[inline] - fn $fn_assign(&mut self, b : F) { + fn $fn_assign(&mut self, b: F) { self.map_mut(|a| a.$fn_assign(b)); } } - impl<'a, F : Num, const N : usize> $trait_assign<&'a F> for Loc<F, N> { + impl<'a, F: Num, const N: usize> $trait_assign<&'a F> for Loc<N, F> { #[inline] - fn $fn_assign(&mut self, b : &'a F) { + fn $fn_assign(&mut self, b: &'a F) { self.map_mut(|a| a.$fn_assign(*b)); } } - } + }; } - make_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); make_scalarop_rhs!(Div, div, DivAssign, div_assign); macro_rules! make_unaryop { ($trait:ident, $fn:ident) => { - impl<F : SignedNum, const N : usize> $trait for Loc<F, N> { - type Output = Loc<F, N>; + impl<F: SignedNum, const N: usize> $trait for Loc<N, F> { + type Output = Loc<N, F>; #[inline] fn $fn(mut self) -> Self::Output { self.map_mut(|a| *a = (*a).$fn()); @@ -341,48 +344,48 @@ } } - impl<'a, F : SignedNum, const N : usize> $trait for &'a Loc<F, N> { - type Output = Loc<F, N>; + impl<'a, F: SignedNum, const N: usize> $trait for &'a Loc<N, F> { + type Output = Loc<N, F>; #[inline] fn $fn(self) -> Self::Output { self.map(|a| a.$fn()) } } - } + }; } make_unaryop!(Neg, neg); macro_rules! make_scalarop_lhs { ($trait:ident, $fn:ident; $($f:ident)+) => { $( - impl<const N : usize> $trait<Loc<$f,N>> for $f { - type Output = Loc<$f, N>; + impl<const N : usize> $trait<Loc<N, $f>> for $f { + type Output = Loc<N, $f>; #[inline] - fn $fn(self, v : Loc<$f,N>) -> Self::Output { + fn $fn(self, v : Loc<N, $f>) -> Self::Output { v.map(|b| self.$fn(b)) } } - impl<'a, const N : usize> $trait<&'a Loc<$f,N>> for $f { - type Output = Loc<$f, N>; + impl<'a, const N : usize> $trait<&'a Loc<N, $f>> for $f { + type Output = Loc<N, $f>; #[inline] - fn $fn(self, v : &'a Loc<$f,N>) -> Self::Output { + fn $fn(self, v : &'a Loc<N, $f>) -> Self::Output { v.map(|b| self.$fn(b)) } } - impl<'b, const N : usize> $trait<Loc<$f,N>> for &'b $f { - type Output = Loc<$f, N>; + impl<'b, const N : usize> $trait<Loc<N, $f>> for &'b $f { + type Output = Loc<N, $f>; #[inline] - fn $fn(self, v : Loc<$f,N>) -> Self::Output { + fn $fn(self, v : Loc<N, $f>) -> Self::Output { v.map(|b| self.$fn(b)) } } - impl<'a, 'b, const N : usize> $trait<&'a Loc<$f,N>> for &'b $f { - type Output = Loc<$f, N>; + impl<'a, 'b, const N : usize> $trait<&'a Loc<N, $f>> for &'b $f { + type Output = Loc<N, $f>; #[inline] - fn $fn(self, v : &'a Loc<$f, N>) -> Self::Output { + fn $fn(self, v : &'a Loc<N, $f>) -> Self::Output { v.map(|b| self.$fn(b)) } } @@ -396,21 +399,21 @@ macro_rules! domination { ($norm:ident, $dominates:ident) => { - impl<F : Float, const N : usize> Dominated<F, $dominates, Loc<F, N>> for $norm { + impl<F: Float, const N: usize> Dominated<F, $dominates, Loc<N, F>> for $norm { #[inline] - fn norm_factor(&self, _p : $dominates) -> F { + fn norm_factor(&self, _p: $dominates) -> F { F::ONE } #[inline] - fn from_norm(&self, p_norm : F, _p : $dominates) -> F { + fn from_norm(&self, p_norm: F, _p: $dominates) -> F { p_norm } } }; ($norm:ident, $dominates:ident, $fn:path) => { - impl<F : Float, const N : usize> Dominated<F, $dominates, Loc<F, N>> for $norm { + impl<F: Float, const N: usize> Dominated<F, $dominates, Loc<N, F>> for $norm { #[inline] - fn norm_factor(&self, _p : $dominates) -> F { + fn norm_factor(&self, _p: $dominates) -> F { $fn(F::cast_from(N)) } } @@ -429,16 +432,17 @@ domination!(Linfinity, L2); domination!(L2, L1); -impl<F : Float,const N : usize> Euclidean<F> for Loc<F, N> { +impl<F: Float, const N: usize> Euclidean<F> for Loc<N, F> { type Output = Self; /// This implementation is not stabilised as it's meant to be used for very small vectors. /// Use [`nalgebra`] for larger vectors. #[inline] - fn dot<I : Instance<Self>>(&self, other : I) -> F { - self.0.iter() - .zip(other.ref_instance().0.iter()) - .fold(F::ZERO, |m, (&v, &w)| m + v * w) + fn dot<I: Instance<Self>>(&self, other: I) -> F { + self.0 + .iter() + .zip(other.ref_instance().0.iter()) + .fold(F::ZERO, |m, (&v, &w)| m + v * w) } /// This implementation is not stabilised as it's meant to be used for very small vectors. @@ -448,16 +452,19 @@ self.iter().fold(F::ZERO, |m, &v| m + v * v) } - fn dist2_squared<I : Instance<Self>>(&self, other : I) -> F { + fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { self.iter() .zip(other.ref_instance().iter()) - .fold(F::ZERO, |m, (&v, &w)| { let d = v - w; m + d * d }) + .fold(F::ZERO, |m, (&v, &w)| { + let d = v - w; + m + d * d + }) } #[inline] fn norm2(&self) -> F { // Optimisation for N==1 that avoids squaring and square rooting. - if N==1 { + if N == 1 { unsafe { self.0.get_unchecked(0) }.abs() } else { self.norm2_squared().sqrt() @@ -465,10 +472,10 @@ } #[inline] - fn dist2<I : Instance<Self>>(&self, other : I) -> F { + fn dist2<I: Instance<Self>>(&self, other: I) -> F { // Optimisation for N==1 that avoids squaring and square rooting. let otherr = other.ref_instance(); - if N==1 { + if N == 1 { unsafe { *self.0.get_unchecked(0) - *otherr.0.get_unchecked(0) }.abs() } else { self.dist2_squared(other).sqrt() @@ -476,28 +483,28 @@ } } -impl<F : Num, const N : usize> Loc<F, N> { +impl<F: Num, const N: usize> Loc<N, F> { /// Origin point - pub const ORIGIN : Self = Loc([F::ZERO; N]); + pub const ORIGIN: Self = Loc([F::ZERO; N]); } -impl<F : Num + std::ops::Neg<Output=F>, const N : usize> Loc<F, N> { +impl<F: Num + std::ops::Neg<Output = F>, const N: usize> Loc<N, F> { /// Reflects along the given coordinate - pub fn reflect(mut self, i : usize) -> Self { + pub fn reflect(mut self, i: usize) -> Self { self[i] = -self[i]; self } /// Reflects along the given coordinate sequences - pub fn reflect_many<I : IntoIterator<Item=usize>>(mut self, idxs : I) -> Self { + pub fn reflect_many<I: IntoIterator<Item = usize>>(mut self, idxs: I) -> Self { for i in idxs { - self[i]=-self[i] + self[i] = -self[i] } self } } -impl<F : std::ops::Neg<Output=F>> Loc<F, 2> { +impl<F: std::ops::Neg<Output = F>> Loc<2, F> { /// Reflect x coordinate pub fn reflect_x(self) -> Self { let Loc([x, y]) = self; @@ -511,18 +518,17 @@ } } -impl<F : Float> Loc<F, 2> { +impl<F: Float> Loc<2, F> { /// Rotate by angle φ - pub fn rotate(self, φ : F) -> Self { + pub fn rotate(self, φ: F) -> Self { let Loc([x, y]) = self; let sin_φ = φ.sin(); let cos_φ = φ.cos(); - [cos_φ * x - sin_φ * y, - sin_φ * x + cos_φ * y].into() + [cos_φ * x - sin_φ * y, sin_φ * x + cos_φ * y].into() } } -impl<F : std::ops::Neg<Output=F>> Loc<F, 3> { +impl<F: std::ops::Neg<Output = F>> Loc<3, F> { /// Reflect x coordinate pub fn reflect_x(self) -> Self { let Loc([x, y, z]) = self; @@ -542,39 +548,32 @@ } } -impl<F : Float> Loc<F, 3> { +impl<F: Float> Loc<3, F> { /// Rotate by angles (yaw, pitch, roll) - pub fn rotate(self, Loc([φ, ψ, θ]) : Self) -> Self { + pub fn rotate(self, Loc([φ, ψ, θ]): Self) -> Self { let Loc([mut x, mut y, mut z]) = self; let sin_φ = φ.sin(); let cos_φ = φ.cos(); - [x, y, z] = [cos_φ * x - sin_φ *y, - sin_φ * x + cos_φ * y, - z]; + [x, y, z] = [cos_φ * x - sin_φ * y, sin_φ * x + cos_φ * y, z]; let sin_ψ = ψ.sin(); let cos_ψ = ψ.cos(); - [x, y, z] = [cos_ψ * x + sin_ψ * z, - y, - -sin_ψ * x + cos_ψ * z]; + [x, y, z] = [cos_ψ * x + sin_ψ * z, y, -sin_ψ * x + cos_ψ * z]; let sin_θ = θ.sin(); let cos_θ = θ.cos(); - [x, y, z] = [x, - cos_θ * y - sin_θ * z, - sin_θ * y + cos_θ * z]; + [x, y, z] = [x, cos_θ * y - sin_θ * z, sin_θ * y + cos_θ * z]; [x, y, z].into() } } -impl<F : Float,const N : usize> StaticEuclidean<F> for Loc<F, N> { +impl<F: Float, const N: usize> StaticEuclidean<F> for Loc<N, F> { #[inline] fn origin() -> Self { Self::ORIGIN } } - /// The default norm for `Loc` is [`L2`]. -impl<F : Float, const N : usize> Normed<F> for Loc<F, N> { +impl<F: Float, const N: usize> Normed<F> for Loc<N, F> { type NormExp = L2; #[inline] @@ -593,22 +592,26 @@ } } -impl<F : Float, const N : usize> HasDual<F> for Loc<F, N> { +impl<F: Float, const N: usize> HasDual<F> for Loc<N, F> { type DualSpace = Self; } -impl<F : Float, const N : usize> Norm<F, L2> for Loc<F, N> { +impl<F: Float, const N: usize> Norm<L2, F> for Loc<N, F> { #[inline] - fn norm(&self, _ : L2) -> F { self.norm2() } + fn norm(&self, _: L2) -> F { + self.norm2() + } } -impl<F : Float, const N : usize> Dist<F, L2> for Loc<F, N> { +impl<F: Float, const N: usize> Dist<F, L2> for Loc<N, F> { #[inline] - fn dist<I : Instance<Self>>(&self, other : I, _ : L2) -> F { self.dist2(other) } + fn dist<I: Instance<Self>>(&self, other: I, _: L2) -> F { + self.dist2(other) + } } /* Implemented automatically as Euclidean. -impl<F : Float, const N : usize> Projection<F, L2> for Loc<F, N> { +impl<F : Float, const N : usize> Projection<F, L2> for Loc<N, F> { #[inline] fn proj_ball_mut(&mut self, ρ : F, nrm : L2) { let n = self.norm(nrm); @@ -618,53 +621,53 @@ } }*/ -impl<F : Float, const N : usize> Norm<F, L1> for Loc<F, N> { +impl<F: Float, const N: usize> Norm<L1, F> for Loc<N, F> { /// This implementation is not stabilised as it's meant to be used for very small vectors. /// Use [`nalgebra`] for larger vectors. #[inline] - fn norm(&self, _ : L1) -> F { + fn norm(&self, _: L1) -> F { self.iter().fold(F::ZERO, |m, v| m + v.abs()) } } -impl<F : Float, const N : usize> Dist<F, L1> for Loc<F, N> { +impl<F: Float, const N: usize> Dist<F, L1> for Loc<N, F> { #[inline] - fn dist<I : Instance<Self>>(&self, other : I, _ : L1) -> F { + fn dist<I: Instance<Self>>(&self, other: I, _: L1) -> F { self.iter() .zip(other.ref_instance().iter()) - .fold(F::ZERO, |m, (&v, &w)| m + (v-w).abs() ) + .fold(F::ZERO, |m, (&v, &w)| m + (v - w).abs()) } } -impl<F : Float, const N : usize> Projection<F, Linfinity> for Loc<F, N> { +impl<F: Float, const N: usize> Projection<F, Linfinity> for Loc<N, F> { #[inline] - fn proj_ball_mut(&mut self, ρ : F, _ : Linfinity) { - self.iter_mut().for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) + fn proj_ball_mut(&mut self, ρ: F, _: Linfinity) { + self.iter_mut() + .for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) } } -impl<F : Float, const N : usize> Norm<F, Linfinity> for Loc<F, N> { +impl<F: Float, const N: usize> Norm<Linfinity, F> for Loc<N, F> { /// This implementation is not stabilised as it's meant to be used for very small vectors. /// Use [`nalgebra`] for larger vectors. #[inline] - fn norm(&self, _ : Linfinity) -> F { + fn norm(&self, _: Linfinity) -> F { self.iter().fold(F::ZERO, |m, v| m.max(v.abs())) } } -impl<F : Float, const N : usize> Dist<F, Linfinity> for Loc<F, N> { +impl<F: Float, const N: usize> Dist<F, Linfinity> for Loc<N, F> { #[inline] - fn dist<I : Instance<Self>>(&self, other : I, _ : Linfinity) -> F { + fn dist<I: Instance<Self>>(&self, other: I, _: Linfinity) -> F { self.iter() .zip(other.ref_instance().iter()) - .fold(F::ZERO, |m, (&v, &w)| m.max((v-w).abs())) + .fold(F::ZERO, |m, (&v, &w)| m.max((v - w).abs())) } } - // Misc. -impl<A, const N : usize> FixedLength<N> for Loc<A,N> { +impl<A, const N: usize> FixedLength<N> for Loc<N, A> { type Iter = std::array::IntoIter<A, N>; type Elem = A; #[inline] @@ -673,15 +676,18 @@ } } -impl<A, const N : usize> FixedLengthMut<N> for Loc<A,N> { - type IterMut<'a> = std::slice::IterMut<'a, A> where A : 'a; +impl<A, const N: usize> FixedLengthMut<N> for Loc<N, A> { + type IterMut<'a> + = std::slice::IterMut<'a, A> + where + A: 'a; #[inline] fn fl_iter_mut(&mut self) -> Self::IterMut<'_> { self.iter_mut() } } -impl<'a, A, const N : usize> FixedLength<N> for &'a Loc<A,N> { +impl<'a, A, const N: usize> FixedLength<N> for &'a Loc<N, A> { type Iter = std::slice::Iter<'a, A>; type Elem = &'a A; #[inline] @@ -690,38 +696,37 @@ } } - -impl<F : Num, const N : usize> Space for Loc<F, N> { +impl<F: Num, const N: usize> Space for Loc<N, F> { type Decomp = BasicDecomposition; } -impl<F : Float, const N : usize> Mapping<Loc<F, N>> for Loc<F, N> { +impl<F: Float, const N: usize> Mapping<Loc<N, F>> for Loc<N, F> { type Codomain = F; - fn apply<I : Instance<Loc<F, N>>>(&self, x : I) -> Self::Codomain { + fn apply<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Codomain { x.eval(|x̃| self.dot(x̃)) } } -impl<F : Float, const N : usize> Linear<Loc<F, N>> for Loc<F, N> { } +impl<F: Float, const N: usize> Linear<Loc<N, F>> for Loc<N, F> {} -impl<F : Float, const N : usize> AXPY<F, Loc<F, N>> for Loc<F, N> { +impl<F: Float, const N: usize> AXPY<F, Loc<N, F>> for Loc<N, F> { type Owned = Self; #[inline] - fn axpy<I : Instance<Loc<F, N>>>(&mut self, α : F, x : I, β : F) { + fn axpy<I: Instance<Loc<N, F>>>(&mut self, α: F, x: I, β: F) { x.eval(|x̃| { if β == F::ZERO { - map2_mut(self, x̃, |yi, xi| { *yi = α * (*xi) }) + map2_mut(self, x̃, |yi, xi| *yi = α * (*xi)) } else { - map2_mut(self, x̃, |yi, xi| { *yi = β * (*yi) + α * (*xi) }) + map2_mut(self, x̃, |yi, xi| *yi = β * (*yi) + α * (*xi)) } }) } #[inline] - fn copy_from<I : Instance<Loc<F, N>>>(&mut self, x : I) { - x.eval(|x̃| map2_mut(self, x̃, |yi, xi| *yi = *xi )) + fn copy_from<I: Instance<Loc<N, F>>>(&mut self, x: I) { + x.eval(|x̃| map2_mut(self, x̃, |yi, xi| *yi = *xi)) } #[inline] @@ -734,4 +739,3 @@ *self = Self::ORIGIN; } } -