src/mapping.rs

branch
dev
changeset 81
d2acaaddd9af
parent 49
edb95d2b83cc
equal deleted inserted replaced
49:edb95d2b83cc 81:d2acaaddd9af
1 /*! 1 /*!
2 Traits for mathematical functions. 2 Traits for mathematical functions.
3 */ 3 */
4 4
5 use std::marker::PhantomData; 5 use std::marker::PhantomData;
6 use crate::types::Float; 6 use crate::types::{Float, HasRealField, HasScalarField};
7 use serde::Serialize; 7 use serde::Serialize;
8 use crate::loc::Loc; 8 use crate::loc::Loc;
9 use std::borrow::Cow;
9 10
10 /// Trait for application of `Self` as a mathematical function or operator on `X`. 11 /// Trait for application of `Self` as a mathematical function or operator on `X`.
11 pub trait Apply<X> { 12 pub trait Apply<X> {
12 type Output; 13 type Output;
13 14
42 type Codomain = Codomain; 43 type Codomain = Codomain;
43 } 44 }
44 45
45 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`. 46 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`.
46 pub trait RealMapping<F : Float, const N : usize> 47 pub trait RealMapping<F : Float, const N : usize>
47 : Mapping<Loc<F, N>, Codomain = F> {} 48 : Mapping<Loc<F, N>, Codomain = F> + HasRealField<RealField = F> {}
48 49
49 impl<F : Float, T, const N : usize> RealMapping<F, N> for T 50 impl<F : Float, T, const N : usize> RealMapping<F, N> for T
50 where T : Mapping<Loc<F, N>, Codomain = F> {} 51 where T : Mapping<Loc<F, N>, Codomain = F> + HasRealField<RealField = F> {}
51 52
52 /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from 53 /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from
53 /// [`Loc<F, N>`] to `F`. 54 /// [`Loc<F, N>`] to `F`.
54 pub trait DifferentiableRealMapping<F : Float, const N : usize> 55 pub trait DifferentiableRealMapping<F : Float, const N : usize>
55 : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>> {} 56 : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>>
57 + RealMapping<F, N>
58 + HasRealField<RealField=F> {}
56 59
57 impl<F : Float, T, const N : usize> DifferentiableRealMapping<F, N> for T 60 impl<F : Float, T, const N : usize> DifferentiableRealMapping<F, N> for T
58 where T : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>> {} 61 where T : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>>
62 + RealMapping<F, N>
63 + HasRealField<RealField=F> {}
59 64
60 65
61 /// A helper trait alias for referring to [`Mapping`]s from [`Loc<F, N>`] to [`Loc<F, M>`]. 66 /// A helper trait alias for referring to [`Mapping`]s from [`Loc<F, N>`] to [`Loc<F, M>`].
62 pub trait RealVectorField<F : Float, const N : usize, const M : usize> 67 pub trait RealVectorField<F : Float, const N : usize, const M : usize>
63 : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} 68 : Mapping<Loc<F, N>, Codomain = Loc<F, M>> + HasRealField<RealField=F> {}
64 69
65 impl<F : Float, T, const N : usize, const M : usize> RealVectorField<F, N, M> for T 70 impl<F : Float, T, const N : usize, const M : usize> RealVectorField<F, N, M> for T
66 where T : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} 71 where T : Mapping<Loc<F, N>, Codomain = Loc<F, M>> + HasRealField<RealField=F> {}
67 72
68 73
69 /// Trait for calculation the differential of `Self` as a mathematical function on `X`. 74 /// Trait for calculation the differential of `Self` as a mathematical function on `X`.
70 pub trait Differentiable<X> : Sized { 75 pub trait Differentiable<X> : Sized + HasRealField {
71 type Derivative; 76 type Derivative : HasRealField<RealField = Self::RealField>;
72 77
73 /// Compute the differential of `self` at `x`. 78 /// Compute the differential of `self` at `x`.
74 fn differential(&self, x : X) -> Self::Derivative; 79 fn differential(&self, x : X) -> Self::Derivative;
75 } 80 }
76 81
77 impl<'g, X, G : Differentiable<X>> Differentiable<X> for &'g G { 82 // impl<'g, X, G : Differentiable<X>> Differentiable<X> for &'g G {
78 type Derivative = G::Derivative; 83 // type Derivative = G::Derivative;
79 #[inline] 84 // #[inline]
80 fn differential(&self, x : X) -> Self::Derivative { 85 // fn differential(&self, x : X) -> Self::Derivative {
81 (*self).differential(x) 86 // (*self).differential(x)
82 } 87 // }
83 } 88 // }
84 89
85 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials 90 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials
86 /// `Differential`. 91 /// `Differential`.
87 /// 92 ///
88 /// This is automatically implemented when the relevant [`Differentiate`] are implemented. 93 /// This is automatically implemented when the relevant [`Differentiate`] are implemented.
89 pub trait DifferentiableMapping<Domain> 94 pub trait DifferentiableMapping<Domain>
90 : Mapping<Domain> 95 : Mapping<Domain>
91 + Differentiable<Domain, Derivative=Self::DerivativeDomain> 96 + Differentiable<Domain, Derivative=Self::DerivativeDomain>
92 + for<'a> Differentiable<&'a Domain, Derivative=Self::DerivativeDomain> { 97 + for<'a> Differentiable<&'a Domain, Derivative=Self::DerivativeDomain> {
93 type DerivativeDomain; 98 type DerivativeDomain : HasRealField<RealField=Self::RealField>;
94 type Differential : Mapping<Domain, Codomain=Self::DerivativeDomain>; 99 type Differential<'b> : Mapping<Domain, Codomain=Self::DerivativeDomain>
95 type DifferentialRef<'b> : Mapping<Domain, Codomain=Self::DerivativeDomain> where Self : 'b; 100 + HasRealField<RealField=Self::RealField>
101 + Clone where Self : 'b;
96 102
97 /// Form the differential mapping of `self`. 103 /// Form the differential mapping of `self`.
98 fn diff(self) -> Self::Differential; 104 fn diff(self) -> Self::Differential<'static>;
99 /// Form the differential mapping of `self`. 105 /// Form the differential mapping of `self`.
100 fn diff_ref(&self) -> Self::DifferentialRef<'_>; 106 fn diff_ref(&self) -> Self::Differential<'_>;
101 } 107 }
102 108
103 109
104 impl<Domain, Derivative, T> DifferentiableMapping<Domain> for T 110 impl<Domain : Clone, Derivative, T> DifferentiableMapping<Domain> for T
105 where T : Mapping<Domain> 111 where T : Mapping<Domain> + Clone
106 + Differentiable<Domain, Derivative=Derivative> 112 + Differentiable<Domain, Derivative=Derivative>
107 + for<'a> Differentiable<&'a Domain,Derivative=Derivative> { 113 + for<'a> Differentiable<&'a Domain, Derivative=Derivative>,
114 Derivative : HasRealField<RealField = T::RealField> {
108 type DerivativeDomain = Derivative; 115 type DerivativeDomain = Derivative;
109 type Differential = Differential<Domain, Self>; 116 type Differential<'b> = Differential<'b, Domain, Self> where Self : 'b + Clone;
110 type DifferentialRef<'b> = Differential<Domain, &'b Self> where Self : 'b;
111 117
112 /// Form the differential mapping of `self`. 118 /// Form the differential mapping of `self`.
113 fn diff(self) -> Self::Differential { 119 fn diff(self) -> Self::Differential<'static> {
114 Differential{ g : self, _space : PhantomData } 120 Differential{ g : Cow::Owned(self), _space : PhantomData }
115 } 121 }
116 122
117 /// Form the differential mapping of `self`. 123 /// Form the differential mapping of `self`.
118 fn diff_ref(&self) -> Self::DifferentialRef<'_> { 124 fn diff_ref(&self) -> Self::Differential<'_> {
119 Differential{ g : self, _space : PhantomData } 125 Differential{ g : Cow::Borrowed(self), _space : PhantomData }
120 } 126 }
121 } 127 }
122 128
123 /// A sum of [`Mapping`]s. 129 /// A sum of [`Mapping`]s.
124 #[derive(Serialize, Debug, Clone)] 130 #[derive(Serialize, Debug, Clone)]
125 pub struct Sum<Domain, M : Mapping<Domain>> { 131 pub struct Sum<Domain, M : Mapping<Domain>> {
126 components : Vec<M>, 132 components : Vec<M>,
127 _domain : PhantomData<Domain>, 133 _domain : PhantomData<Domain>,
128 } 134 }
129 135
136 impl<Domain, M : Mapping<Domain> + HasScalarField> HasScalarField for Sum<Domain, M> {
137 type Field = M::Field;
138 }
139
130 impl<Domain, M : Mapping<Domain>> Sum<Domain, M> { 140 impl<Domain, M : Mapping<Domain>> Sum<Domain, M> {
131 /// Construct from an iterator. 141 /// Construct from an iterator.
132 pub fn new<I : Iterator<Item = M>>(iter : I) -> Self { 142 pub fn new<I : Iterator<Item = M>>(iter : I) -> Self {
133 Sum { components : iter.collect(), _domain : PhantomData } 143 Sum { components : iter.collect(), _domain : PhantomData }
134 } 144 }
172 self.components.iter().map(|c| c.differential(x)).sum() 182 self.components.iter().map(|c| c.differential(x)).sum()
173 } 183 }
174 } 184 }
175 185
176 /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. 186 /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping.
177 pub struct Differential<X, G : DifferentiableMapping<X>> { 187 #[derive(Clone, Debug)]
178 g : G, 188 pub struct Differential<'a, X, G : 'a + DifferentiableMapping<X> + Clone> {
189 g : Cow<'a, G>,
179 _space : PhantomData<X> 190 _space : PhantomData<X>
180 } 191 }
181 192
182 impl<X, G : DifferentiableMapping<X>> Differential<X, G> { 193 impl<'a, X, G : DifferentiableMapping<X> + Clone> Differential<'a, X, G> {
183 pub fn base_fn(&self) -> &G { 194 pub fn base_fn(&'a self) -> &'a G {
184 &self.g 195 &*self.g
185 } 196 }
186 } 197 }
187 198
188 impl<X, G : DifferentiableMapping<X>> Apply<X> for Differential<X, G> { 199
200 impl<'a, X, G> HasScalarField for Differential<'a, X, G>
201 where G : 'a + DifferentiableMapping<X> + HasScalarField + Clone {
202 type Field = G::Field;
203 }
204
205 impl<'b, X, G : DifferentiableMapping<X> + Clone> Apply<X> for Differential<'b, X, G> {
189 type Output = G::DerivativeDomain; 206 type Output = G::DerivativeDomain;
190 207
191 #[inline] 208 #[inline]
192 fn apply(&self, x : X) -> Self::Output { 209 fn apply(&self, x : X) -> Self::Output {
193 self.g.differential(x) 210 self.g.differential(x)
194 } 211 }
195 } 212 }
196 213
197 impl<'a, X, G : DifferentiableMapping<X>> Apply<&'a X> for Differential<X, G> { 214 impl<'a, 'b, X, G : 'b + DifferentiableMapping<X> + Clone> Apply<&'a X>
215 for Differential<'b, X, G> {
198 type Output = G::DerivativeDomain; 216 type Output = G::DerivativeDomain;
199 217
200 #[inline] 218 #[inline]
201 fn apply(&self, x : &'a X) -> Self::Output { 219 fn apply(&self, x : &'a X) -> Self::Output {
202 self.g.differential(x) 220 self.g.differential(x)
230 248
231 impl<X, F, G : Sized + Mapping<X, Codomain=Loc<F, 1>>> FlattenCodomain<X, F> for G {} 249 impl<X, F, G : Sized + Mapping<X, Codomain=Loc<F, 1>>> FlattenCodomain<X, F> for G {}
232 250
233 251
234 /// Container for dimensional slicing [`Loc`]`<F, N>` codomain of a [`Mapping`] to `F`. 252 /// Container for dimensional slicing [`Loc`]`<F, N>` codomain of a [`Mapping`] to `F`.
235 pub struct SlicedCodomain<X, F, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> { 253 pub struct SlicedCodomain<
236 g : G, 254 'a, X, F,
255 G : Mapping<X, Codomain=Loc<F, N>> + Clone,
256 const N : usize
257 > {
258 g : Cow<'a, G>,
237 slice : usize, 259 slice : usize,
238 _phantoms : PhantomData<(X, F)> 260 _phantoms : PhantomData<(X, F)>
239 } 261 }
240 262
241 impl<X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> Apply<X> 263 impl<'a, X, F, G, const N : usize> HasScalarField for SlicedCodomain<'a, X, F, G, N>
242 for SlicedCodomain<X, F, G, N> { 264 where G : HasScalarField + Mapping<X, Codomain=Loc<F, N>> + Clone {
265 type Field = G::Field;
266 }
267
268 impl<'a, X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize> Apply<X>
269 for SlicedCodomain<'a, X, F, G, N> {
243 type Output = F; 270 type Output = F;
244 271
245 #[inline] 272 #[inline]
246 fn apply(&self, x : X) -> Self::Output { 273 fn apply(&self, x : X) -> Self::Output {
247 let tmp : [F; N] = self.g.apply(x).into(); 274 let tmp : [F; N] = self.g.apply(x).into();
248 // Safety: `slice_codomain` below checks the range. 275 // Safety: `slice_codomain` below checks the range.
249 unsafe { *tmp.get_unchecked(self.slice) } 276 unsafe { *tmp.get_unchecked(self.slice) }
250 } 277 }
251 } 278 }
252 279
253 impl<'a, X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> Apply<&'a X> 280 impl<'a, 'b, X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize>
254 for SlicedCodomain<X, F, G, N> { 281 Apply<&'b X>
282 for SlicedCodomain<'a, X, F, G, N> {
255 type Output = F; 283 type Output = F;
256 284
257 #[inline] 285 #[inline]
258 fn apply(&self, x : &'a X) -> Self::Output { 286 fn apply(&self, x : &'b X) -> Self::Output {
259 let tmp : [F; N] = self.g.apply(x).into(); 287 let tmp : [F; N] = self.g.apply(x).into();
260 // Safety: `slice_codomain` below checks the range. 288 // Safety: `slice_codomain` below checks the range.
261 unsafe { *tmp.get_unchecked(self.slice) } 289 unsafe { *tmp.get_unchecked(self.slice) }
262 } 290 }
263 } 291 }
264 292
265 /// An auto-trait for constructing a [`FlattenCodomain`] structure for 293 /// An auto-trait for constructing a [`FlattenCodomain`] structure for
266 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. 294 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`.
267 pub trait SliceCodomain<X, F : Copy, const N : usize> : Mapping<X, Codomain=Loc<F, N>> + Sized { 295 pub trait SliceCodomain<X, F : Copy, const N : usize> : Mapping<X, Codomain=Loc<F, N>> + Clone + Sized {
268 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. 296 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
269 fn slice_codomain(self, slice : usize) -> SlicedCodomain<X, F, Self, N> { 297 fn slice_codomain(self, slice : usize) -> SlicedCodomain<'static, X, F, Self, N> {
270 assert!(slice < N); 298 assert!(slice < N);
271 SlicedCodomain{ g : self, slice, _phantoms : PhantomData } 299 SlicedCodomain{ g : Cow::Owned(self), slice, _phantoms : PhantomData }
272 } 300 }
273 301
274 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. 302 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
275 fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<X, F, &'_ Self, N> { 303 fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<'_, X, F, Self, N> {
276 assert!(slice < N); 304 assert!(slice < N);
277 SlicedCodomain{ g : self, slice, _phantoms : PhantomData } 305 SlicedCodomain{ g : Cow::Borrowed(self), slice, _phantoms : PhantomData }
278 } 306 }
279 } 307 }
280 308
281 impl<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>>, const N : usize> 309 impl<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize>
282 SliceCodomain<X, F, N> 310 SliceCodomain<X, F, N>
283 for G {} 311 for G {}
284 312

mercurial