--- 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<X> { @@ -44,43 +45,47 @@ /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`. pub trait RealMapping<F : Float, const N : usize> -: Mapping<Loc<F, N>, Codomain = F> {} +: Mapping<Loc<F, N>, Codomain = F> + HasRealField<RealField = F> {} impl<F : Float, T, const N : usize> RealMapping<F, N> for T -where T : Mapping<Loc<F, N>, Codomain = F> {} +where T : Mapping<Loc<F, N>, Codomain = F> + HasRealField<RealField = F> {} /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from /// [`Loc<F, N>`] to `F`. pub trait DifferentiableRealMapping<F : Float, const N : usize> -: DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>> {} +: DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>> + + RealMapping<F, N> + + HasRealField<RealField=F> {} impl<F : Float, T, const N : usize> DifferentiableRealMapping<F, N> for T -where T : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>> {} +where T : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>> + + RealMapping<F, N> + + HasRealField<RealField=F> {} /// A helper trait alias for referring to [`Mapping`]s from [`Loc<F, N>`] to [`Loc<F, M>`]. pub trait RealVectorField<F : Float, const N : usize, const M : usize> -: Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} +: Mapping<Loc<F, N>, Codomain = Loc<F, M>> + HasRealField<RealField=F> {} impl<F : Float, T, const N : usize, const M : usize> RealVectorField<F, N, M> for T -where T : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} +where T : Mapping<Loc<F, N>, Codomain = Loc<F, M>> + HasRealField<RealField=F> {} /// Trait for calculation the differential of `Self` as a mathematical function on `X`. -pub trait Differentiable<X> : Sized { - type Derivative; +pub trait Differentiable<X> : Sized + HasRealField { + type Derivative : HasRealField<RealField = Self::RealField>; /// Compute the differential of `self` at `x`. fn differential(&self, x : X) -> Self::Derivative; } -impl<'g, X, G : Differentiable<X>> Differentiable<X> for &'g G { - type Derivative = G::Derivative; - #[inline] - fn differential(&self, x : X) -> Self::Derivative { - (*self).differential(x) - } -} +// impl<'g, X, G : Differentiable<X>> Differentiable<X> 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<Domain> + Differentiable<Domain, Derivative=Self::DerivativeDomain> + for<'a> Differentiable<&'a Domain, Derivative=Self::DerivativeDomain> { - type DerivativeDomain; - type Differential : Mapping<Domain, Codomain=Self::DerivativeDomain>; - type DifferentialRef<'b> : Mapping<Domain, Codomain=Self::DerivativeDomain> where Self : 'b; + type DerivativeDomain : HasRealField<RealField=Self::RealField>; + type Differential<'b> : Mapping<Domain, Codomain=Self::DerivativeDomain> + + HasRealField<RealField=Self::RealField> + + 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<Domain, Derivative, T> DifferentiableMapping<Domain> for T -where T : Mapping<Domain> +impl<Domain : Clone, Derivative, T> DifferentiableMapping<Domain> for T +where T : Mapping<Domain> + Clone + Differentiable<Domain, Derivative=Derivative> - + for<'a> Differentiable<&'a Domain,Derivative=Derivative> { + + for<'a> Differentiable<&'a Domain, Derivative=Derivative>, + Derivative : HasRealField<RealField = T::RealField> { type DerivativeDomain = Derivative; - type Differential = Differential<Domain, Self>; - type DifferentialRef<'b> = Differential<Domain, &'b Self> 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<Domain>, } +impl<Domain, M : Mapping<Domain> + HasScalarField> HasScalarField for Sum<Domain, M> { + type Field = M::Field; +} + impl<Domain, M : Mapping<Domain>> Sum<Domain, M> { /// Construct from an iterator. pub fn new<I : Iterator<Item = M>>(iter : I) -> Self { @@ -174,18 +184,25 @@ } /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. -pub struct Differential<X, G : DifferentiableMapping<X>> { - g : G, +#[derive(Clone, Debug)] +pub struct Differential<'a, X, G : 'a + DifferentiableMapping<X> + Clone> { + g : Cow<'a, G>, _space : PhantomData<X> } -impl<X, G : DifferentiableMapping<X>> Differential<X, G> { - pub fn base_fn(&self) -> &G { - &self.g +impl<'a, X, G : DifferentiableMapping<X> + Clone> Differential<'a, X, G> { + pub fn base_fn(&'a self) -> &'a G { + &*self.g } } -impl<X, G : DifferentiableMapping<X>> Apply<X> for Differential<X, G> { + +impl<'a, X, G> HasScalarField for Differential<'a, X, G> +where G : 'a + DifferentiableMapping<X> + HasScalarField + Clone { + type Field = G::Field; +} + +impl<'b, X, G : DifferentiableMapping<X> + Clone> Apply<X> for Differential<'b, X, G> { type Output = G::DerivativeDomain; #[inline] @@ -194,7 +211,8 @@ } } -impl<'a, X, G : DifferentiableMapping<X>> Apply<&'a X> for Differential<X, G> { +impl<'a, 'b, X, G : 'b + DifferentiableMapping<X> + Clone> Apply<&'a X> +for Differential<'b, X, G> { type Output = G::DerivativeDomain; #[inline] @@ -232,14 +250,23 @@ /// Container for dimensional slicing [`Loc`]`<F, N>` codomain of a [`Mapping`] to `F`. -pub struct SlicedCodomain<X, F, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> { - g : G, +pub struct SlicedCodomain< + 'a, X, F, + G : Mapping<X, Codomain=Loc<F, N>> + Clone, + const N : usize +> { + g : Cow<'a, G>, slice : usize, _phantoms : PhantomData<(X, F)> } -impl<X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> Apply<X> -for SlicedCodomain<X, F, G, N> { +impl<'a, X, F, G, const N : usize> HasScalarField for SlicedCodomain<'a, X, F, G, N> +where G : HasScalarField + Mapping<X, Codomain=Loc<F, N>> + Clone { + type Field = G::Field; +} + +impl<'a, X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize> Apply<X> +for SlicedCodomain<'a, X, F, G, N> { type Output = F; #[inline] @@ -250,12 +277,13 @@ } } -impl<'a, X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> Apply<&'a X> -for SlicedCodomain<X, F, G, N> { +impl<'a, 'b, X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>> + 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`]`<F, 1>` to `F`. -pub trait SliceCodomain<X, F : Copy, const N : usize> : Mapping<X, Codomain=Loc<F, N>> + Sized { +pub trait SliceCodomain<X, F : Copy, const N : usize> : Mapping<X, Codomain=Loc<F, N>> + Clone + Sized { /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. - fn slice_codomain(self, slice : usize) -> SlicedCodomain<X, F, Self, N> { + 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`]`<F, 1>` to `F`. - fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<X, F, &'_ Self, N> { + 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<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>>, const N : usize> +impl<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize> SliceCodomain<X, F, N> for G {}