Tue, 31 Dec 2024 08:30:43 -0500
Compositions
src/linops.rs | file | annotate | diff | comparison | revisions | |
src/mapping.rs | file | annotate | diff | comparison | revisions |
--- a/src/linops.rs Tue Dec 31 09:02:55 2024 -0500 +++ b/src/linops.rs Tue Dec 31 08:30:43 2024 -0500 @@ -6,10 +6,10 @@ use std::marker::PhantomData; use serde::Serialize; use crate::types::*; -pub use crate::mapping::{Mapping, Space}; +pub use crate::mapping::{Mapping, Space, Composition}; use crate::direct_product::Pair; use crate::instance::Instance; -use crate::norms::{NormExponent, PairNorm, L1, L2, Linfinity}; +use crate::norms::{NormExponent, PairNorm, L1, L2, Linfinity, Norm}; /// Trait for linear operators on `X`. pub trait Linear<X : Space> : Mapping<X> @@ -58,7 +58,7 @@ pub trait BoundedLinear<X, XExp, CodExp, F = f64> : Linear<X> where F : Num, - X : Space, + X : Space + Norm<F, XExp>, XExp : NormExponent, CodExp : NormExponent { @@ -152,7 +152,7 @@ impl<F, X, E> BoundedLinear<X, E, E, F> for IdOp<X> where - X : Space + Clone, + X : Space + Clone + Norm<F, E>, F : Num, E : NormExponent { @@ -173,6 +173,53 @@ fn preadjoint(&self) -> Self::Preadjoint<'_> { IdOp::new() } } + +impl<S, T, E, X> Linear<X> for Composition<S, T, E> +where + X : Space, + T : Linear<X>, + S : Linear<T::Codomain> +{ } + +impl<F, S, T, E, X, Y> GEMV<F, X, Y> for Composition<S, T, E> +where + F : Num, + X : Space, + T : Linear<X>, + S : GEMV<F, T::Codomain, Y>, +{ + fn gemv<I : Instance<X>>(&self, y : &mut Y, α : F, x : I, β : F) { + self.outer.gemv(y, α, self.inner.apply(x), β) + } + + /// Computes `y = Ax`, where `A` is `Self` + fn apply_mut<I : Instance<X>>(&self, y : &mut Y, x : I){ + self.outer.apply_mut(y, self.inner.apply(x)) + } + + /// Computes `y += Ax`, where `A` is `Self` + fn apply_add<I : Instance<X>>(&self, y : &mut Y, x : I){ + self.outer.apply_add(y, self.inner.apply(x)) + } +} + +impl<F, S, T, X, Z, Xexp, Yexp, Zexp> BoundedLinear<X, Xexp, Yexp, F> for Composition<S, T, Zexp> +where + F : Num, + X : Space + Norm<F, Xexp>, + Z : Space + Norm<F, Zexp>, + Xexp : NormExponent, + Yexp : NormExponent, + Zexp : NormExponent, + T : BoundedLinear<X, Xexp, Zexp, F, Codomain=Z>, + S : BoundedLinear<Z, Zexp, Yexp, F>, +{ + fn opnorm_bound(&self, xexp : Xexp, yexp : Yexp) -> F { + let zexp = self.intermediate_norm_exponent; + self.outer.opnorm_bound(zexp, yexp) * self.inner.opnorm_bound(xexp, zexp) + } +} + /// “Row operator” $(S, T)$; $(S, T)(x, y)=Sx + Ty$. pub struct RowOp<S, T>(pub S, pub T); @@ -488,8 +535,8 @@ for RowOp<S, T> where F : Float, - A : Space, - B : Space, + A : Space + Norm<F, ExpA>, + B : Space + Norm<F, ExpB>, S : BoundedLinear<A, ExpA, ExpR, F>, T : BoundedLinear<B, ExpB, ExpR, F>, S::Codomain : Add<T::Codomain>, @@ -516,7 +563,7 @@ for ColOp<S, T> where F : Float, - A : Space, + A : Space + Norm<F, ExpA>, S : BoundedLinear<A, ExpA, ExpS, F>, T : BoundedLinear<A, ExpA, ExpT, F>, ExpA : NormExponent,
--- a/src/mapping.rs Tue Dec 31 09:02:55 2024 -0500 +++ b/src/mapping.rs Tue Dec 31 08:30:43 2024 -0500 @@ -4,10 +4,11 @@ use std::marker::PhantomData; use std::borrow::Cow; -use crate::types::Float; +use crate::types::{Num, Float}; use serde::Serialize; use crate::loc::Loc; pub use crate::instance::{Instance, Decomposition, BasicDecomposition, Space}; +use crate::norms::{Norm, NormExponent}; /// A mapping from `Domain` to `Codomain`. /// @@ -17,6 +18,33 @@ /// Compute the value of `self` at `x`. fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain; + + #[inline] + /// Form the composition `self ∘ other` + fn compose<X : Space, T : Mapping<X, Codomain=Domain>>(self, other : T) + -> Composition<Self, T> + where + Self : Sized + { + Composition{ outer : self, inner : other, intermediate_norm_exponent : () } + } + + + #[inline] + /// Form the composition `self ∘ other`, assigning a norm to the inermediate space + fn compose_with_norm<F, X, T, E>( + self, other : T, norm : E + ) -> Composition<Self, T, E> + where + Self : Sized, + X : Space, + T : Mapping<X, Codomain=Domain>, + E : NormExponent, + Domain : Norm<F, E>, + F : Num + { + Composition{ outer : self, inner : other, intermediate_norm_exponent : norm } + } } /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`. @@ -236,3 +264,25 @@ impl<X : Space, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize> SliceCodomain<X, F, N> for G {} + + +/// The composition S ∘ T. `E` is for storing a `NormExponent` for the intermediate space. +pub struct Composition<S, T, E = ()> { + pub outer : S, + pub inner : T, + pub intermediate_norm_exponent : E +} + +impl<S, T, X, E> Mapping<X> for Composition<S, T, E> +where + X : Space, + T : Mapping<X>, + S : Mapping<T::Codomain> +{ + type Codomain = S::Codomain; + + #[inline] + fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain { + self.outer.apply(self.inner.apply(x)) + } +}