| 1 /*! |
1 /*! |
| 2 Traits for mathematical functions. |
2 Traits for mathematical functions. |
| 3 */ |
3 */ |
| 4 |
4 |
| 5 use crate::error::DynResult; |
5 use crate::error::DynResult; |
| |
6 use crate::instance::MyCow; |
| 6 pub use crate::instance::{BasicDecomposition, Decomposition, Instance, Space}; |
7 pub use crate::instance::{BasicDecomposition, Decomposition, Instance, Space}; |
| 7 use crate::loc::Loc; |
8 use crate::loc::Loc; |
| 8 use crate::norms::{Norm, NormExponent}; |
9 use crate::norms::{Norm, NormExponent}; |
| 9 use crate::operator_arithmetic::{Constant, Weighted}; |
10 use crate::operator_arithmetic::{Constant, Weighted}; |
| 10 use crate::types::{ClosedMul, Float, Num}; |
11 use crate::types::{ClosedMul, Float, Num}; |
| 11 use std::borrow::Cow; |
|
| 12 use std::marker::PhantomData; |
12 use std::marker::PhantomData; |
| 13 use std::ops::Mul; |
13 use std::ops::Mul; |
| 14 |
14 |
| 15 /// A mapping from `Domain` to `Self::Codomain`. |
15 /// A mapping from `Domain` to `Self::Codomain`. |
| 16 pub trait Mapping<Domain: Space> { |
16 pub trait Mapping<Domain: Space> { |
| 122 } |
122 } |
| 123 |
123 |
| 124 impl<T, Domain> DifferentiableMapping<Domain> for T |
124 impl<T, Domain> DifferentiableMapping<Domain> for T |
| 125 where |
125 where |
| 126 Domain: Space, |
126 Domain: Space, |
| 127 T: Clone + Mapping<Domain> + DifferentiableImpl<Domain>, |
127 T: Mapping<Domain> + DifferentiableImpl<Domain>, |
| 128 { |
128 { |
| 129 type DerivativeDomain = T::Derivative; |
129 type DerivativeDomain = T::Derivative; |
| 130 type Differential<'b> |
130 type Differential<'b> |
| 131 = Differential<'b, Domain, Self> |
131 = Differential<'b, Domain, Self> |
| 132 where |
132 where |
| 137 self.differential_impl(x) |
137 self.differential_impl(x) |
| 138 } |
138 } |
| 139 |
139 |
| 140 fn diff(self) -> Differential<'static, Domain, Self> { |
140 fn diff(self) -> Differential<'static, Domain, Self> { |
| 141 Differential { |
141 Differential { |
| 142 g: Cow::Owned(self), |
142 g: MyCow::Owned(self), |
| 143 _space: PhantomData, |
143 _space: PhantomData, |
| 144 } |
144 } |
| 145 } |
145 } |
| 146 |
146 |
| 147 fn diff_ref(&self) -> Differential<'_, Domain, Self> { |
147 fn diff_ref(&self) -> Differential<'_, Domain, Self> { |
| 148 Differential { |
148 Differential { |
| 149 g: Cow::Borrowed(self), |
149 g: MyCow::Borrowed(self), |
| 150 _space: PhantomData, |
150 _space: PhantomData, |
| 151 } |
151 } |
| 152 } |
152 } |
| 153 } |
153 } |
| 154 |
154 |
| 155 /// Container for the differential [`Mapping`] of a [`DifferentiableMapping`]. |
155 /// Container for the differential [`Mapping`] of a [`DifferentiableMapping`]. |
| 156 pub struct Differential<'a, X, G: Clone> { |
156 pub struct Differential<'a, X, G> { |
| 157 g: Cow<'a, G>, |
157 g: MyCow<'a, G>, |
| 158 _space: PhantomData<X>, |
158 _space: PhantomData<X>, |
| 159 } |
159 } |
| 160 |
160 |
| 161 impl<'a, X, G: Clone> Differential<'a, X, G> { |
161 impl<'a, X, G> Differential<'a, X, G> { |
| 162 pub fn base_fn(&self) -> &G { |
162 pub fn base_fn(&self) -> &G { |
| 163 &self.g |
163 &self.g |
| 164 } |
164 } |
| 165 } |
165 } |
| 166 |
166 |
| 167 impl<'a, X, G> Mapping<X> for Differential<'a, X, G> |
167 impl<'a, X, G> Mapping<X> for Differential<'a, X, G> |
| 168 where |
168 where |
| 169 X: Space, |
169 X: Space, |
| 170 G: Clone + DifferentiableMapping<X>, |
170 G: DifferentiableMapping<X>, |
| 171 { |
171 { |
| 172 type Codomain = G::DerivativeDomain; |
172 type Codomain = G::DerivativeDomain; |
| 173 |
173 |
| 174 #[inline] |
174 #[inline] |
| 175 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain { |
175 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain { |
| 209 } |
209 } |
| 210 |
210 |
| 211 impl<X: Space, F, G: Sized + Mapping<X, Codomain = Loc<1, F>>> FlattenCodomain<X, F> for G {} |
211 impl<X: Space, F, G: Sized + Mapping<X, Codomain = Loc<1, F>>> FlattenCodomain<X, F> for G {} |
| 212 |
212 |
| 213 /// Container for dimensional slicing [`Loc`]`<N, F>` codomain of a [`Mapping`] to `F`. |
213 /// Container for dimensional slicing [`Loc`]`<N, F>` codomain of a [`Mapping`] to `F`. |
| 214 pub struct SlicedCodomain<'a, X, F, G: Clone, const N: usize> { |
214 pub struct SlicedCodomain<'a, X, F, G, const N: usize> { |
| 215 g: Cow<'a, G>, |
215 g: MyCow<'a, G>, |
| 216 slice: usize, |
216 slice: usize, |
| 217 _phantoms: PhantomData<(X, F)>, |
217 _phantoms: PhantomData<(X, F)>, |
| 218 } |
218 } |
| 219 |
219 |
| 220 impl<'a, X, F, G, const N: usize> Mapping<X> for SlicedCodomain<'a, X, F, G, N> |
220 impl<'a, X, F, G, const N: usize> Mapping<X> for SlicedCodomain<'a, X, F, G, N> |
| 221 where |
221 where |
| 222 X: Space, |
222 X: Space, |
| 223 F: Copy + Space, |
223 F: Copy + Space, |
| 224 G: Mapping<X, Codomain = Loc<N, F>> + Clone, |
224 G: Mapping<X, Codomain = Loc<N, F>>, |
| 225 { |
225 { |
| 226 type Codomain = F; |
226 type Codomain = F; |
| 227 |
227 |
| 228 #[inline] |
228 #[inline] |
| 229 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain { |
229 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain { |
| 234 } |
234 } |
| 235 |
235 |
| 236 /// An auto-trait for constructing a [`FlattenCodomain`] structure for |
236 /// An auto-trait for constructing a [`FlattenCodomain`] structure for |
| 237 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. |
237 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. |
| 238 pub trait SliceCodomain<X: Space, const N: usize, F: Copy = f64>: |
238 pub trait SliceCodomain<X: Space, const N: usize, F: Copy = f64>: |
| 239 Mapping<X, Codomain = Loc<N, F>> + Clone + Sized |
239 Mapping<X, Codomain = Loc<N, F>> + Sized |
| 240 { |
240 { |
| 241 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
241 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
| 242 fn slice_codomain(self, slice: usize) -> SlicedCodomain<'static, X, F, Self, N> { |
242 fn slice_codomain(self, slice: usize) -> SlicedCodomain<'static, X, F, Self, N> { |
| 243 assert!(slice < N); |
243 assert!(slice < N); |
| 244 SlicedCodomain { |
244 SlicedCodomain { |
| 245 g: Cow::Owned(self), |
245 g: MyCow::Owned(self), |
| 246 slice, |
246 slice, |
| 247 _phantoms: PhantomData, |
247 _phantoms: PhantomData, |
| 248 } |
248 } |
| 249 } |
249 } |
| 250 |
250 |
| 251 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
251 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
| 252 fn slice_codomain_ref(&self, slice: usize) -> SlicedCodomain<'_, X, F, Self, N> { |
252 fn slice_codomain_ref(&self, slice: usize) -> SlicedCodomain<'_, X, F, Self, N> { |
| 253 assert!(slice < N); |
253 assert!(slice < N); |
| 254 SlicedCodomain { |
254 SlicedCodomain { |
| 255 g: Cow::Borrowed(self), |
255 g: MyCow::Borrowed(self), |
| 256 slice, |
256 slice, |
| 257 _phantoms: PhantomData, |
257 _phantoms: PhantomData, |
| 258 } |
258 } |
| 259 } |
259 } |
| 260 } |
260 } |
| 261 |
261 |
| 262 impl<X: Space, F: Copy, G: Sized + Mapping<X, Codomain = Loc<N, F>> + Clone, const N: usize> |
262 impl<X: Space, F: Copy, G: Sized + Mapping<X, Codomain = Loc<N, F>>, const N: usize> |
| 263 SliceCodomain<X, N, F> for G |
263 SliceCodomain<X, N, F> for G |
| 264 { |
264 { |
| 265 } |
265 } |
| 266 |
266 |
| 267 /// The composition S ∘ T. `E` is for storing a `NormExponent` for the intermediate space. |
267 /// The composition S ∘ T. `E` is for storing a `NormExponent` for the intermediate space. |
| 335 } |
335 } |
| 336 |
336 |
| 337 impl<'b, M, X, A> Lipschitz<M> for Differential<'b, X, A> |
337 impl<'b, M, X, A> Lipschitz<M> for Differential<'b, X, A> |
| 338 where |
338 where |
| 339 X: Space, |
339 X: Space, |
| 340 A: LipschitzDifferentiableImpl<X, M> + Clone, |
340 A: LipschitzDifferentiableImpl<X, M>, |
| 341 { |
341 { |
| 342 type FloatType = A::FloatType; |
342 type FloatType = A::FloatType; |
| 343 |
343 |
| 344 fn lipschitz_factor(&self, seminorm: M) -> DynResult<Self::FloatType> { |
344 fn lipschitz_factor(&self, seminorm: M) -> DynResult<Self::FloatType> { |
| 345 (*self.g).diff_lipschitz_factor(seminorm) |
345 (*self.g).diff_lipschitz_factor(seminorm) |