| 304 fn adjoint(&self) -> Self::Adjoint<'_> { |
301 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 305 SimpleZeroOp |
302 SimpleZeroOp |
| 306 } |
303 } |
| 307 } |
304 } |
| 308 |
305 |
| |
306 pub trait OriginGenerator<Y: AXPY> { |
| |
307 type Ref<'b>: OriginGenerator<Y> |
| |
308 where |
| |
309 Self: 'b; |
| |
310 |
| |
311 fn origin(&self) -> Y::Owned; |
| |
312 fn as_ref(&self) -> Self::Ref<'_>; |
| |
313 } |
| |
314 |
| |
315 impl<Y: AXPY> OriginGenerator<Y> for Y { |
| |
316 type Ref<'b> |
| |
317 = &'b Y |
| |
318 where |
| |
319 Self: 'b; |
| |
320 |
| |
321 #[inline] |
| |
322 fn origin(&self) -> Y::Owned { |
| |
323 return self.similar_origin(); |
| |
324 } |
| |
325 |
| |
326 #[inline] |
| |
327 fn as_ref(&self) -> Self::Ref<'_> { |
| |
328 self |
| |
329 } |
| |
330 } |
| |
331 |
| |
332 impl<'b, Y: AXPY> OriginGenerator<Y> for &'b Y { |
| |
333 type Ref<'c> |
| |
334 = Self |
| |
335 where |
| |
336 Self: 'c; |
| |
337 |
| |
338 #[inline] |
| |
339 fn origin(&self) -> Y::Owned { |
| |
340 return self.similar_origin(); |
| |
341 } |
| |
342 |
| |
343 #[inline] |
| |
344 fn as_ref(&self) -> Self::Ref<'_> { |
| |
345 self |
| |
346 } |
| |
347 } |
| |
348 |
| 309 /// A zero operator that can be eitherh dualised or predualised (once). |
349 /// A zero operator that can be eitherh dualised or predualised (once). |
| 310 /// This is achieved by storing an oppropriate zero. |
350 /// This is achieved by storing an oppropriate zero. |
| 311 pub struct ZeroOp<X, Y: AXPY<Field = F>, C, O, F: Float = f64> { |
351 pub struct ZeroOp<X, Y: AXPY<Field = F>, OY: OriginGenerator<Y>, O, F: Float = f64> { |
| 312 codomain_sample: C, |
352 codomain_origin_generator: OY, |
| 313 other_sample: O, |
353 other_origin_generator: O, |
| 314 _phantoms: PhantomData<(X, Y, F)>, |
354 _phantoms: PhantomData<(X, Y, F)>, |
| 315 } |
355 } |
| 316 |
356 |
| 317 impl<'b, X, Y, F> ZeroOp<X, Y, &'b Y, &'b X::DualSpace, F> |
357 impl<X, Y, OY, F> ZeroOp<X, Y, OY, (), F> |
| 318 where |
358 where |
| 319 X: HasDual<F>, |
359 OY: OriginGenerator<Y>, |
| 320 Y: HasDual<F>, |
360 X: AXPY<Field = F>, |
| 321 Y::Owned: Clone, |
361 Y: AXPY<Field = F>, |
| 322 F: Float, |
362 F: Float, |
| 323 { |
363 { |
| 324 pub fn new_dualisable(x_dual_sample: &'b X::DualSpace, y_sample: &'b Y) -> Self { |
364 pub fn new(y_og: OY) -> Self { |
| 325 ZeroOp { |
365 ZeroOp { |
| 326 codomain_sample: y_sample, |
366 codomain_origin_generator: y_og, |
| 327 other_sample: x_dual_sample, |
367 other_origin_generator: (), |
| 328 _phantoms: PhantomData, |
368 _phantoms: PhantomData, |
| 329 } |
369 } |
| 330 } |
370 } |
| 331 } |
371 } |
| 332 |
372 |
| 333 impl<'b, X, Y, O, F> Mapping<X> for ZeroOp<X, Y, &'b Y, O, F> |
373 impl<X, Y, OY, OXprime, Xprime, Yprime, F> ZeroOp<X, Y, OY, OXprime, F> |
| |
374 where |
| |
375 OY: OriginGenerator<Y>, |
| |
376 OXprime: OriginGenerator<Xprime>, |
| |
377 X: HasDual<F, DualSpace = Xprime>, |
| |
378 Y: HasDual<F, DualSpace = Yprime>, |
| |
379 F: Float, |
| |
380 Xprime: AXPY<Field = F, Owned = Xprime>, |
| |
381 Xprime::Owned: AXPY<Field = F>, |
| |
382 Yprime: Space + Instance<Yprime>, |
| |
383 { |
| |
384 pub fn new_dualisable(y_og: OY, xprime_og: OXprime) -> Self { |
| |
385 ZeroOp { |
| |
386 codomain_origin_generator: y_og, |
| |
387 other_origin_generator: xprime_og, |
| |
388 _phantoms: PhantomData, |
| |
389 } |
| |
390 } |
| |
391 } |
| |
392 |
| |
393 impl<X, Y, O, OY, F> Mapping<X> for ZeroOp<X, Y, OY, O, F> |
| 334 where |
394 where |
| 335 X: Space + Instance<X>, |
395 X: Space + Instance<X>, |
| 336 Y: AXPY<Field = F>, |
396 Y: AXPY<Field = F>, |
| 337 F: Float, |
397 F: Float, |
| |
398 OY: OriginGenerator<Y>, |
| 338 { |
399 { |
| 339 type Codomain = Y::Owned; |
400 type Codomain = Y::Owned; |
| 340 |
401 |
| 341 fn apply<I: Instance<X>>(&self, _x: I) -> Y::Owned { |
402 fn apply<I: Instance<X>>(&self, _x: I) -> Y::Owned { |
| 342 self.codomain_sample.similar_origin() |
403 self.codomain_origin_generator.origin() |
| 343 } |
404 } |
| 344 } |
405 } |
| 345 |
406 |
| 346 impl<'b, X, Y, O, F> Linear<X> for ZeroOp<X, Y, &'b Y, O, F> |
407 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F> |
| 347 where |
408 where |
| 348 X: Space + Instance<X>, |
409 X: Space + Instance<X>, |
| 349 Y: AXPY<Field = F>, |
410 Y: AXPY<Field = F>, |
| 350 F: Float, |
411 F: Float, |
| |
412 OY: OriginGenerator<Y>, |
| 351 { |
413 { |
| 352 } |
414 } |
| 353 |
415 |
| 354 #[replace_float_literals(F::cast_from(literal))] |
416 #[replace_float_literals(F::cast_from(literal))] |
| 355 impl<'b, X, Y, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, &'b Y, O, F> |
417 impl<X, Y, OY, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, OY, O, F> |
| 356 where |
418 where |
| 357 X: Space + Instance<X>, |
419 X: Space + Instance<X>, |
| 358 Y: AXPY<Field = F>, |
420 Y: AXPY<Field = F, Owned = Y>, |
| 359 F: Float, |
421 F: Float, |
| |
422 OY: OriginGenerator<Y>, |
| 360 { |
423 { |
| 361 // Computes `y = αAx + βy`, where `A` is `Self`. |
424 // Computes `y = αAx + βy`, where `A` is `Self`. |
| 362 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
425 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
| 363 *y *= β; |
426 *y *= β; |
| 364 } |
427 } |
| 366 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { |
429 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { |
| 367 y.set_zero(); |
430 y.set_zero(); |
| 368 } |
431 } |
| 369 } |
432 } |
| 370 |
433 |
| 371 impl<'b, X, Y, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, &'b Y, O, F> |
434 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F> |
| 372 where |
435 where |
| 373 X: Space + Instance<X> + Norm<E1, F>, |
436 X: Space + Instance<X> + Norm<E1, F>, |
| 374 Y: AXPY<Field = F>, |
437 Y: AXPY<Field = F>, |
| 375 Y::Owned: Clone, |
438 Y::Owned: Clone, |
| 376 F: Float, |
439 F: Float, |
| 377 E1: NormExponent, |
440 E1: NormExponent, |
| 378 E2: NormExponent, |
441 E2: NormExponent, |
| |
442 OY: OriginGenerator<Y>, |
| 379 { |
443 { |
| 380 fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult<F> { |
444 fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult<F> { |
| 381 Ok(F::ZERO) |
445 Ok(F::ZERO) |
| 382 } |
446 } |
| 383 } |
447 } |
| 384 |
448 |
| 385 impl<'b, X, Y, Xprime, Yprime, F> Adjointable<X, Yprime> for ZeroOp<X, Y, &'b Y, &'b Xprime, F> |
449 impl<'b, X, Y, OY, OXprime, Xprime, Yprime, F> Adjointable<X, Yprime> |
| |
450 for ZeroOp<X, Y, OY, OXprime, F> |
| 386 where |
451 where |
| 387 X: HasDual<F, DualSpace = Xprime>, |
452 X: HasDual<F, DualSpace = Xprime>, |
| 388 Y: HasDual<F, DualSpace = Yprime>, |
453 Y: HasDual<F, DualSpace = Yprime>, |
| 389 F: Float, |
454 F: Float, |
| 390 Xprime: AXPY<Field = F, Owned = Xprime>, |
455 Xprime: AXPY<Field = F, Owned = Xprime>, |
| 391 Xprime::Owned: AXPY<Field = F>, |
456 Xprime::Owned: AXPY<Field = F>, |
| 392 Yprime: Space + Instance<Yprime>, |
457 Yprime: Space + Instance<Yprime>, |
| |
458 OY: OriginGenerator<Y>, |
| |
459 OXprime: OriginGenerator<X::DualSpace>, |
| 393 { |
460 { |
| 394 type AdjointCodomain = Xprime; |
461 type AdjointCodomain = Xprime; |
| 395 type Adjoint<'c> |
462 type Adjoint<'c> |
| 396 = ZeroOp<Yprime, Xprime, &'b Xprime, (), F> |
463 = ZeroOp<Yprime, Xprime, OXprime::Ref<'c>, (), F> |
| 397 where |
464 where |
| 398 Self: 'c; |
465 Self: 'c; |
| 399 // () means not (pre)adjointable. |
466 // () means not (pre)adjointable. |
| 400 |
467 |
| 401 fn adjoint(&self) -> Self::Adjoint<'_> { |
468 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 402 ZeroOp { |
469 ZeroOp { |
| 403 codomain_sample: self.other_sample, |
470 codomain_origin_generator: self.other_origin_generator.as_ref(), |
| 404 other_sample: (), |
471 other_origin_generator: (), |
| 405 _phantoms: PhantomData, |
472 _phantoms: PhantomData, |
| 406 } |
473 } |
| 407 } |
474 } |
| 408 } |
475 } |
| 409 |
|
| 410 /* |
|
| 411 /// Trait for forming origins (zeroes) in vector spaces |
|
| 412 pub trait OriginGenerator<X, F: Num = f64> { |
|
| 413 fn make_origin(&self) -> X; |
|
| 414 } |
|
| 415 |
|
| 416 /// Origin generator for statically sized Euclidean spaces. |
|
| 417 pub struct StaticEuclideanOriginGenerator; |
|
| 418 |
|
| 419 impl<X, F: Float> OriginGenerator<X, F> for StaticEuclideanOriginGenerator |
|
| 420 where |
|
| 421 X: StaticEuclidean<F> + Euclidean<F, Output = X>, |
|
| 422 { |
|
| 423 #[inline] |
|
| 424 fn make_origin(&self) -> X { |
|
| 425 X::origin() |
|
| 426 } |
|
| 427 } |
|
| 428 |
|
| 429 /// Origin generator arbitrary spaces that implement [`AXPY`], based on a sample vector. |
|
| 430 pub struct SimilarOriginGenerator<'a, X>(&'a X); |
|
| 431 |
|
| 432 impl<'a, X, F: Float> OriginGenerator<X, F> for SimilarOriginGenerator<'a, X> |
|
| 433 where |
|
| 434 X: AXPY<F, Owned = X>, |
|
| 435 { |
|
| 436 #[inline] |
|
| 437 fn make_origin(&self) -> X { |
|
| 438 self.0.similar_origin() |
|
| 439 } |
|
| 440 } |
|
| 441 |
|
| 442 pub struct NotAnOriginGenerator; |
|
| 443 |
|
| 444 /// The zero operator |
|
| 445 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
|
| 446 pub struct ZeroOp<X, Y, YOrigin, XDOrigin = NotAnOriginGenerator, F: Num = f64> { |
|
| 447 y_origin: YOrigin, |
|
| 448 xd_origin: XDOrigin, |
|
| 449 _phantoms: PhantomData<(X, Y, F)>, |
|
| 450 } |
|
| 451 |
|
| 452 // TODO: Need to make Zero in Instance. |
|
| 453 |
|
| 454 impl<X, Y, F, YOrigin, XDOrigin> ZeroOp<X, Y, YOrigin, XDOrigin, F> |
|
| 455 where |
|
| 456 F: Num, |
|
| 457 YOrigin: OriginGenerator<Y, F>, |
|
| 458 { |
|
| 459 pub fn new(y_origin: YOrigin, xd_origin: XDOrigin) -> Self { |
|
| 460 ZeroOp { |
|
| 461 y_origin, |
|
| 462 xd_origin, |
|
| 463 _phantoms: PhantomData, |
|
| 464 } |
|
| 465 } |
|
| 466 } |
|
| 467 |
|
| 468 impl<X, Y, F, YOrigin, XDOrigin> Mapping<X> for ZeroOp<X, Y, YOrigin, XDOrigin, F> |
|
| 469 where |
|
| 470 F: Num, |
|
| 471 YOrigin: OriginGenerator<Y, F>, |
|
| 472 Y: Space, |
|
| 473 X: Space + Instance<X>, |
|
| 474 { |
|
| 475 type Codomain = Y; |
|
| 476 |
|
| 477 fn apply<I: Instance<X>>(&self, _: I) -> Y { |
|
| 478 self.y_origin.make_origin() |
|
| 479 } |
|
| 480 } |
|
| 481 |
|
| 482 impl<X, Y, F, YOrigin, XDOrigin> Linear<X> for ZeroOp<X, Y, YOrigin, XDOrigin, F> |
|
| 483 where |
|
| 484 F: Num, |
|
| 485 YOrigin: OriginGenerator<Y, F>, |
|
| 486 Y: Space, |
|
| 487 X: Space + Instance<X>, |
|
| 488 { |
|
| 489 } |
|
| 490 |
|
| 491 #[replace_float_literals(F::cast_from(literal))] |
|
| 492 impl<X, Y, F, YOrigin, XDOrigin> GEMV<F, X, Y> for ZeroOp<X, Y, YOrigin, XDOrigin, F> |
|
| 493 where |
|
| 494 F: Num, |
|
| 495 YOrigin: OriginGenerator<Y, F>, |
|
| 496 Y: Space + AXPY<F>, |
|
| 497 X: Space + Instance<X>, |
|
| 498 { |
|
| 499 // Computes `y = αAx + βy`, where `A` is `Self`. |
|
| 500 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
|
| 501 *y *= β; |
|
| 502 } |
|
| 503 |
|
| 504 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { |
|
| 505 y.set_zero(); |
|
| 506 } |
|
| 507 } |
|
| 508 |
|
| 509 impl<X, Y, F, YOrigin, XDOrigin, E1, E2> BoundedLinear<X, E1, E2, F> |
|
| 510 for ZeroOp<X, Y, YOrigin, XDOrigin, F> |
|
| 511 where |
|
| 512 F: Num, |
|
| 513 YOrigin: OriginGenerator<Y, F>, |
|
| 514 Y: Space + AXPY<F> + Norm<E2, F>, |
|
| 515 X: Space + Instance<X> + Norm<E1, F>, |
|
| 516 E1: NormExponent, |
|
| 517 E2: NormExponent, |
|
| 518 { |
|
| 519 fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult<F> { |
|
| 520 Ok(F::ZERO) |
|
| 521 } |
|
| 522 } |
|
| 523 |
|
| 524 impl<X, Y, Yprime, F, YOrigin, XDOrigin> Adjointable<X, Yprime> |
|
| 525 for ZeroOp<X, Y, YOrigin, XDOrigin, F> |
|
| 526 where |
|
| 527 F: Num, |
|
| 528 YOrigin: OriginGenerator<Y, F>, |
|
| 529 Y: Space + AXPY<F>, |
|
| 530 X: Space + Instance<X> + HasDual<F>, |
|
| 531 XDOrigin: OriginGenerator<X::DualSpace, F> + Clone, |
|
| 532 Yprime: Space + Instance<Yprime>, |
|
| 533 { |
|
| 534 type AdjointCodomain = X::DualSpace; |
|
| 535 type Adjoint<'b> |
|
| 536 = ZeroOp<Yprime, X::DualSpace, XDOrigin, NotAnOriginGenerator, F> |
|
| 537 where |
|
| 538 Self: 'b; |
|
| 539 // () means not (pre)adjointable. |
|
| 540 |
|
| 541 fn adjoint(&self) -> Self::Adjoint<'_> { |
|
| 542 ZeroOp::new(self.xd_origin.clone(), NotAnOriginGenerator) |
|
| 543 } |
|
| 544 } |
|
| 545 */ |
|
| 546 |
|
| 547 /* |
|
| 548 impl<X, Y, Ypre, Xpre, F, YOrigin, XDOrigin> Preadjointable<X, Ypre> |
|
| 549 for ZeroOp<X, Y, YOrigin, XDOrigin, F> |
|
| 550 where |
|
| 551 F: Num, |
|
| 552 YOrigin: OriginGenerator<Y, F>, |
|
| 553 Y: Space + AXPY<F>, |
|
| 554 X: Space + Instance<X> + HasDual<F>, |
|
| 555 XDOrigin: OriginGenerator<Xpre, F> + Clone, |
|
| 556 Ypre: Space + Instance<Ypre> + HasDual<DualSpace = X>, |
|
| 557 { |
|
| 558 type PreadjointCodomain = Xpre; |
|
| 559 type Preadjoint<'b> |
|
| 560 = ZeroOp<Ypre, Xpre, XDOrigin, NotAnOriginGenerator, F> |
|
| 561 where |
|
| 562 Self: 'b; |
|
| 563 // () means not (pre)adjointable. |
|
| 564 |
|
| 565 fn adjoint(&self) -> Self::Adjoint<'_> { |
|
| 566 ZeroOp::new(self.xpre_origin.clone(), NotAnOriginGenerator) |
|
| 567 } |
|
| 568 } |
|
| 569 */ |
|
| 570 |
476 |
| 571 impl<S, T, E, X> Linear<X> for Composition<S, T, E> |
477 impl<S, T, E, X> Linear<X> for Composition<S, T, E> |
| 572 where |
478 where |
| 573 X: Space, |
479 X: Space, |
| 574 T: Linear<X>, |
480 T: Linear<X>, |