70 pub trait Differentiable<X> : Sized { |
70 pub trait Differentiable<X> : Sized { |
71 type Derivative; |
71 type Derivative; |
72 |
72 |
73 /// Compute the differential of `self` at `x`. |
73 /// Compute the differential of `self` at `x`. |
74 fn differential(&self, x : X) -> Self::Derivative; |
74 fn differential(&self, x : X) -> Self::Derivative; |
|
75 } |
|
76 |
|
77 impl<'g, X, G : Differentiable<X>> Differentiable<X> for &'g G { |
|
78 type Derivative = G::Derivative; |
|
79 #[inline] |
|
80 fn differential(&self, x : X) -> Self::Derivative { |
|
81 (*self).differential(x) |
|
82 } |
75 } |
83 } |
76 |
84 |
77 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials |
85 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials |
78 /// `Differential`. |
86 /// `Differential`. |
79 /// |
87 /// |
97 where T : Mapping<Domain> |
105 where T : Mapping<Domain> |
98 + Differentiable<Domain, Derivative=Derivative> |
106 + Differentiable<Domain, Derivative=Derivative> |
99 + for<'a> Differentiable<&'a Domain,Derivative=Derivative> { |
107 + for<'a> Differentiable<&'a Domain,Derivative=Derivative> { |
100 type DerivativeDomain = Derivative; |
108 type DerivativeDomain = Derivative; |
101 type Differential = Differential<Domain, Self>; |
109 type Differential = Differential<Domain, Self>; |
102 type DifferentialRef<'b> = Differential<Domain, Ref<'b, Self>> where Self : 'b; |
110 type DifferentialRef<'b> = Differential<Domain, &'b Self> where Self : 'b; |
103 |
111 |
104 /// Form the differential mapping of `self`. |
112 /// Form the differential mapping of `self`. |
105 fn diff(self) -> Self::Differential { |
113 fn diff(self) -> Self::Differential { |
106 Differential{ g : self, _space : PhantomData } |
114 Differential{ g : self, _space : PhantomData } |
107 } |
115 } |
108 |
116 |
109 /// Form the differential mapping of `self`. |
117 /// Form the differential mapping of `self`. |
110 fn diff_ref(&self) -> Self::DifferentialRef<'_> { |
118 fn diff_ref(&self) -> Self::DifferentialRef<'_> { |
111 Differential{ g : Ref(self), _space : PhantomData } |
119 Differential{ g : self, _space : PhantomData } |
112 } |
120 } |
113 } |
121 } |
114 |
122 |
115 /// A sum of [`Mapping`]s. |
123 /// A sum of [`Mapping`]s. |
116 #[derive(Serialize, Debug, Clone)] |
124 #[derive(Serialize, Debug, Clone)] |
167 |
175 |
168 /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. |
176 /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. |
169 pub struct Differential<X, G : DifferentiableMapping<X>> { |
177 pub struct Differential<X, G : DifferentiableMapping<X>> { |
170 g : G, |
178 g : G, |
171 _space : PhantomData<X> |
179 _space : PhantomData<X> |
|
180 } |
|
181 |
|
182 impl<X, G : DifferentiableMapping<X>> Differential<X, G> { |
|
183 pub fn base_fn(&self) -> &G { |
|
184 &self.g |
|
185 } |
172 } |
186 } |
173 |
187 |
174 impl<X, G : DifferentiableMapping<X>> Apply<X> for Differential<X, G> { |
188 impl<X, G : DifferentiableMapping<X>> Apply<X> for Differential<X, G> { |
175 type Output = G::DerivativeDomain; |
189 type Output = G::DerivativeDomain; |
176 |
190 |
256 assert!(slice < N); |
270 assert!(slice < N); |
257 SlicedCodomain{ g : self, slice, _phantoms : PhantomData } |
271 SlicedCodomain{ g : self, slice, _phantoms : PhantomData } |
258 } |
272 } |
259 |
273 |
260 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
274 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
261 fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<X, F, Ref<'_, Self>, N> { |
275 fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<X, F, &'_ Self, N> { |
262 assert!(slice < N); |
276 assert!(slice < N); |
263 SlicedCodomain{ g : Ref(self), slice, _phantoms : PhantomData } |
277 SlicedCodomain{ g : self, slice, _phantoms : PhantomData } |
264 } |
278 } |
265 } |
279 } |
266 |
280 |
267 impl<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>>, const N : usize> |
281 impl<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>>, const N : usize> |
268 SliceCodomain<X, F, N> |
282 SliceCodomain<X, F, N> |
269 for G {} |
283 for G {} |
270 |
284 |
271 |
|
272 /// Helper struct for doing operations on references of mappings while avoiding |
|
273 /// conflicting implementations that `&'g G` would cause. |
|
274 pub struct Ref<'g, G>(&'g G); |
|
275 |
|
276 impl<'g, X, G : Apply<X>> Apply<X> for Ref<'g, G> { |
|
277 type Output = G::Output; |
|
278 #[inline] |
|
279 fn apply(&self, x : X) -> Self::Output { |
|
280 self.0.apply(x) |
|
281 } |
|
282 } |
|
283 |
|
284 impl<'g, X, G : Differentiable<X>> Differentiable<X> for Ref<'g, G> { |
|
285 type Derivative = G::Derivative; |
|
286 #[inline] |
|
287 fn differential(&self, x : X) -> Self::Derivative { |
|
288 self.0.differential(x) |
|
289 } |
|
290 } |
|