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 |