| 26 // } |
26 // } |
| 27 |
27 |
| 28 /// Vector spaces |
28 /// Vector spaces |
| 29 #[replace_float_literals(Self::Field::cast_from(literal))] |
29 #[replace_float_literals(Self::Field::cast_from(literal))] |
| 30 pub trait VectorSpace: |
30 pub trait VectorSpace: |
| 31 Space<OwnedSpace = Self::Owned> |
31 Space<Principal = Self::PrincipalV> |
| 32 + Mul<Self::Field, Output = Self::Owned> |
32 + Mul<Self::Field, Output = Self::PrincipalV> |
| 33 + Div<Self::Field, Output = Self::Owned> |
33 + Div<Self::Field, Output = Self::PrincipalV> |
| 34 + Add<Self, Output = Self::Owned> |
34 + Add<Self, Output = Self::PrincipalV> |
| 35 + Add<Self::Owned, Output = Self::Owned> |
35 + Add<Self::PrincipalV, Output = Self::PrincipalV> |
| 36 + Sub<Self, Output = Self::Owned> |
36 + Sub<Self, Output = Self::PrincipalV> |
| 37 + Sub<Self::Owned, Output = Self::Owned> |
37 + Sub<Self::PrincipalV, Output = Self::PrincipalV> |
| 38 + Neg |
38 + Neg |
| 39 + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::Owned> |
39 + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::PrincipalV> |
| 40 + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::Owned> |
40 + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::PrincipalV> |
| 41 { |
41 { |
| |
42 /// Underlying scalar field |
| 42 type Field: Num; |
43 type Field: Num; |
| 43 type Owned: ClosedSpace |
44 |
| |
45 /// Principal form of the space; always equal to [`Space::Principal`], but with |
| |
46 /// more traits guaranteed. |
| |
47 type PrincipalV: ClosedSpace |
| 44 + AXPY< |
48 + AXPY< |
| 45 Self, |
49 Self, |
| 46 Field = Self::Field, |
50 Field = Self::Field, |
| 47 Owned = Self::Owned, |
51 PrincipalV = Self::PrincipalV, |
| 48 OwnedVariant = Self::Owned, |
52 OwnedVariant = Self::PrincipalV, |
| 49 OwnedSpace = Self::Owned, |
53 Principal = Self::PrincipalV, |
| 50 >; |
54 >; |
| 51 |
55 |
| 52 /// Return a similar zero as `self`. |
56 /// Return a similar zero as `self`. |
| 53 fn similar_origin(&self) -> Self::Owned; |
57 fn similar_origin(&self) -> Self::PrincipalV; |
| 54 // { |
58 // { |
| 55 // self.make_origin_generator().make_origin() |
59 // self.make_origin_generator().make_origin() |
| 56 // } |
60 // } |
| 57 |
61 |
| 58 /// Return a similar zero as `x`. |
62 /// Return a similar zero as `x`. |
| 59 fn similar_origin_inst<I: Instance<Self>>(x: I) -> Self::Owned { |
63 fn similar_origin_inst<I: Instance<Self>>(x: I) -> Self::PrincipalV { |
| 60 x.eval(|xr| xr.similar_origin()) |
64 x.eval(|xr| xr.similar_origin()) |
| 61 } |
65 } |
| 62 } |
66 } |
| 63 |
67 |
| 64 /// Efficient in-place summation. |
68 /// Efficient in-place summation. |
| 66 pub trait AXPY<X = Self>: |
70 pub trait AXPY<X = Self>: |
| 67 VectorSpace |
71 VectorSpace |
| 68 + MulAssign<Self::Field> |
72 + MulAssign<Self::Field> |
| 69 + DivAssign<Self::Field> |
73 + DivAssign<Self::Field> |
| 70 + AddAssign<Self> |
74 + AddAssign<Self> |
| 71 + AddAssign<Self::Owned> |
75 + AddAssign<Self::PrincipalV> |
| 72 + SubAssign<Self> |
76 + SubAssign<Self> |
| 73 + SubAssign<Self::Owned> |
77 + SubAssign<Self::PrincipalV> |
| 74 + for<'b> AddAssign<&'b Self> |
78 + for<'b> AddAssign<&'b Self> |
| 75 + for<'b> SubAssign<&'b Self> |
79 + for<'b> SubAssign<&'b Self> |
| 76 where |
80 where |
| 77 X: Space, |
81 X: Space, |
| 78 { |
82 { |
| 91 |
95 |
| 92 /// Set self to zero. |
96 /// Set self to zero. |
| 93 fn set_zero(&mut self); |
97 fn set_zero(&mut self); |
| 94 } |
98 } |
| 95 |
99 |
| 96 pub trait ClosedVectorSpace: Instance<Self> + VectorSpace<Owned = Self> {} |
100 pub trait ClosedVectorSpace: Instance<Self> + VectorSpace<PrincipalV = Self> {} |
| 97 impl<X: Instance<X> + VectorSpace<Owned = Self>> ClosedVectorSpace for X {} |
101 impl<X: Instance<X> + VectorSpace<PrincipalV = Self>> ClosedVectorSpace for X {} |
| 98 |
102 |
| 99 /// Efficient in-place application for [`Linear`] operators. |
103 /// Efficient in-place application for [`Linear`] operators. |
| 100 #[replace_float_literals(F::cast_from(literal))] |
104 #[replace_float_literals(F::cast_from(literal))] |
| 101 pub trait GEMV<F: Num, X: Space, Y = <Self as Mapping<X>>::Codomain>: Linear<X> { |
105 pub trait GEMV<F: Num, X: Space, Y = <Self as Mapping<X>>::Codomain>: Linear<X> { |
| 102 /// Computes `y = αAx + βy`, where `A` is `Self`. |
106 /// Computes `y = αAx + βy`, where `A` is `Self`. |
| 231 fn opnorm_bound(&self, _xexp: E, _codexp: E) -> DynResult<F> { |
235 fn opnorm_bound(&self, _xexp: E, _codexp: E) -> DynResult<F> { |
| 232 Ok(F::ONE) |
236 Ok(F::ONE) |
| 233 } |
237 } |
| 234 } |
238 } |
| 235 |
239 |
| 236 impl<X: Clone + Space> Adjointable<X, X::OwnedSpace> for IdOp<X> { |
240 impl<X: Clone + Space> Adjointable<X, X::Principal> for IdOp<X> { |
| 237 type AdjointCodomain = X::OwnedSpace; |
241 type AdjointCodomain = X::Principal; |
| 238 type Adjoint<'a> |
242 type Adjoint<'a> |
| 239 = IdOp<X::OwnedSpace> |
243 = IdOp<X::Principal> |
| 240 where |
244 where |
| 241 X: 'a; |
245 X: 'a; |
| 242 |
246 |
| 243 fn adjoint(&self) -> Self::Adjoint<'_> { |
247 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 244 IdOp::new() |
248 IdOp::new() |
| 245 } |
249 } |
| 246 } |
250 } |
| 247 |
251 |
| 248 impl<X: Clone + Space> Preadjointable<X, X::OwnedSpace> for IdOp<X> { |
252 impl<X: Clone + Space> Preadjointable<X, X::Principal> for IdOp<X> { |
| 249 type PreadjointCodomain = X::OwnedSpace; |
253 type PreadjointCodomain = X::Principal; |
| 250 type Preadjoint<'a> |
254 type Preadjoint<'a> |
| 251 = IdOp<X::OwnedSpace> |
255 = IdOp<X::Principal> |
| 252 where |
256 where |
| 253 X: 'a; |
257 X: 'a; |
| 254 |
258 |
| 255 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
259 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
| 256 IdOp::new() |
260 IdOp::new() |
| 260 /// The zero operator from a space to itself |
264 /// The zero operator from a space to itself |
| 261 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
265 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
| 262 pub struct SimpleZeroOp; |
266 pub struct SimpleZeroOp; |
| 263 |
267 |
| 264 impl<X: VectorSpace> Mapping<X> for SimpleZeroOp { |
268 impl<X: VectorSpace> Mapping<X> for SimpleZeroOp { |
| 265 type Codomain = X::Owned; |
269 type Codomain = X::PrincipalV; |
| 266 |
270 |
| 267 fn apply<I: Instance<X>>(&self, x: I) -> X::Owned { |
271 fn apply<I: Instance<X>>(&self, x: I) -> X::PrincipalV { |
| 268 X::similar_origin_inst(x) |
272 X::similar_origin_inst(x) |
| 269 } |
273 } |
| 270 } |
274 } |
| 271 |
275 |
| 272 impl<X: VectorSpace> Linear<X> for SimpleZeroOp {} |
276 impl<X: VectorSpace> Linear<X> for SimpleZeroOp {} |
| 321 pub trait OriginGenerator<Y: VectorSpace> { |
325 pub trait OriginGenerator<Y: VectorSpace> { |
| 322 type Ref<'b>: OriginGenerator<Y> |
326 type Ref<'b>: OriginGenerator<Y> |
| 323 where |
327 where |
| 324 Self: 'b; |
328 Self: 'b; |
| 325 |
329 |
| 326 fn origin(&self) -> Y::Owned; |
330 fn origin(&self) -> Y::PrincipalV; |
| 327 fn as_ref(&self) -> Self::Ref<'_>; |
331 fn as_ref(&self) -> Self::Ref<'_>; |
| 328 } |
332 } |
| 329 |
333 |
| 330 impl<Y: VectorSpace> OriginGenerator<Y> for Y { |
334 impl<Y: VectorSpace> OriginGenerator<Y> for Y { |
| 331 type Ref<'b> |
335 type Ref<'b> |
| 332 = &'b Y |
336 = &'b Y |
| 333 where |
337 where |
| 334 Self: 'b; |
338 Self: 'b; |
| 335 |
339 |
| 336 #[inline] |
340 #[inline] |
| 337 fn origin(&self) -> Y::Owned { |
341 fn origin(&self) -> Y::PrincipalV { |
| 338 return self.similar_origin(); |
342 return self.similar_origin(); |
| 339 } |
343 } |
| 340 |
344 |
| 341 #[inline] |
345 #[inline] |
| 342 fn as_ref(&self) -> Self::Ref<'_> { |
346 fn as_ref(&self) -> Self::Ref<'_> { |
| 390 OY: OriginGenerator<Y>, |
394 OY: OriginGenerator<Y>, |
| 391 OXprime: OriginGenerator<Xprime>, |
395 OXprime: OriginGenerator<Xprime>, |
| 392 X: HasDual<F, DualSpace = Xprime>, |
396 X: HasDual<F, DualSpace = Xprime>, |
| 393 Y: HasDual<F, DualSpace = Yprime>, |
397 Y: HasDual<F, DualSpace = Yprime>, |
| 394 F: Float, |
398 F: Float, |
| 395 Xprime: VectorSpace<Field = F, Owned = Xprime>, |
399 Xprime: VectorSpace<Field = F, PrincipalV = Xprime>, |
| 396 Xprime::Owned: AXPY<Field = F>, |
400 Xprime::PrincipalV: AXPY<Field = F>, |
| 397 Yprime: Space + Instance<Yprime>, |
401 Yprime: Space + Instance<Yprime>, |
| 398 { |
402 { |
| 399 pub fn new_dualisable(y_og: OY, xprime_og: OXprime) -> Self { |
403 pub fn new_dualisable(y_og: OY, xprime_og: OXprime) -> Self { |
| 400 ZeroOp { |
404 ZeroOp { |
| 401 codomain_origin_generator: y_og, |
405 codomain_origin_generator: y_og, |
| 410 X: Space, |
414 X: Space, |
| 411 Y: VectorSpace<Field = F>, |
415 Y: VectorSpace<Field = F>, |
| 412 F: Float, |
416 F: Float, |
| 413 OY: OriginGenerator<Y>, |
417 OY: OriginGenerator<Y>, |
| 414 { |
418 { |
| 415 type Codomain = Y::Owned; |
419 type Codomain = Y::PrincipalV; |
| 416 |
420 |
| 417 fn apply<I: Instance<X>>(&self, _x: I) -> Y::Owned { |
421 fn apply<I: Instance<X>>(&self, _x: I) -> Y::PrincipalV { |
| 418 self.codomain_origin_generator.origin() |
422 self.codomain_origin_generator.origin() |
| 419 } |
423 } |
| 420 } |
424 } |
| 421 |
425 |
| 422 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F> |
426 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F> |
| 430 |
434 |
| 431 #[replace_float_literals(F::cast_from(literal))] |
435 #[replace_float_literals(F::cast_from(literal))] |
| 432 impl<X, Y, OY, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, OY, O, F> |
436 impl<X, Y, OY, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, OY, O, F> |
| 433 where |
437 where |
| 434 X: Space, |
438 X: Space, |
| 435 Y: AXPY<Field = F, Owned = Y>, |
439 Y: AXPY<Field = F, PrincipalV = Y>, |
| 436 F: Float, |
440 F: Float, |
| 437 OY: OriginGenerator<Y>, |
441 OY: OriginGenerator<Y>, |
| 438 { |
442 { |
| 439 // Computes `y = αAx + βy`, where `A` is `Self`. |
443 // Computes `y = αAx + βy`, where `A` is `Self`. |
| 440 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
444 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
| 448 |
452 |
| 449 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F> |
453 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F> |
| 450 where |
454 where |
| 451 X: Space + Instance<X> + Norm<E1, F>, |
455 X: Space + Instance<X> + Norm<E1, F>, |
| 452 Y: VectorSpace<Field = F>, |
456 Y: VectorSpace<Field = F>, |
| 453 Y::Owned: Clone, |
457 Y::PrincipalV: Clone, |
| 454 F: Float, |
458 F: Float, |
| 455 E1: NormExponent, |
459 E1: NormExponent, |
| 456 E2: NormExponent, |
460 E2: NormExponent, |
| 457 OY: OriginGenerator<Y>, |
461 OY: OriginGenerator<Y>, |
| 458 { |
462 { |
| 918 |
922 |
| 919 impl<Domain, F> Mapping<Domain> for Scaled<F> |
923 impl<Domain, F> Mapping<Domain> for Scaled<F> |
| 920 where |
924 where |
| 921 F: Float, |
925 F: Float, |
| 922 Domain: Space, |
926 Domain: Space, |
| 923 Domain::OwnedSpace: Mul<F>, |
927 Domain::Principal: Mul<F>, |
| 924 <Domain::OwnedSpace as Mul<F>>::Output: ClosedSpace, |
928 <Domain::Principal as Mul<F>>::Output: ClosedSpace, |
| 925 { |
929 { |
| 926 type Codomain = <Domain::OwnedSpace as Mul<F>>::Output; |
930 type Codomain = <Domain::Principal as Mul<F>>::Output; |
| 927 |
931 |
| 928 /// Compute the value of `self` at `x`. |
932 /// Compute the value of `self` at `x`. |
| 929 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { |
933 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { |
| 930 x.own() * self.0 |
934 x.own() * self.0 |
| 931 } |
935 } |