diff -r 2e4517b55442 -r 9e5b9fc81c52 src/linops.rs --- a/src/linops.rs Sun Apr 27 20:41:36 2025 -0500 +++ b/src/linops.rs Mon Apr 28 08:26:04 2025 -0500 @@ -2,38 +2,46 @@ Abstract linear operators. */ -use numeric_literals::replace_float_literals; -use std::marker::PhantomData; -use serde::Serialize; -use crate::types::*; -pub use crate::mapping::{Mapping, Space, Composition}; use crate::direct_product::Pair; use crate::instance::Instance; -use crate::norms::{NormExponent, PairNorm, L1, L2, Linfinity, Norm}; +pub use crate::mapping::{Composition, DifferentiableImpl, Mapping, Space}; +use crate::norms::{Linfinity, Norm, NormExponent, PairNorm, L1, L2}; +use crate::types::*; +use numeric_literals::replace_float_literals; +use serde::Serialize; +use std::marker::PhantomData; /// Trait for linear operators on `X`. -pub trait Linear : Mapping -{ } +pub trait Linear: Mapping {} + +// impl> DifferentiableImpl for A { +// type Derivative = >::Codomain; + +// /// Compute the differential of `self` at `x`, consuming the input. +// fn differential_impl>(&self, x: I) -> Self::Derivative { +// self.apply(x) +// } +// } /// Efficient in-place summation. #[replace_float_literals(F::cast_from(literal))] -pub trait AXPY : Space + std::ops::MulAssign +pub trait AXPY: Space + std::ops::MulAssign where - F : Num, - X : Space, + F: Num, + X: Space, { - type Owned : AXPY; + type Owned: AXPY; /// Computes `y = βy + αx`, where `y` is `Self`. - fn axpy>(&mut self, α : F, x : I, β : F); + fn axpy>(&mut self, α: F, x: I, β: F); /// Copies `x` to `self`. - fn copy_from>(&mut self, x : I) { + fn copy_from>(&mut self, x: I) { self.axpy(1.0, x, 0.0) } /// Computes `y = αx`, where `y` is `Self`. - fn scale_from>(&mut self, α : F, x : I) { + fn scale_from>(&mut self, α: F, x: I) { self.axpy(α, x, 0.0) } @@ -46,37 +54,36 @@ /// Efficient in-place application for [`Linear`] operators. #[replace_float_literals(F::cast_from(literal))] -pub trait GEMV>::Codomain> : Linear { +pub trait GEMV>::Codomain>: Linear { /// Computes `y = αAx + βy`, where `A` is `Self`. - fn gemv>(&self, y : &mut Y, α : F, x : I, β : F); + fn gemv>(&self, y: &mut Y, α: F, x: I, β: F); #[inline] /// Computes `y = Ax`, where `A` is `Self` - fn apply_mut>(&self, y : &mut Y, x : I){ + fn apply_mut>(&self, y: &mut Y, x: I) { self.gemv(y, 1.0, x, 0.0) } #[inline] /// Computes `y += Ax`, where `A` is `Self` - fn apply_add>(&self, y : &mut Y, x : I){ + fn apply_add>(&self, y: &mut Y, x: I) { self.gemv(y, 1.0, x, 1.0) } } - /// Bounded linear operators -pub trait BoundedLinear : Linear +pub trait BoundedLinear: Linear where - F : Num, - X : Space + Norm, - XExp : NormExponent, - CodExp : NormExponent + F: Num, + X: Space + Norm, + XExp: NormExponent, + CodExp: NormExponent, { /// A bound on the operator norm $\|A\|$ for the linear operator $A$=`self`. /// This is not expected to be the norm, just any bound on it that can be /// reasonably implemented. The [`NormExponent`] `xexp` indicates the norm /// in `X`, and `codexp` in the codomain. - fn opnorm_bound(&self, xexp : XExp, codexp : CodExp) -> F; + fn opnorm_bound(&self, xexp: XExp, codexp: CodExp) -> F; } // Linear operator application into mutable target. The [`AsRef`] bound @@ -90,13 +97,15 @@ }*/ /// Trait for forming the adjoint operator of `Self`. -pub trait Adjointable : Linear +pub trait Adjointable: Linear where - X : Space, - Yʹ : Space, + X: Space, + Yʹ: Space, { - type AdjointCodomain : Space; - type Adjoint<'a> : Linear where Self : 'a; + type AdjointCodomain: Space; + type Adjoint<'a>: Linear + where + Self: 'a; /// Form the adjoint operator of `self`. fn adjoint(&self) -> Self::Adjoint<'_>; @@ -112,144 +121,168 @@ /// We do not make additional restrictions on `Self::Preadjoint` (in particular, it /// does not have to be adjointable) to allow `X` to be a subspace yet the preadjoint /// have the full space as the codomain, etc. -pub trait Preadjointable : Linear { - type PreadjointCodomain : Space; - type Preadjoint<'a> : Linear< - Ypre, Codomain=Self::PreadjointCodomain - > where Self : 'a; +pub trait Preadjointable>::Codomain>: + Linear +{ + type PreadjointCodomain: Space; + type Preadjoint<'a>: Linear + where + Self: 'a; /// Form the adjoint operator of `self`. fn preadjoint(&self) -> Self::Preadjoint<'_>; } /// Adjointable operators $A: X → Y$ between reflexive spaces $X$ and $Y$. -pub trait SimplyAdjointable : Adjointable>::Codomain> {} -impl<'a,X : Space, T> SimplyAdjointable for T -where T : Adjointable>::Codomain> {} +pub trait SimplyAdjointable: Adjointable>::Codomain> {} +impl<'a, X: Space, T> SimplyAdjointable for T where + T: Adjointable>::Codomain> +{ +} /// The identity operator -#[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] -pub struct IdOp (PhantomData); +#[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] +pub struct IdOp(PhantomData); impl IdOp { - pub fn new() -> IdOp { IdOp(PhantomData) } + pub fn new() -> IdOp { + IdOp(PhantomData) + } } -impl Mapping for IdOp { +impl Mapping for IdOp { type Codomain = X; - fn apply>(&self, x : I) -> X { + fn apply>(&self, x: I) -> X { x.own() } } -impl Linear for IdOp -{ } +impl Linear for IdOp {} #[replace_float_literals(F::cast_from(literal))] -impl GEMV for IdOp +impl GEMV for IdOp where - Y : AXPY, - X : Clone + Space + Y: AXPY, + X: Clone + Space, { // Computes `y = αAx + βy`, where `A` is `Self`. - fn gemv>(&self, y : &mut Y, α : F, x : I, β : F) { + fn gemv>(&self, y: &mut Y, α: F, x: I, β: F) { y.axpy(α, x, β) } - fn apply_mut>(&self, y : &mut Y, x : I){ + fn apply_mut>(&self, y: &mut Y, x: I) { y.copy_from(x); } } impl BoundedLinear for IdOp where - X : Space + Clone + Norm, - F : Num, - E : NormExponent + X: Space + Clone + Norm, + F: Num, + E: NormExponent, { - fn opnorm_bound(&self, _xexp : E, _codexp : E) -> F { F::ONE } -} - -impl Adjointable for IdOp { - type AdjointCodomain=X; - type Adjoint<'a> = IdOp where X : 'a; - - fn adjoint(&self) -> Self::Adjoint<'_> { IdOp::new() } + fn opnorm_bound(&self, _xexp: E, _codexp: E) -> F { + F::ONE + } } -impl Preadjointable for IdOp { - type PreadjointCodomain=X; - type Preadjoint<'a> = IdOp where X : 'a; +impl Adjointable for IdOp { + type AdjointCodomain = X; + type Adjoint<'a> + = IdOp + where + X: 'a; - fn preadjoint(&self) -> Self::Preadjoint<'_> { IdOp::new() } + fn adjoint(&self) -> Self::Adjoint<'_> { + IdOp::new() + } } +impl Preadjointable for IdOp { + type PreadjointCodomain = X; + type Preadjoint<'a> + = IdOp + where + X: 'a; + + fn preadjoint(&self) -> Self::Preadjoint<'_> { + IdOp::new() + } +} /// The zero operator -#[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] +#[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] pub struct ZeroOp<'a, X, XD, Y, F> { - zero : &'a Y, // TODO: don't pass this in `new`; maybe not even store. - dual_or_predual_zero : XD, - _phantoms : PhantomData<(X, Y, F)>, + zero: &'a Y, // TODO: don't pass this in `new`; maybe not even store. + dual_or_predual_zero: XD, + _phantoms: PhantomData<(X, Y, F)>, } // TODO: Need to make Zero in Instance. -impl<'a, F : Num, X : Space, XD, Y : Space + Clone> ZeroOp<'a, X, XD, Y, F> { - pub fn new(zero : &'a Y, dual_or_predual_zero : XD) -> Self { - ZeroOp{ zero, dual_or_predual_zero, _phantoms : PhantomData } +impl<'a, F: Num, X: Space, XD, Y: Space + Clone> ZeroOp<'a, X, XD, Y, F> { + pub fn new(zero: &'a Y, dual_or_predual_zero: XD) -> Self { + ZeroOp { + zero, + dual_or_predual_zero, + _phantoms: PhantomData, + } } } -impl<'a, F : Num, X : Space, XD, Y : AXPY + Clone> Mapping for ZeroOp<'a, X, XD, Y, F> { +impl<'a, F: Num, X: Space, XD, Y: AXPY + Clone> Mapping for ZeroOp<'a, X, XD, Y, F> { type Codomain = Y; - fn apply>(&self, _x : I) -> Y { + fn apply>(&self, _x: I) -> Y { self.zero.clone() } } -impl<'a, F : Num, X : Space, XD, Y : AXPY + Clone> Linear for ZeroOp<'a, X, XD, Y, F> -{ } +impl<'a, F: Num, X: Space, XD, Y: AXPY + Clone> Linear for ZeroOp<'a, X, XD, Y, F> {} #[replace_float_literals(F::cast_from(literal))] impl<'a, F, X, XD, Y> GEMV for ZeroOp<'a, X, XD, Y, F> where - F : Num, - Y : AXPY + Clone, - X : Space + F: Num, + Y: AXPY + Clone, + X: Space, { // Computes `y = αAx + βy`, where `A` is `Self`. - fn gemv>(&self, y : &mut Y, _α : F, _x : I, β : F) { + fn gemv>(&self, y: &mut Y, _α: F, _x: I, β: F) { *y *= β; } - fn apply_mut>(&self, y : &mut Y, _x : I){ + fn apply_mut>(&self, y: &mut Y, _x: I) { y.set_zero(); } } impl<'a, F, X, XD, Y, E1, E2> BoundedLinear for ZeroOp<'a, X, XD, Y, F> where - X : Space + Norm, - Y : AXPY + Clone + Norm, - F : Num, - E1 : NormExponent, - E2 : NormExponent, + X: Space + Norm, + Y: AXPY + Clone + Norm, + F: Num, + E1: NormExponent, + E2: NormExponent, { - fn opnorm_bound(&self, _xexp : E1, _codexp : E2) -> F { F::ZERO } + fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> F { + F::ZERO + } } -impl<'a, F : Num, X, XD, Y, Yprime : Space> Adjointable for ZeroOp<'a, X, XD, Y, F> +impl<'a, F: Num, X, XD, Y, Yprime: Space> Adjointable for ZeroOp<'a, X, XD, Y, F> where - X : Space, - Y : AXPY + Clone + 'static, - XD : AXPY + Clone + 'static, + X: Space, + Y: AXPY + Clone + 'static, + XD: AXPY + Clone + 'static, { type AdjointCodomain = XD; - type Adjoint<'b> = ZeroOp<'b, Yprime, (), XD, F> where Self : 'b; - // () means not (pre)adjointable. + type Adjoint<'b> + = ZeroOp<'b, Yprime, (), XD, F> + where + Self: 'b; + // () means not (pre)adjointable. fn adjoint(&self) -> Self::Adjoint<'_> { ZeroOp::new(&self.dual_or_predual_zero, ()) @@ -258,15 +291,18 @@ impl<'a, F, X, XD, Y, Ypre> Preadjointable for ZeroOp<'a, X, XD, Y, F> where - F : Num, - X : Space, - Y : AXPY + Clone, - Ypre : Space, - XD : AXPY + Clone + 'static, + F: Num, + X: Space, + Y: AXPY + Clone, + Ypre: Space, + XD: AXPY + Clone + 'static, { type PreadjointCodomain = XD; - type Preadjoint<'b> = ZeroOp<'b, Ypre, (), XD, F> where Self : 'b; - // () means not (pre)adjointable. + type Preadjoint<'b> + = ZeroOp<'b, Ypre, (), XD, F> + where + Self: 'b; + // () means not (pre)adjointable. fn preadjoint(&self) -> Self::Preadjoint<'_> { ZeroOp::new(&self.dual_or_predual_zero, ()) @@ -275,45 +311,46 @@ impl Linear for Composition where - X : Space, - T : Linear, - S : Linear -{ } + X: Space, + T: Linear, + S: Linear, +{ +} impl GEMV for Composition where - F : Num, - X : Space, - T : Linear, - S : GEMV, + F: Num, + X: Space, + T: Linear, + S: GEMV, { - fn gemv>(&self, y : &mut Y, α : F, x : I, β : F) { + fn gemv>(&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>(&self, y : &mut Y, x : I){ + fn apply_mut>(&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>(&self, y : &mut Y, x : I){ + fn apply_add>(&self, y: &mut Y, x: I) { self.outer.apply_add(y, self.inner.apply(x)) } } impl BoundedLinear for Composition where - F : Num, - X : Space + Norm, - Z : Space + Norm, - Xexp : NormExponent, - Yexp : NormExponent, - Zexp : NormExponent, - T : BoundedLinear, - S : BoundedLinear, + F: Num, + X: Space + Norm, + Z: Space + Norm, + Xexp: NormExponent, + Yexp: NormExponent, + Zexp: NormExponent, + T: BoundedLinear, + S: BoundedLinear, { - fn opnorm_bound(&self, xexp : Xexp, yexp : 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) } @@ -326,17 +363,16 @@ impl Mapping> for RowOp where - A : Space, - B : Space, - S : Mapping, - T : Mapping, - S::Codomain : Add, - >::Output : Space, - + A: Space, + B: Space, + S: Mapping, + T: Mapping, + S::Codomain: Add, + >::Output: Space, { type Codomain = >::Output; - fn apply>>(&self, x : I) -> Self::Codomain { + fn apply>>(&self, x: I) -> Self::Codomain { let Pair(a, b) = x.decompose(); self.0.apply(a) + self.1.apply(b) } @@ -344,38 +380,38 @@ impl Linear> for RowOp where - A : Space, - B : Space, - S : Linear, - T : Linear, - S::Codomain : Add, - >::Output : Space, -{ } - + A: Space, + B: Space, + S: Linear, + T: Linear, + S::Codomain: Add, + >::Output: Space, +{ +} impl<'b, F, S, T, Y, U, V> GEMV, Y> for RowOp where - U : Space, - V : Space, - S : GEMV, - T : GEMV, - F : Num, - Self : Linear, Codomain=Y> + U: Space, + V: Space, + S: GEMV, + T: GEMV, + F: Num, + Self: Linear, Codomain = Y>, { - fn gemv>>(&self, y : &mut Y, α : F, x : I, β : F) { + fn gemv>>(&self, y: &mut Y, α: F, x: I, β: F) { let Pair(u, v) = x.decompose(); self.0.gemv(y, α, u, β); self.1.gemv(y, α, v, F::ONE); } - fn apply_mut>>(&self, y : &mut Y, x : I) { + fn apply_mut>>(&self, y: &mut Y, x: I) { let Pair(u, v) = x.decompose(); self.0.apply_mut(y, u); self.1.apply_add(y, v); } /// Computes `y += Ax`, where `A` is `Self` - fn apply_add>>(&self, y : &mut Y, x : I) { + fn apply_add>>(&self, y: &mut Y, x: I) { let Pair(u, v) = x.decompose(); self.0.apply_add(y, u); self.1.apply_add(y, v); @@ -387,129 +423,137 @@ impl Mapping for ColOp where - A : Space, - S : Mapping, - T : Mapping, + A: Space, + S: Mapping, + T: Mapping, { type Codomain = Pair; - fn apply>(&self, a : I) -> Self::Codomain { + fn apply>(&self, a: I) -> Self::Codomain { Pair(self.0.apply(a.ref_instance()), self.1.apply(a)) } } impl Linear for ColOp where - A : Space, - S : Mapping, - T : Mapping, -{ } + A: Space, + S: Mapping, + T: Mapping, +{ +} impl GEMV> for ColOp where - X : Space, - S : GEMV, - T : GEMV, - F : Num, - Self : Linear> + X: Space, + S: GEMV, + T: GEMV, + F: Num, + Self: Linear>, { - fn gemv>(&self, y : &mut Pair, α : F, x : I, β : F) { + fn gemv>(&self, y: &mut Pair, α: F, x: I, β: F) { self.0.gemv(&mut y.0, α, x.ref_instance(), β); self.1.gemv(&mut y.1, α, x, β); } - fn apply_mut>(&self, y : &mut Pair, x : I){ + fn apply_mut>(&self, y: &mut Pair, x: I) { self.0.apply_mut(&mut y.0, x.ref_instance()); self.1.apply_mut(&mut y.1, x); } /// Computes `y += Ax`, where `A` is `Self` - fn apply_add>(&self, y : &mut Pair, x : I){ + fn apply_add>(&self, y: &mut Pair, x: I) { self.0.apply_add(&mut y.0, x.ref_instance()); self.1.apply_add(&mut y.1, x); } } - -impl Adjointable, Yʹ> for RowOp +impl Adjointable, Yʹ> for RowOp where - A : Space, - B : Space, - Yʹ : Space, - S : Adjointable, - T : Adjointable, - Self : Linear>, + A: Space, + B: Space, + Yʹ: Space, + S: Adjointable, + T: Adjointable, + Self: Linear>, // for<'a> ColOp, T::Adjoint<'a>> : Linear< // Yʹ, // Codomain=Pair // >, { type AdjointCodomain = Pair; - type Adjoint<'a> = ColOp, T::Adjoint<'a>> where Self : 'a; + type Adjoint<'a> + = ColOp, T::Adjoint<'a>> + where + Self: 'a; fn adjoint(&self) -> Self::Adjoint<'_> { ColOp(self.0.adjoint(), self.1.adjoint()) } } -impl Preadjointable, Yʹ> for RowOp +impl Preadjointable, Yʹ> for RowOp where - A : Space, - B : Space, - Yʹ : Space, - S : Preadjointable, - T : Preadjointable, - Self : Linear>, - for<'a> ColOp, T::Preadjoint<'a>> : Linear< - Yʹ, Codomain=Pair, - >, + A: Space, + B: Space, + Yʹ: Space, + S: Preadjointable, + T: Preadjointable, + Self: Linear>, + for<'a> ColOp, T::Preadjoint<'a>>: + Linear>, { type PreadjointCodomain = Pair; - type Preadjoint<'a> = ColOp, T::Preadjoint<'a>> where Self : 'a; + type Preadjoint<'a> + = ColOp, T::Preadjoint<'a>> + where + Self: 'a; fn preadjoint(&self) -> Self::Preadjoint<'_> { ColOp(self.0.preadjoint(), self.1.preadjoint()) } } - -impl Adjointable> for ColOp +impl Adjointable> for ColOp where - A : Space, - Xʹ : Space, - Yʹ : Space, - R : Space + ClosedAdd, - S : Adjointable, - T : Adjointable, - Self : Linear, + A: Space, + Xʹ: Space, + Yʹ: Space, + R: Space + ClosedAdd, + S: Adjointable, + T: Adjointable, + Self: Linear, // for<'a> RowOp, T::Adjoint<'a>> : Linear< // Pair, // Codomain=R, // >, { type AdjointCodomain = R; - type Adjoint<'a> = RowOp, T::Adjoint<'a>> where Self : 'a; + type Adjoint<'a> + = RowOp, T::Adjoint<'a>> + where + Self: 'a; fn adjoint(&self) -> Self::Adjoint<'_> { RowOp(self.0.adjoint(), self.1.adjoint()) } } -impl Preadjointable> for ColOp +impl Preadjointable> for ColOp where - A : Space, - Xʹ : Space, - Yʹ : Space, - R : Space + ClosedAdd, - S : Preadjointable, - T : Preadjointable, - Self : Linear, - for<'a> RowOp, T::Preadjoint<'a>> : Linear< - Pair, Codomain = R, - >, + A: Space, + Xʹ: Space, + Yʹ: Space, + R: Space + ClosedAdd, + S: Preadjointable, + T: Preadjointable, + Self: Linear, + for<'a> RowOp, T::Preadjoint<'a>>: Linear, Codomain = R>, { type PreadjointCodomain = R; - type Preadjoint<'a> = RowOp, T::Preadjoint<'a>> where Self : 'a; + type Preadjoint<'a> + = RowOp, T::Preadjoint<'a>> + where + Self: 'a; fn preadjoint(&self) -> Self::Preadjoint<'_> { RowOp(self.0.preadjoint(), self.1.preadjoint()) @@ -521,14 +565,14 @@ impl Mapping> for DiagOp where - A : Space, - B : Space, - S : Mapping, - T : Mapping, + A: Space, + B: Space, + S: Mapping, + T: Mapping, { type Codomain = Pair; - fn apply>>(&self, x : I) -> Self::Codomain { + fn apply>>(&self, x: I) -> Self::Codomain { let Pair(a, b) = x.decompose(); Pair(self.0.apply(a), self.1.apply(b)) } @@ -536,81 +580,84 @@ impl Linear> for DiagOp where - A : Space, - B : Space, - S : Linear, - T : Linear, -{ } + A: Space, + B: Space, + S: Linear, + T: Linear, +{ +} impl GEMV, Pair> for DiagOp where - A : Space, - B : Space, - U : Space, - V : Space, - S : GEMV, - T : GEMV, - F : Num, - Self : Linear, Codomain=Pair>, + A: Space, + B: Space, + U: Space, + V: Space, + S: GEMV, + T: GEMV, + F: Num, + Self: Linear, Codomain = Pair>, { - fn gemv>>(&self, y : &mut Pair, α : F, x : I, β : F) { + fn gemv>>(&self, y: &mut Pair, α: F, x: I, β: F) { let Pair(u, v) = x.decompose(); self.0.gemv(&mut y.0, α, u, β); self.1.gemv(&mut y.1, α, v, β); } - fn apply_mut>>(&self, y : &mut Pair, x : I){ + fn apply_mut>>(&self, y: &mut Pair, x: I) { let Pair(u, v) = x.decompose(); self.0.apply_mut(&mut y.0, u); self.1.apply_mut(&mut y.1, v); } /// Computes `y += Ax`, where `A` is `Self` - fn apply_add>>(&self, y : &mut Pair, x : I){ + fn apply_add>>(&self, y: &mut Pair, x: I) { let Pair(u, v) = x.decompose(); self.0.apply_add(&mut y.0, u); self.1.apply_add(&mut y.1, v); } } -impl Adjointable, Pair> for DiagOp +impl Adjointable, Pair> for DiagOp where - A : Space, - B : Space, + A: Space, + B: Space, Xʹ: Space, - Yʹ : Space, - R : Space, - S : Adjointable, - T : Adjointable, - Self : Linear>, - for<'a> DiagOp, T::Adjoint<'a>> : Linear< - Pair, Codomain=R, - >, + Yʹ: Space, + R: Space, + S: Adjointable, + T: Adjointable, + Self: Linear>, + for<'a> DiagOp, T::Adjoint<'a>>: Linear, Codomain = R>, { type AdjointCodomain = R; - type Adjoint<'a> = DiagOp, T::Adjoint<'a>> where Self : 'a; + type Adjoint<'a> + = DiagOp, T::Adjoint<'a>> + where + Self: 'a; fn adjoint(&self) -> Self::Adjoint<'_> { DiagOp(self.0.adjoint(), self.1.adjoint()) } } -impl Preadjointable, Pair> for DiagOp +impl Preadjointable, Pair> for DiagOp where - A : Space, - B : Space, + A: Space, + B: Space, Xʹ: Space, - Yʹ : Space, - R : Space, - S : Preadjointable, - T : Preadjointable, - Self : Linear>, - for<'a> DiagOp, T::Preadjoint<'a>> : Linear< - Pair, Codomain=R, - >, + Yʹ: Space, + R: Space, + S: Preadjointable, + T: Preadjointable, + Self: Linear>, + for<'a> DiagOp, T::Preadjoint<'a>>: Linear, Codomain = R>, { type PreadjointCodomain = R; - type Preadjoint<'a> = DiagOp, T::Preadjoint<'a>> where Self : 'a; + type Preadjoint<'a> + = DiagOp, T::Preadjoint<'a>> + where + Self: 'a; fn preadjoint(&self) -> Self::Preadjoint<'_> { DiagOp(self.0.preadjoint(), self.1.preadjoint()) @@ -620,28 +667,26 @@ /// Block operator pub type BlockOp = ColOp, RowOp>; - macro_rules! pairnorm { ($expj:ty) => { impl - BoundedLinear, PairNorm, ExpR, F> - for RowOp + BoundedLinear, PairNorm, ExpR, F> for RowOp where - F : Float, - A : Space + Norm, - B : Space + Norm, - S : BoundedLinear, - T : BoundedLinear, - S::Codomain : Add, - >::Output : Space, - ExpA : NormExponent, - ExpB : NormExponent, - ExpR : NormExponent, + F: Float, + A: Space + Norm, + B: Space + Norm, + S: BoundedLinear, + T: BoundedLinear, + S::Codomain: Add, + >::Output: Space, + ExpA: NormExponent, + ExpB: NormExponent, + ExpR: NormExponent, { fn opnorm_bound( &self, - PairNorm(expa, expb, _) : PairNorm, - expr : ExpR + PairNorm(expa, expb, _): PairNorm, + expr: ExpR, ) -> F { // An application of the triangle inequality bounds the norm by the maximum // of the individual norms. A simple observation shows this to be exact. @@ -650,23 +695,22 @@ na.max(nb) } } - - impl - BoundedLinear, F> - for ColOp + + impl BoundedLinear, F> + for ColOp where - F : Float, - A : Space + Norm, - S : BoundedLinear, - T : BoundedLinear, - ExpA : NormExponent, - ExpS : NormExponent, - ExpT : NormExponent, + F: Float, + A: Space + Norm, + S: BoundedLinear, + T: BoundedLinear, + ExpA: NormExponent, + ExpS: NormExponent, + ExpT: NormExponent, { fn opnorm_bound( &self, - expa : ExpA, - PairNorm(exps, expt, _) : PairNorm + expa: ExpA, + PairNorm(exps, expt, _): PairNorm, ) -> F { // This is based on the rule for RowOp and ‖A^*‖ = ‖A‖, hence, // for A=[S; T], ‖A‖=‖[S^*, T^*]‖ ≤ max{‖S^*‖, ‖T^*‖} = max{‖S‖, ‖T‖} @@ -675,10 +719,9 @@ ns.max(nt) } } - } + }; } pairnorm!(L1); pairnorm!(L2); pairnorm!(Linfinity); -