src/mapping.rs

branch
dev
changeset 81
d2acaaddd9af
parent 49
edb95d2b83cc
--- 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 {}
 

mercurial