Mon, 12 May 2025 20:40:14 -0500
Replace Instance ref_instance and decompose by eval_* for flexibility
| src/direct_product.rs | file | annotate | diff | comparison | revisions | |
| src/discrete_gradient.rs | file | annotate | diff | comparison | revisions | |
| src/fe_model/p2_local_model.rs | file | annotate | diff | comparison | revisions | |
| src/instance.rs | file | annotate | diff | comparison | revisions | |
| src/linops.rs | file | annotate | diff | comparison | revisions | |
| src/loc.rs | file | annotate | diff | comparison | revisions | |
| src/mapping.rs | file | annotate | diff | comparison | revisions | |
| src/nalgebra_support.rs | file | annotate | diff | comparison | revisions | |
| src/operator_arithmetic.rs | file | annotate | diff | comparison | revisions | |
| src/sets.rs | file | annotate | diff | comparison | revisions |
--- a/src/direct_product.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/direct_product.rs Mon May 12 20:40:14 2025 -0500 @@ -285,8 +285,7 @@ + Neg<Output = <Self as AXPY>::Owned>, { fn dot<I: Instance<Self>>(&self, other: I) -> F { - let Pair(u, v) = other.decompose(); - self.0.dot(u) + self.1.dot(v) + other.eval_decompose(|Pair(u, v)| self.0.dot(u) + self.1.dot(v)) } fn norm2_squared(&self) -> F { @@ -294,8 +293,7 @@ } 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) + other.eval_decompose(|Pair(u, v)| self.0.dist2_squared(u) + self.1.dist2_squared(v)) } } @@ -316,21 +314,24 @@ type Owned = Pair<A::Owned, B::Owned>; fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) { - let Pair(u, v) = x.decompose(); - self.0.axpy(α, u, β); - self.1.axpy(α, v, β); + x.eval_decompose(|Pair(u, v)| { + self.0.axpy(α, u, β); + self.1.axpy(α, v, β); + }) } fn copy_from<I: Instance<Pair<U, V>>>(&mut self, x: I) { - let Pair(u, v) = x.decompose(); - self.0.copy_from(u); - self.1.copy_from(v); + x.eval_decompose(|Pair(u, v)| { + self.0.copy_from(u); + self.1.copy_from(v); + }) } fn scale_from<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I) { - let Pair(u, v) = x.decompose(); - self.0.scale_from(α, u); - self.1.scale_from(α, v); + x.eval_decompose(|Pair(u, v)| { + self.0.scale_from(α, u); + self.1.scale_from(α, v); + }) } /// Return a similar zero as `self`. @@ -384,22 +385,28 @@ U: Instance<A, D>, V: Instance<B, Q>, { - #[inline] - fn decompose<'b>( + fn eval_decompose<'b, R>( self, - ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Decomposition<'b> + f: impl FnOnce(Pair<D::Decomposition<'b>, Q::Decomposition<'b>>) -> R, + ) -> R where + Pair<A, B>: 'b, Self: 'b, - Pair<A, B>: 'b, { - Pair(self.0.decompose(), self.1.decompose()) + self.0 + .eval_decompose(|a| self.1.eval_decompose(|b| f(Pair(a, b)))) } - #[inline] - fn ref_instance( - &self, - ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Reference<'_> { - Pair(self.0.ref_instance(), self.1.ref_instance()) + fn eval_ref_decompose<'b, R>( + &'b self, + f: impl FnOnce(Pair<D::Reference<'b>, Q::Reference<'b>>) -> R, + ) -> R + where + Pair<A, B>: 'b, + Self: 'b, + { + self.0 + .eval_ref_decompose(|a| self.1.eval_ref_decompose(|b| f(Pair(a, b)))) } #[inline] @@ -427,25 +434,30 @@ &'a U: Instance<A, D>, &'a V: Instance<B, Q>, { - #[inline] - fn decompose<'b>( + fn eval_decompose<'b, R>( self, - ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Decomposition<'b> + f: impl FnOnce(Pair<D::Decomposition<'b>, Q::Decomposition<'b>>) -> R, + ) -> R where + Pair<A, B>: 'b, Self: 'b, - Pair<A, B>: 'b, { - Pair( - D::lift(self.0.ref_instance()), - Q::lift(self.1.ref_instance()), - ) + self.0.eval_ref_decompose(|a| { + self.1 + .eval_ref_decompose(|b| f(Pair(D::lift(a), Q::lift(b)))) + }) } - #[inline] - fn ref_instance( - &self, - ) -> <PairDecomposition<D, Q> as Decomposition<Pair<A, B>>>::Reference<'_> { - Pair(self.0.ref_instance(), self.1.ref_instance()) + fn eval_ref_decompose<'b, R>( + &'b self, + f: impl FnOnce(Pair<D::Reference<'b>, Q::Reference<'b>>) -> R, + ) -> R + where + Pair<A, B>: 'b, + Self: 'b, + { + self.0 + .eval_ref_decompose(|a| self.1.eval_ref_decompose(|b| f(Pair(a, b)))) } #[inline]
--- a/src/discrete_gradient.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/discrete_gradient.rs Mon May 12 20:40:14 2025 -0500 @@ -316,7 +316,7 @@ } let h = self.h; let m = self.len(); - i.eval(|x| { + i.eval_decompose(|x| { assert_eq!(x.len(), N * m); for d in 0..N { let v = x.generic_view((d * m, 0), (Dyn(m), U1));
--- a/src/fe_model/p2_local_model.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/fe_model/p2_local_model.rs Mon May 12 20:40:14 2025 -0500 @@ -32,9 +32,10 @@ impl<'a, F: Float> Set<Loc<1, F>> for RealInterval<F> { #[inline] fn contains<I: Instance<Loc<1, F>>>(&self, z: I) -> bool { - let &Loc([x]) = z.ref_instance(); - let &[Loc([x0]), Loc([x1])] = &self.0; - (x0 < x && x < x1) || (x1 < x && x < x0) + z.eval_ref_decompose(|&Loc([x])| { + let &[Loc([x0]), Loc([x1])] = &self.0; + (x0 < x && x < x1) || (x1 < x && x < x0) + }) } }
--- a/src/instance.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/instance.rs Mon May 12 20:40:14 2025 -0500 @@ -25,7 +25,10 @@ impl<'b, X> MyCow<'b, X> { #[inline] - pub fn into_owned(self) -> X where X : Clone { + pub fn into_owned(self) -> X + where + X: Clone, + { match self { EitherDecomp::Owned(x) => x, EitherDecomp::Borrowed(x) => x.clone(), @@ -34,9 +37,9 @@ } /// Trait for abitrary mathematical spaces. -pub trait Space : Instance<Self, Self::Decomp> { +pub trait Space: Instance<Self, Self::Decomp> { /// Default decomposition for the space - type Decomp : Decomposition<Self>; + type Decomp: Decomposition<Self>; } #[macro_export] @@ -58,17 +61,21 @@ f32 f64); /// Marker type for decompositions to be used with [`Instance`]. -pub trait Decomposition<X : Space> : Sized { +pub trait Decomposition<X: Space>: Sized { /// Possibly owned form of the decomposition - type Decomposition<'b> : Instance<X, Self> where X : 'b; + type Decomposition<'b>: Instance<X, Self> + where + X: 'b; /// Unlikely owned form of the decomposition. /// Type for a lightweight intermediate conversion that does not own the original variable. /// Usually this is just a reference, but may also be a lightweight structure that /// contains references; see the implementation for [`crate::direct_product::Pair`]. - type Reference<'b> : Instance<X, Self> + Copy where X : 'b; + type Reference<'b>: Instance<X, Self> + Copy + where + X: 'b; /// Left the lightweight reference type into a full decomposition type. - fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b>; + fn lift<'b>(r: Self::Reference<'b>) -> Self::Decomposition<'b>; } /// Most common [`Decomposition`] (into `Either<X, &'b X>`) that allows working with owned @@ -76,12 +83,18 @@ #[derive(Copy, Clone, Debug)] pub struct BasicDecomposition; -impl<X : Space + Clone> Decomposition<X> for BasicDecomposition { - type Decomposition<'b> = MyCow<'b, X> where X : 'b; - type Reference<'b> = &'b X where X : 'b; +impl<X: Space + Clone> Decomposition<X> for BasicDecomposition { + type Decomposition<'b> + = MyCow<'b, X> + where + X: 'b; + type Reference<'b> + = &'b X + where + X: 'b; #[inline] - fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b> { + fn lift<'b>(r: Self::Reference<'b>) -> Self::Decomposition<'b> { MyCow::Borrowed(r) } } @@ -91,13 +104,23 @@ /// generalises [`std::borrow::ToOwned`], [`std::borrow::Borrow`], and [`std::borrow::Cow`]. /// /// This is used, for example, by [`crate::mapping::Mapping::apply`]. -pub trait Instance<X : Space, D = <X as Space>::Decomp> : Sized where D : Decomposition<X> { - /// Decomposes self according to `decomposer`. - fn decompose<'b>(self) -> D::Decomposition<'b> - where Self : 'b, X : 'b; - - /// Returns a lightweight instance of `self`. - fn ref_instance(&self) -> D::Reference<'_>; +pub trait Instance<X: Space, D = <X as Space>::Decomp>: Sized +where + D: Decomposition<X>, +{ + /// Decomposes self according to `decomposer`, and evaluate `f` on the result. + /// Consumes self. + fn eval_decompose<'b, R>(self, f: impl FnOnce(D::Decomposition<'b>) -> R) -> R + where + X: 'b, + Self: 'b; + + /// Does a light decomposition of self `decomposer`, and evaluates `f` on the result. + /// Does not consume self. + fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(D::Reference<'b>) -> R) -> R + where + X: 'b, + Self: 'b; /// Returns an owned instance of `X`, cloning or converting non-true instances when necessary. fn own(self) -> X; @@ -107,16 +130,21 @@ /// Returns an owned instance or reference to `X`, converting non-true instances when necessary. /// /// Default implementation uses [`Self::own`]. Consumes the input. - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b { + fn cow<'b>(self) -> MyCow<'b, X> + where + Self: 'b, + { MyCow::Owned(self.own()) } - + #[inline] /// Evaluates `f` on a reference to self. /// /// Default implementation uses [`Self::cow`]. Consumes the input. - fn eval<'b, R>(self, f : impl FnOnce(&X) -> R) -> R - where X : 'b, Self : 'b + fn eval<'b, R>(self, f: impl FnOnce(&X) -> R) -> R + where + X: 'b, + Self: 'b, { f(&*self.cow()) } @@ -125,12 +153,9 @@ /// Evaluates `f` or `g` depending on whether a reference or owned value is available. /// /// Default implementation uses [`Self::cow`]. Consumes the input. - fn either<'b, R>( - self, - f : impl FnOnce(X) -> R, - g : impl FnOnce(&X) -> R - ) -> R - where Self : 'b + fn either<'b, R>(self, f: impl FnOnce(X) -> R, g: impl FnOnce(&X) -> R) -> R + where + Self: 'b, { match self.cow() { EitherDecomp::Owned(x) => f(x), @@ -139,13 +164,23 @@ } } - -impl<X : Space + Clone> Instance<X, BasicDecomposition> for X { +impl<X: Space + Clone> Instance<X, BasicDecomposition> for X { #[inline] - fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b> - where Self : 'b, X : 'b + fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R + where + X: 'b, + Self: 'b, { - MyCow::Owned(self) + f(MyCow::Owned(self)) + } + + #[inline] + fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R + where + X: 'b, + Self: 'b, + { + f(self) } #[inline] @@ -154,22 +189,31 @@ } #[inline] - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b { + fn cow<'b>(self) -> MyCow<'b, X> + where + Self: 'b, + { MyCow::Owned(self) } +} + +impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for &'a X { + #[inline] + fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R + where + X: 'b, + Self: 'b, + { + f(MyCow::Borrowed(self)) + } #[inline] - fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> { - self - } -} - -impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for &'a X { - #[inline] - fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b> - where Self : 'b, X : 'b + fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R + where + X: 'b, + Self: 'b, { - MyCow::Borrowed(self) + f(*self) } #[inline] @@ -178,22 +222,31 @@ } #[inline] - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b { + fn cow<'b>(self) -> MyCow<'b, X> + where + Self: 'b, + { MyCow::Borrowed(self) } +} + +impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for &'a mut X { + #[inline] + fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R + where + X: 'b, + Self: 'b, + { + f(EitherDecomp::Borrowed(self)) + } #[inline] - fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> { - *self - } -} - -impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for &'a mut X { - #[inline] - fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b> - where Self : 'b, X : 'b + fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R + where + X: 'b, + Self: 'b, { - EitherDecomp::Borrowed(self) + f(*self) } #[inline] @@ -202,81 +255,95 @@ } #[inline] - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b, X : Clone { + fn cow<'b>(self) -> MyCow<'b, X> + where + Self: 'b, + X: Clone, + { EitherDecomp::Borrowed(self) } +} + +impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for MyCow<'a, X> { + #[inline] + fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R + where + X: 'b, + Self: 'b, + { + f(self) + } #[inline] - fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> { - *self - } -} - -impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for MyCow<'a, X> { - - #[inline] - fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b> - where Self : 'b, X : 'b + fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R + where + X: 'b, + Self: 'b, { - self + match self { + MyCow::Borrowed(a) => f(a), + MyCow::Owned(b) => f(&b), + } } #[inline] fn own(self) -> X { match self { MyCow::Borrowed(a) => a.own(), - MyCow::Owned(b) => b.own() + MyCow::Owned(b) => b.own(), } } #[inline] - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b { + fn cow<'b>(self) -> MyCow<'b, X> + where + Self: 'b, + { match self { MyCow::Borrowed(a) => a.cow(), - MyCow::Owned(b) => b.cow() - } - } - - #[inline] - fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> { - match self { - MyCow::Borrowed(a) => a, - MyCow::Owned(b) => &b, + MyCow::Owned(b) => b.cow(), } } } /// Marker type for mutable decompositions to be used with [`InstanceMut`]. -pub trait DecompositionMut<X : Space> : Sized { - type ReferenceMut<'b> : InstanceMut<X, Self> where X : 'b; +pub trait DecompositionMut<X: Space>: Sized { + type ReferenceMut<'b>: InstanceMut<X, Self> + where + X: 'b; } - /// Helper trait for functions to work with mutable references. -pub trait InstanceMut<X : Space , D = <X as Space>::Decomp> : Sized where D : DecompositionMut<X> { +pub trait InstanceMut<X: Space, D = <X as Space>::Decomp>: Sized +where + D: DecompositionMut<X>, +{ /// Returns a mutable decomposition of self. fn ref_instance_mut(&mut self) -> D::ReferenceMut<'_>; } -impl<X : Space> DecompositionMut<X> for BasicDecomposition { - type ReferenceMut<'b> = &'b mut X where X : 'b; +impl<X: Space> DecompositionMut<X> for BasicDecomposition { + type ReferenceMut<'b> + = &'b mut X + where + X: 'b; } /// This impl may seem pointless, but allows throwaway mutable scratch variables -impl<'a, X : Space> InstanceMut<X, BasicDecomposition> for X { +impl<'a, X: Space> InstanceMut<X, BasicDecomposition> for X { #[inline] - fn ref_instance_mut(&mut self) - -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_> - { + fn ref_instance_mut( + &mut self, + ) -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_> { self } } -impl<'a, X : Space> InstanceMut<X, BasicDecomposition> for &'a mut X { +impl<'a, X: Space> InstanceMut<X, BasicDecomposition> for &'a mut X { #[inline] - fn ref_instance_mut(&mut self) - -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_> - { + fn ref_instance_mut( + &mut self, + ) -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_> { self } }
--- a/src/linops.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/linops.rs Mon May 12 20:40:14 2025 -0500 @@ -530,8 +530,7 @@ type Codomain = <S::Codomain as Add<T::Codomain>>::Output; fn apply<I: Instance<Pair<A, B>>>(&self, x: I) -> Self::Codomain { - let Pair(a, b) = x.decompose(); - self.0.apply(a) + self.1.apply(b) + x.eval_decompose(|Pair(a, b)| self.0.apply(a) + self.1.apply(b)) } } @@ -556,22 +555,25 @@ Self: Linear<Pair<U, V>, Codomain = Y>, { fn gemv<I: Instance<Pair<U, V>>>(&self, y: &mut Y, α: F, x: I, β: F) { - let Pair(u, v) = x.decompose(); - self.0.gemv(y, α, u, β); - self.1.gemv(y, α, v, F::ONE); + x.eval_decompose(|Pair(u, v)| { + self.0.gemv(y, α, u, β); + self.1.gemv(y, α, v, F::ONE); + }) } fn apply_mut<I: Instance<Pair<U, V>>>(&self, y: &mut Y, x: I) { - let Pair(u, v) = x.decompose(); - self.0.apply_mut(y, u); - self.1.apply_add(y, v); + x.eval_decompose(|Pair(u, v)| { + self.0.apply_mut(y, u); + self.1.apply_add(y, v); + }) } /// Computes `y += Ax`, where `A` is `Self` fn apply_add<I: Instance<Pair<U, V>>>(&self, y: &mut Y, x: I) { - let Pair(u, v) = x.decompose(); - self.0.apply_add(y, u); - self.1.apply_add(y, v); + x.eval_decompose(|Pair(u, v)| { + self.0.apply_add(y, u); + self.1.apply_add(y, v); + }) } } @@ -588,7 +590,7 @@ type Codomain = Pair<S::Codomain, T::Codomain>; fn apply<I: Instance<A>>(&self, a: I) -> Self::Codomain { - Pair(self.0.apply(a.ref_instance()), self.1.apply(a)) + Pair(a.eval_ref_decompose(|r| self.0.apply(r)), self.1.apply(a)) } } @@ -609,18 +611,18 @@ Self: Linear<X, Codomain = Pair<A, B>>, { fn gemv<I: Instance<X>>(&self, y: &mut Pair<A, B>, α: F, x: I, β: F) { - self.0.gemv(&mut y.0, α, x.ref_instance(), β); + x.eval_ref_decompose(|r| self.0.gemv(&mut y.0, α, r, β)); self.1.gemv(&mut y.1, α, x, β); } fn apply_mut<I: Instance<X>>(&self, y: &mut Pair<A, B>, x: I) { - self.0.apply_mut(&mut y.0, x.ref_instance()); + x.eval_ref_decompose(|r| self.0.apply_mut(&mut y.0, r)); self.1.apply_mut(&mut y.1, x); } /// Computes `y += Ax`, where `A` is `Self` fn apply_add<I: Instance<X>>(&self, y: &mut Pair<A, B>, x: I) { - self.0.apply_add(&mut y.0, x.ref_instance()); + x.eval_ref_decompose(|r| self.0.apply_add(&mut y.0, r)); self.1.apply_add(&mut y.1, x); } } @@ -732,8 +734,7 @@ type Codomain = Pair<S::Codomain, T::Codomain>; fn apply<I: Instance<Pair<A, B>>>(&self, x: I) -> Self::Codomain { - let Pair(a, b) = x.decompose(); - Pair(self.0.apply(a), self.1.apply(b)) + x.eval_decompose(|Pair(a, b)| Pair(self.0.apply(a), self.1.apply(b))) } } @@ -758,22 +759,25 @@ Self: Linear<Pair<U, V>, Codomain = Pair<A, B>>, { fn gemv<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, α: F, x: I, β: F) { - let Pair(u, v) = x.decompose(); - self.0.gemv(&mut y.0, α, u, β); - self.1.gemv(&mut y.1, α, v, β); + x.eval_decompose(|Pair(u, v)| { + self.0.gemv(&mut y.0, α, u, β); + self.1.gemv(&mut y.1, α, v, β); + }) } fn apply_mut<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, x: I) { - let Pair(u, v) = x.decompose(); - self.0.apply_mut(&mut y.0, u); - self.1.apply_mut(&mut y.1, v); + x.eval_decompose(|Pair(u, v)| { + self.0.apply_mut(&mut y.0, u); + self.1.apply_mut(&mut y.1, v); + }) } /// Computes `y += Ax`, where `A` is `Self` fn apply_add<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, x: I) { - let Pair(u, v) = x.decompose(); - self.0.apply_add(&mut y.0, u); - self.1.apply_add(&mut y.1, v); + x.eval_decompose(|Pair(u, v)| { + self.0.apply_add(&mut y.0, u); + self.1.apply_add(&mut y.1, v); + }) } }
--- a/src/loc.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/loc.rs Mon May 12 20:40:14 2025 -0500 @@ -437,10 +437,12 @@ /// 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) + other.eval_ref_decompose(|r| { + self.0 + .iter() + .zip(r.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. @@ -451,12 +453,12 @@ } fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { - self.iter() - .zip(other.ref_instance().iter()) - .fold(F::ZERO, |m, (&v, &w)| { + other.eval_ref_decompose(|r| { + self.iter().zip(r.iter()).fold(F::ZERO, |m, (&v, &w)| { let d = v - w; m + d * d }) + }) } #[inline] @@ -472,9 +474,10 @@ #[inline] 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 { - unsafe { *self.0.get_unchecked(0) - *otherr.0.get_unchecked(0) }.abs() + other.eval_ref_decompose(|r| { + unsafe { *self.0.get_unchecked(0) - *r.0.get_unchecked(0) }.abs() + }) } else { self.dist2_squared(other).sqrt() } @@ -631,9 +634,11 @@ impl<F: Float, const N: usize> Dist<F, L1> for Loc<N, F> { #[inline] 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()) + other.eval_ref_decompose(|r| { + self.iter() + .zip(r.iter()) + .fold(F::ZERO, |m, (&v, &w)| m + (v - w).abs()) + }) } } @@ -657,9 +662,11 @@ impl<F: Float, const N: usize> Dist<F, Linfinity> for Loc<N, F> { #[inline] 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())) + other.eval_ref_decompose(|r| { + self.iter() + .zip(r.iter()) + .fold(F::ZERO, |m, (&v, &w)| m.max((v - w).abs())) + }) } } @@ -702,7 +709,7 @@ type Codomain = F; fn apply<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Codomain { - x.eval(|x̃| self.dot(x̃)) + x.eval_decompose(|x̃| self.dot(x̃)) } }
--- a/src/mapping.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/mapping.rs Mon May 12 20:40:14 2025 -0500 @@ -308,8 +308,9 @@ // inner: self.inner.differential_impl(x), // intermediate_norm_exponent: self.intermediate_norm_exponent, // } + self.outer - .differential_impl(self.inner.apply(x.ref_instance())) + .differential_impl(x.eval_ref_decompose(|r| self.inner.apply(r))) * self.inner.differential_impl(x) } }
--- a/src/nalgebra_support.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/nalgebra_support.rs Mon May 12 20:40:14 2025 -0500 @@ -224,7 +224,7 @@ { #[inline] fn dot<I: Instance<Self>>(&self, other: I) -> E { - Vector::<E, M, S>::dot(self, other.ref_instance()) + other.eval_ref_decompose(|r| Vector::<E, M, S>::dot(self, r)) } #[inline] @@ -234,7 +234,7 @@ #[inline] fn dist2_squared<I: Instance<Self>>(&self, other: I) -> E { - metric_distance_squared(self, other.ref_instance()) + other.eval_ref_decompose(|r| metric_distance_squared(self, r)) } } @@ -305,7 +305,7 @@ { #[inline] fn dist<I: Instance<Self>>(&self, other: I, _: L1) -> E { - nalgebra::Norm::metric_distance(&LpNorm(1), self, other.ref_instance()) + other.eval_ref_decompose(|r| nalgebra::Norm::metric_distance(&LpNorm(1), self, r)) } } @@ -331,7 +331,7 @@ { #[inline] fn dist<I: Instance<Self>>(&self, other: I, _: L2) -> E { - nalgebra::Norm::metric_distance(&LpNorm(2), self, other.ref_instance()) + other.eval_ref_decompose(|r| nalgebra::Norm::metric_distance(&LpNorm(2), self, r)) } } @@ -357,7 +357,7 @@ { #[inline] fn dist<I: Instance<Self>>(&self, other: I, _: Linfinity) -> E { - nalgebra::Norm::metric_distance(&UniformNorm, self, other.ref_instance()) + other.eval_ref_decompose(|r| nalgebra::Norm::metric_distance(&UniformNorm, self, r)) } }
--- a/src/operator_arithmetic.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/operator_arithmetic.rs Mon May 12 20:40:14 2025 -0500 @@ -99,8 +99,7 @@ type Codomain = M::Codomain; fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { - let xr = x.ref_instance(); - self.0.iter().map(|c| c.apply(xr)).sum() + x.eval_ref_decompose(|xr| self.0.iter().map(|c| c.apply(xr)).sum()) } } @@ -113,7 +112,6 @@ type Derivative = M::DerivativeDomain; fn differential_impl<I: Instance<Domain>>(&self, x: I) -> Self::Derivative { - let xr = x.ref_instance(); - self.0.iter().map(|c| c.differential(xr)).sum() + x.eval_ref_decompose(|xr| self.0.iter().map(|c| c.differential(xr)).sum()) } }
--- a/src/sets.rs Mon May 12 19:30:41 2025 -0500 +++ b/src/sets.rs Mon May 12 20:40:14 2025 -0500 @@ -36,10 +36,7 @@ U: Num + PartialOrd + Sized, { fn contains<I: Instance<Loc<N, U>>>(&self, item: I) -> bool { - self.0 - .iter() - .zip(item.ref_instance().iter()) - .all(|(s, x)| s.contains(x)) + item.eval_ref_decompose(|r| self.0.iter().zip(r.iter()).all(|(s, x)| s.contains(x))) } } @@ -151,7 +148,6 @@ F: Float, { fn contains<I: Instance<A>>(&self, item: I) -> bool { - let r = item.ref_instance(); - self.0.iter().all(|halfspace| halfspace.contains(r)) + item.eval_ref_decompose(|r| self.0.iter().all(|halfspace| halfspace.contains(r))) } }