diff -r 1a38447a89fa -r 9226980e45a7 src/mapping.rs --- a/src/mapping.rs Sat Dec 14 09:31:27 2024 -0500 +++ b/src/mapping.rs Tue Dec 31 08:30:02 2024 -0500 @@ -3,43 +3,20 @@ */ use std::marker::PhantomData; +use std::borrow::Cow; use crate::types::Float; use serde::Serialize; use crate::loc::Loc; - -/// Trait for application of `Self` as a mathematical function or operator on `X`. -pub trait Apply { - type Output; - - /// Compute the value of `self` at `x`. - fn apply(&self, x : X) -> Self::Output; -} - -/// This blanket implementation is a workaround helper to Rust trait system limitations. -/// -/// It is introduced because the trait system does not allow blanket implementations of both -/// [`Apply`] and [`Apply<&'a X>`]. With this, the latter is implemented automatically for -/// the reference, which can be sufficient to apply the operation in another blanket implementation. -impl<'a, T, X> Apply for &'a T where T : Apply { - type Output = >::Output; - - #[inline] - fn apply(&self, x : X) -> Self::Output { - (*self).apply(x) - } -} +pub use crate::instance::{Instance, Decomposition, BasicDecomposition, Space}; /// A mapping from `Domain` to `Codomain`. /// /// This is automatically implemented when the relevant [`Apply`] are implemented. -pub trait Mapping : Apply - + for<'a> Apply<&'a Domain, Output=Self::Codomain> { - type Codomain; -} +pub trait Mapping { + type Codomain : Space; -impl Mapping for T -where T : Apply + for<'a> Apply<&'a Domain, Output=Codomain> { - type Codomain = Codomain; + /// Compute the value of `self` at `x`. + fn apply>(&self, x : I) -> Self::Codomain; } /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc`] to `F`. @@ -49,15 +26,6 @@ impl RealMapping for T where T : Mapping, Codomain = F> {} -/// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from -/// [`Loc`] to `F`. -pub trait DifferentiableRealMapping -: DifferentiableMapping, Codomain = F, DerivativeDomain=Loc> {} - -impl DifferentiableRealMapping for T -where T : DifferentiableMapping, Codomain = F, DerivativeDomain=Loc> {} - - /// A helper trait alias for referring to [`Mapping`]s from [`Loc`] to [`Loc`]. pub trait RealVectorField : Mapping, Codomain = Loc> {} @@ -65,69 +33,70 @@ impl RealVectorField for T where T : Mapping, Codomain = Loc> {} - -/// Trait for calculation the differential of `Self` as a mathematical function on `X`. -pub trait Differentiable : Sized { - type Derivative; - - /// Compute the differential of `self` at `x`. - fn differential(&self, x : X) -> Self::Derivative; -} - -impl<'g, X, G : Differentiable> Differentiable for &'g G { - type Derivative = G::Derivative; - #[inline] - fn differential(&self, x : X) -> Self::Derivative { - (*self).differential(x) - } -} - /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials /// `Differential`. /// -/// This is automatically implemented when the relevant [`Differentiable`] are implemented. -pub trait DifferentiableMapping -: Mapping - + Differentiable - + for<'a> Differentiable<&'a Domain, Derivative=Self::DerivativeDomain> { - type DerivativeDomain; - type Differential : Mapping; - type DifferentialRef<'b> : Mapping where Self : 'b; +/// This is automatically implemented when [`DifferentiableImpl`] is. +pub trait DifferentiableMapping : Mapping { + type DerivativeDomain : Space; + type Differential<'b> : Mapping where Self : 'b; + + /// Calculate differential at `x` + fn differential>(&self, x : I) -> Self::DerivativeDomain; /// Form the differential mapping of `self`. - fn diff(self) -> Self::Differential; + fn diff(self) -> Self::Differential<'static>; + /// Form the differential mapping of `self`. - fn diff_ref(&self) -> Self::DifferentialRef<'_>; + fn diff_ref(&self) -> Self::Differential<'_>; } +/// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from +/// [`Loc`] to `F`. +pub trait DifferentiableRealMapping +: DifferentiableMapping, Codomain = F, DerivativeDomain = Loc> {} -impl DifferentiableMapping for T -where T : Mapping - + Differentiable - + for<'a> Differentiable<&'a Domain,Derivative=Derivative> { - type DerivativeDomain = Derivative; - type Differential = Differential; - type DifferentialRef<'b> = Differential where Self : 'b; +impl DifferentiableRealMapping for T +where T : DifferentiableMapping, Codomain = F, DerivativeDomain = Loc> {} + +/// Helper trait for implementing [`DifferentiableMapping`] +pub trait DifferentiableImpl : Sized { + type Derivative : Space; + + /// Compute the differential of `self` at `x`, consuming the input. + fn differential_impl>(&self, x : I) -> Self::Derivative; +} + +impl DifferentiableMapping for T +where + Domain : Space, + T : Clone + Mapping + DifferentiableImpl +{ + type DerivativeDomain = T::Derivative; + type Differential<'b> = Differential<'b, Domain, Self> where Self : 'b; - /// Form the differential mapping of `self`. - fn diff(self) -> Self::Differential { - Differential{ g : self, _space : PhantomData } + #[inline] + fn differential>(&self, x : I) -> Self::DerivativeDomain { + self.differential_impl(x) } - /// Form the differential mapping of `self`. - fn diff_ref(&self) -> Self::DifferentialRef<'_> { - Differential{ g : self, _space : PhantomData } + fn diff(self) -> Differential<'static, Domain, Self> { + Differential{ g : Cow::Owned(self), _space : PhantomData } + } + + fn diff_ref(&self) -> Differential<'_, Domain, Self> { + Differential{ g : Cow::Borrowed(self), _space : PhantomData } } } /// A sum of [`Mapping`]s. #[derive(Serialize, Debug, Clone)] -pub struct Sum> { +pub struct Sum { components : Vec, _domain : PhantomData, } -impl> Sum { +impl Sum { /// Construct from an iterator. pub fn new>(iter : I) -> Self { Sum { components : iter.collect(), _domain : PhantomData } @@ -140,123 +109,107 @@ } -impl Apply for Sum -where M : Mapping, - M::Codomain : std::iter::Sum { - type Output = M::Codomain; +impl Mapping for Sum +where + Domain : Space + Clone, + M : Mapping, + M::Codomain : std::iter::Sum + Clone +{ + type Codomain = M::Codomain; - fn apply(&self, x : Domain) -> Self::Output { - self.components.iter().map(|c| c.apply(&x)).sum() + fn apply>(&self, x : I) -> Self::Codomain { + let xr = x.ref_instance(); + self.components.iter().map(|c| c.apply(xr)).sum() } } -impl<'a, Domain, M> Apply<&'a Domain> for Sum -where M : Mapping, - M::Codomain : std::iter::Sum { - type Output = M::Codomain; - - fn apply(&self, x : &'a Domain) -> Self::Output { - self.components.iter().map(|c| c.apply(x)).sum() - } -} - -impl Differentiable for Sum -where M : DifferentiableMapping, - M :: Codomain : std::iter::Sum, - M :: DerivativeDomain : std::iter::Sum, - Domain : Copy { - +impl DifferentiableImpl for Sum +where + Domain : Space + Clone, + M : DifferentiableMapping, + M :: DerivativeDomain : std::iter::Sum +{ type Derivative = M::DerivativeDomain; - fn differential(&self, x : Domain) -> Self::Derivative { - self.components.iter().map(|c| c.differential(x)).sum() + fn differential_impl>(&self, x : I) -> Self::Derivative { + let xr = x.ref_instance(); + self.components.iter().map(|c| c.differential(xr)).sum() } } /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. -pub struct Differential> { - g : G, +pub struct Differential<'a, X, G : Clone> { + g : Cow<'a, G>, _space : PhantomData } -impl> Differential { +impl<'a, X, G : Clone> Differential<'a, X, G> { pub fn base_fn(&self) -> &G { &self.g } } -impl> Apply for Differential { - type Output = G::DerivativeDomain; +impl<'a, X, G> Mapping for Differential<'a, X, G> +where + X : Space, + G : Clone + DifferentiableMapping +{ + type Codomain = G::DerivativeDomain; #[inline] - fn apply(&self, x : X) -> Self::Output { - self.g.differential(x) + fn apply>(&self, x : I) -> Self::Codomain { + (*self.g).differential(x) } } -impl<'a, X, G : DifferentiableMapping> Apply<&'a X> for Differential { - type Output = G::DerivativeDomain; - - #[inline] - fn apply(&self, x : &'a X) -> Self::Output { - self.g.differential(x) - } -} - - /// Container for flattening [`Loc`]`` codomain of a [`Mapping`] to `F`. -pub struct FlattenedCodomain>> { +pub struct FlattenedCodomain { g : G, _phantoms : PhantomData<(X, F)> } -impl>> Apply for FlattenedCodomain { - type Output = F; +impl Mapping for FlattenedCodomain +where + X : Space, + G: Mapping> +{ + type Codomain = F; #[inline] - fn apply(&self, x : X) -> Self::Output { + fn apply>(&self, x : I) -> Self::Codomain { self.g.apply(x).flatten1d() } } /// An auto-trait for constructing a [`FlattenCodomain`] structure for /// flattening the codomain of a [`Mapping`] from [`Loc`]`` to `F`. -pub trait FlattenCodomain : Mapping> + Sized { +pub trait FlattenCodomain : Mapping> + Sized { /// Flatten the codomain from [`Loc`]`` to `F`. fn flatten_codomain(self) -> FlattenedCodomain { FlattenedCodomain{ g : self, _phantoms : PhantomData } } } -impl>> FlattenCodomain for G {} - +impl>> FlattenCodomain for G {} /// Container for dimensional slicing [`Loc`]`` codomain of a [`Mapping`] to `F`. -pub struct SlicedCodomain>, const N : usize> { - g : G, +pub struct SlicedCodomain<'a, X, F, G : Clone, const N : usize> { + g : Cow<'a, G>, slice : usize, _phantoms : PhantomData<(X, F)> } -impl>, const N : usize> Apply -for SlicedCodomain { - type Output = F; +impl<'a, X, F, G, const N : usize> Mapping for SlicedCodomain<'a, X, F, G, N> +where + X : Space, + F : Copy + Space, + G : Mapping> + Clone, +{ + type Codomain = F; #[inline] - fn apply(&self, x : X) -> Self::Output { - let tmp : [F; N] = self.g.apply(x).into(); - // Safety: `slice_codomain` below checks the range. - unsafe { *tmp.get_unchecked(self.slice) } - } -} - -impl<'a, X, F : Copy, G : Mapping>, const N : usize> Apply<&'a X> -for SlicedCodomain { - type Output = F; - - #[inline] - fn apply(&self, x : &'a X) -> Self::Output { - let tmp : [F; N] = self.g.apply(x).into(); + fn apply>(&self, x : I) -> Self::Codomain { + let tmp : [F; N] = (*self.g).apply(x).into(); // Safety: `slice_codomain` below checks the range. unsafe { *tmp.get_unchecked(self.slice) } } @@ -264,21 +217,22 @@ /// An auto-trait for constructing a [`FlattenCodomain`] structure for /// flattening the codomain of a [`Mapping`] from [`Loc`]`` to `F`. -pub trait SliceCodomain : Mapping> + Sized { +pub trait SliceCodomain + : Mapping> + Clone + Sized +{ /// Flatten the codomain from [`Loc`]`` to `F`. - fn slice_codomain(self, slice : usize) -> SlicedCodomain { + fn slice_codomain(self, slice : usize) -> SlicedCodomain<'static, X, F, Self, N> { assert!(slice < N); - SlicedCodomain{ g : self, slice, _phantoms : PhantomData } + SlicedCodomain{ g : Cow::Owned(self), slice, _phantoms : PhantomData } } /// Flatten the codomain from [`Loc`]`` to `F`. - fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain { + fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<'_, X, F, Self, N> { assert!(slice < N); - SlicedCodomain{ g : self, slice, _phantoms : PhantomData } + SlicedCodomain{ g : Cow::Borrowed(self), slice, _phantoms : PhantomData } } } -impl>, const N : usize> +impl> + Clone, const N : usize> SliceCodomain for G {} -