| 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 |