Wed, 04 Oct 2023 08:59:29 -0500
Add Mapping codomain slicing and RealVectorField
src/loc.rs | file | annotate | diff | comparison | revisions | |
src/mapping.rs | file | annotate | diff | comparison | revisions |
--- a/src/loc.rs Wed Oct 04 08:02:14 2023 -0500 +++ b/src/loc.rs Wed Oct 04 08:59:29 2023 -0500 @@ -135,6 +135,14 @@ } } +impl<F> Loc<F, 1> { + #[inline] + pub fn flatten1d(self) -> F { + let Loc([v]) = self; + v + } +} + impl<F, const N : usize> From<Loc<F, N>> for [F; N] { #[inline] fn from(other : Loc<F, N>) -> [F; N] {
--- a/src/mapping.rs Wed Oct 04 08:02:14 2023 -0500 +++ b/src/mapping.rs Wed Oct 04 08:59:29 2023 -0500 @@ -49,6 +49,13 @@ impl<F : Float, T, const N : usize> RealMapping<F, N> for T where T : Mapping<Loc<F, N>, Codomain = 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>> {} + +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>> {} + /// Trait for calculation the differential of `Self` as a mathematical function on `X`. pub trait Differentiable<X> : Sized { @@ -144,8 +151,76 @@ } } + +/// Container for flattening [`Loc`]`<F, 1>` codomain of a [`Mapping`] to `F`. +pub struct FlattenedCodomain<X, F, G : Mapping<X, Codomain=Loc<F, 1>>> { + g : G, + _phantoms : PhantomData<(X, F)> +} + +impl<X, F, G : Mapping<X, Codomain=Loc<F, 1>>> Apply<X> for FlattenedCodomain<X, F, G> { + type Output = F; + #[inline] fn apply(&self, x : X) -> Self::Output { - self.g.differential(x) + self.g.apply(x).flatten1d() + } +} + +/// An auto-trait for constructing a [`FlattenCodomain`] structure for +/// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. +pub trait FlattenCodomain<X, F> : Mapping<X, Codomain=Loc<F, 1>> + Sized { + /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. + fn flatten_codomain(self) -> FlattenedCodomain<X, F, Self> { + FlattenedCodomain{ g : self, _phantoms : PhantomData } } } + +impl<X, F, G : Sized + Mapping<X, Codomain=Loc<F, 1>>> FlattenCodomain<X, F> for G {} + + +/// 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, + 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> { + type Output = 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<X, Codomain=Loc<F, N>>, const N : usize> Apply<&'a X> +for SlicedCodomain<X, F, G, N> { + type Output = F; + + #[inline] + fn apply(&self, x : &'a 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) } + } +} + +/// 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 { + /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. + fn slice_codomain(self, slice : usize) -> SlicedCodomain<X, F, Self, N> { + assert!(slice < N); + SlicedCodomain{ g : self, slice, _phantoms : PhantomData } + } +} + +impl<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>>, const N : usize> +SliceCodomain<X, F, N> +for G {} +