diff -r edb95d2b83cc -r d2acaaddd9af src/mapping.rs --- a/src/mapping.rs Sun Nov 10 09:02:57 2024 -0500 +++ b/src/mapping.rs Tue Dec 31 09:12:43 2024 -0500 @@ -3,9 +3,10 @@ */ use std::marker::PhantomData; -use crate::types::Float; +use crate::types::{Float, HasRealField, HasScalarField}; use serde::Serialize; use crate::loc::Loc; +use std::borrow::Cow; /// Trait for application of `Self` as a mathematical function or operator on `X`. pub trait Apply { @@ -44,43 +45,47 @@ /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc`] to `F`. pub trait RealMapping -: Mapping, Codomain = F> {} +: Mapping, Codomain = F> + HasRealField {} impl RealMapping for T -where T : Mapping, Codomain = F> {} +where T : Mapping, Codomain = F> + HasRealField {} /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from /// [`Loc`] to `F`. pub trait DifferentiableRealMapping -: DifferentiableMapping, Codomain = F, DerivativeDomain=Loc> {} +: DifferentiableMapping, Codomain = F, DerivativeDomain=Loc> + + RealMapping + + HasRealField {} impl DifferentiableRealMapping for T -where T : DifferentiableMapping, Codomain = F, DerivativeDomain=Loc> {} +where T : DifferentiableMapping, Codomain = F, DerivativeDomain=Loc> + + RealMapping + + HasRealField {} /// A helper trait alias for referring to [`Mapping`]s from [`Loc`] to [`Loc`]. pub trait RealVectorField -: Mapping, Codomain = Loc> {} +: Mapping, Codomain = Loc> + HasRealField {} impl RealVectorField for T -where T : Mapping, Codomain = Loc> {} +where T : Mapping, Codomain = Loc> + HasRealField {} /// Trait for calculation the differential of `Self` as a mathematical function on `X`. -pub trait Differentiable : Sized { - type Derivative; +pub trait Differentiable : Sized + HasRealField { + type Derivative : HasRealField; /// 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) - } -} +// 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`. @@ -90,33 +95,34 @@ : Mapping + Differentiable + for<'a> Differentiable<&'a Domain, Derivative=Self::DerivativeDomain> { - type DerivativeDomain; - type Differential : Mapping; - type DifferentialRef<'b> : Mapping where Self : 'b; + type DerivativeDomain : HasRealField; + type Differential<'b> : Mapping + + HasRealField + + Clone where Self : 'b; /// 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<'_>; } -impl DifferentiableMapping for T -where T : Mapping +impl DifferentiableMapping for T +where T : Mapping + Clone + Differentiable - + for<'a> Differentiable<&'a Domain,Derivative=Derivative> { + + for<'a> Differentiable<&'a Domain, Derivative=Derivative>, + Derivative : HasRealField { type DerivativeDomain = Derivative; - type Differential = Differential; - type DifferentialRef<'b> = Differential where Self : 'b; + type Differential<'b> = Differential<'b, Domain, Self> where Self : 'b + Clone; /// Form the differential mapping of `self`. - fn diff(self) -> Self::Differential { - Differential{ g : self, _space : PhantomData } + fn diff(self) -> Self::Differential<'static> { + Differential{ g : Cow::Owned(self), _space : PhantomData } } /// Form the differential mapping of `self`. - fn diff_ref(&self) -> Self::DifferentialRef<'_> { - Differential{ g : self, _space : PhantomData } + fn diff_ref(&self) -> Self::Differential<'_> { + Differential{ g : Cow::Borrowed(self), _space : PhantomData } } } @@ -127,6 +133,10 @@ _domain : PhantomData, } +impl + HasScalarField> HasScalarField for Sum { + type Field = M::Field; +} + impl> Sum { /// Construct from an iterator. pub fn new>(iter : I) -> Self { @@ -174,18 +184,25 @@ } /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. -pub struct Differential> { - g : G, +#[derive(Clone, Debug)] +pub struct Differential<'a, X, G : 'a + DifferentiableMapping + Clone> { + g : Cow<'a, G>, _space : PhantomData } -impl> Differential { - pub fn base_fn(&self) -> &G { - &self.g +impl<'a, X, G : DifferentiableMapping + Clone> Differential<'a, X, G> { + pub fn base_fn(&'a self) -> &'a G { + &*self.g } } -impl> Apply for Differential { + +impl<'a, X, G> HasScalarField for Differential<'a, X, G> +where G : 'a + DifferentiableMapping + HasScalarField + Clone { + type Field = G::Field; +} + +impl<'b, X, G : DifferentiableMapping + Clone> Apply for Differential<'b, X, G> { type Output = G::DerivativeDomain; #[inline] @@ -194,7 +211,8 @@ } } -impl<'a, X, G : DifferentiableMapping> Apply<&'a X> for Differential { +impl<'a, 'b, X, G : 'b + DifferentiableMapping + Clone> Apply<&'a X> +for Differential<'b, X, G> { type Output = G::DerivativeDomain; #[inline] @@ -232,14 +250,23 @@ /// 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 : Mapping> + Clone, + const N : usize +> { + g : Cow<'a, G>, slice : usize, _phantoms : PhantomData<(X, F)> } -impl>, const N : usize> Apply -for SlicedCodomain { +impl<'a, X, F, G, const N : usize> HasScalarField for SlicedCodomain<'a, X, F, G, N> +where G : HasScalarField + Mapping> + Clone { + type Field = G::Field; +} + +impl<'a, X, F : Copy, G : Mapping> + Clone, const N : usize> Apply +for SlicedCodomain<'a, X, F, G, N> { type Output = F; #[inline] @@ -250,12 +277,13 @@ } } -impl<'a, X, F : Copy, G : Mapping>, const N : usize> Apply<&'a X> -for SlicedCodomain { +impl<'a, 'b, X, F : Copy, G : Mapping> + Clone, const N : usize> +Apply<&'b X> +for SlicedCodomain<'a, X, F, G, N> { type Output = F; #[inline] - fn apply(&self, x : &'a X) -> Self::Output { + fn apply(&self, x : &'b 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) } @@ -264,21 +292,21 @@ /// 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 {}