# HG changeset patch # User Tuomo Valkonen # Date 1747108096 18000 # Node ID d5dfcb6abcf5f9da32d47e2c0be687e97718f964 # Parent 22fd33834ab77a03f55dd8a9ec078751cc81e405 instantiated-fubar diff -r 22fd33834ab7 -r d5dfcb6abcf5 src/direct_product.rs --- a/src/direct_product.rs Mon May 12 21:56:42 2025 -0500 +++ b/src/direct_product.rs Mon May 12 22:48:16 2025 -0500 @@ -6,7 +6,9 @@ */ use crate::euclidean::Euclidean; -use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow}; +use crate::instance::{ + Decomposition, DecompositionMut, Instance, InstanceMut, Instantiated, MyCow, +}; use crate::linops::AXPY; use crate::loc::Loc; use crate::mapping::Space; @@ -367,6 +369,25 @@ Pair: 'b; } +impl Instantiated, PairDecomposition> for Pair +where + A: Space, + B: Space, + U: Instantiated, + V: Instantiated, + D: Decomposition, + Q: Decomposition, +{ + type RefInstance<'b> + = Pair, V::RefInstance<'b>> + where + Self: 'b; + + fn ref_inst(&self) -> Self::RefInstance<'_> { + Pair(self.0.ref_inst(), self.1.ref_inst()) + } +} + impl Instance, PairDecomposition> for Pair where A: Space, @@ -376,6 +397,12 @@ U: Instance, V: Instance, { + type Instantiated = Pair; + + fn instantiate(self) -> Self::Instantiated { + Pair(self.0.instantiate(), self.1.instantiate()) + } + fn eval_decompose<'b, R>( self, f: impl FnOnce(Pair, Q::Decomposition<'b>>) -> R, @@ -425,6 +452,14 @@ &'a U: Instance, &'a V: Instance, { + type Instantiated = + Pair<<&'a U as Instance>::Instantiated, <&'a V as Instance>::Instantiated>; + + fn instantiate(self) -> Self::Instantiated { + let &Pair(ref u, ref v) = self; + Pair(u.instantiate(), v.instantiate()) + } + fn eval_decompose<'b, R>( self, f: impl FnOnce(Pair, Q::Decomposition<'b>>) -> R, diff -r 22fd33834ab7 -r d5dfcb6abcf5 src/instance.rs --- a/src/instance.rs Mon May 12 21:56:42 2025 -0500 +++ b/src/instance.rs Mon May 12 22:48:16 2025 -0500 @@ -80,6 +80,32 @@ X: 'b; } +pub trait Instantiated::Decomp>: Instance +where + D: Decomposition, +{ + type RefInstance<'b>: Instance + Copy + where + Self: 'b; + + fn ref_inst(&self) -> Self::RefInstance<'_>; +} + +impl Instantiated for X +where + X: Instance + Clone, + for<'b> &'b X: Instance, +{ + type RefInstance<'b> + = &'b X + where + Self: 'b; + + fn ref_inst(&self) -> Self::RefInstance<'_> { + self + } +} + /// Helper trait for functions to work with either owned values or references to either the /// “principal type” `X` or types some present a subset of `X`. In the latter sense, this /// generalises [`std::borrow::ToOwned`], [`std::borrow::Borrow`], and [`std::borrow::Cow`]. @@ -89,6 +115,8 @@ where D: Decomposition, { + type Instantiated: Space + Instantiated; + /// 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 @@ -106,8 +134,23 @@ /// Returns an owned instance of `X`, cloning or converting non-true instances when necessary. fn own(self) -> X; + /// Instantiate to something that can be 'referenced'. + /// + /// This is distinct from [`own`], as it is not guaranteed that `&'b X` is an + /// [`Instance`] of `X`. + fn instantiate(self) -> Self::Instantiated; + // ************** automatically implemented methods below from here ************** + /// Evaluate `f` on the result of [`instantiate`]ing self, and then referencing. + fn eval_inst_ref( + self, + f: impl for<'b> FnOnce(>::RefInstance<'b>) -> R, + ) -> R { + let inst = self.instantiate(); + f(inst.ref_inst()) + } + /// Returns an owned instance or reference to `X`, converting non-true instances when necessary. /// /// Default implementation uses [`Self::own`]. Consumes the input. @@ -146,6 +189,12 @@ } impl Instance for X { + type Instantiated = X; + + fn instantiate(self) -> Self::Instantiated { + self + } + #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where @@ -179,6 +228,12 @@ } impl<'a, X: Space + Clone> Instance for &'a X { + type Instantiated = X; + + fn instantiate(self) -> Self::Instantiated { + self.own() + } + #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where @@ -212,6 +267,12 @@ } impl<'a, X: Space + Clone> Instance for &'a mut X { + type Instantiated = X; + + fn instantiate(self) -> Self::Instantiated { + self.own() + } + #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where @@ -246,6 +307,12 @@ } impl<'a, X: Space + Clone> Instance for MyCow<'a, X> { + type Instantiated = X; + + fn instantiate(self) -> Self::Instantiated { + self.own() + } + #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where diff -r 22fd33834ab7 -r d5dfcb6abcf5 src/operator_arithmetic.rs --- a/src/operator_arithmetic.rs Mon May 12 21:56:42 2025 -0500 +++ b/src/operator_arithmetic.rs Mon May 12 22:48:16 2025 -0500 @@ -2,7 +2,7 @@ Arithmetic of [`Mapping`]s. */ -use crate::instance::{Instance, Space}; +use crate::instance::{Instance, Instantiated, Space}; use crate::mapping::{DifferentiableImpl, DifferentiableMapping, Mapping}; use crate::types::*; use serde::Serialize; @@ -99,7 +99,9 @@ type Codomain = M::Codomain; fn apply>(&self, x: I) -> Self::Codomain { - x.eval_ref_decompose(|xr| self.0.iter().map(|c| c.apply(xr)).sum()) + let xi = x.instantiate(); + let xr = xi.ref_inst(); + self.0.iter().map(|c| c.apply(xr)).sum() } } @@ -112,6 +114,9 @@ type Derivative = M::DerivativeDomain; fn differential_impl>(&self, x: I) -> Self::Derivative { - x.eval_ref_decompose(|xr| self.0.iter().map(|c| c.differential(xr)).sum()) + let xi = x.instantiate(); + let xr = xi.ref_inst(); + + self.0.iter().map(|c| c.differential(xr)).sum() } } diff -r 22fd33834ab7 -r d5dfcb6abcf5 src/sets.rs --- a/src/sets.rs Mon May 12 21:56:42 2025 -0500 +++ b/src/sets.rs Mon May 12 22:48:16 2025 -0500 @@ -148,6 +148,6 @@ F: Float, { fn contains>(&self, item: I) -> bool { - item.eval_ref_decompose(|r| self.0.iter().all(|halfspace| halfspace.contains(r))) + item.eval_inst_ref(|r| self.0.iter().all(|halfspace| halfspace.contains(r))) } }