Mon, 23 Feb 2026 18:18:02 -0500
ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
/*! Preadjoint construction helper */ use alg_tools::error::DynResult; pub use alg_tools::linops::*; use alg_tools::norms::{HasDualExponent, Norm}; use alg_tools::types::*; use std::marker::PhantomData; /// Helper structure for constructing preadjoints of `S` where `S : Linear<X>`. /// [`Linear`] needs to be implemented for each instance, but [`Adjointable`] /// and [`BoundedLinear`] have blanket implementations. #[derive(Clone, Debug)] pub struct PreadjointHelper<'a, S: 'a, X> { pub forward_op: &'a S, _domain: PhantomData<X>, } impl<'a, S: 'a, X> PreadjointHelper<'a, S, X> { pub fn new(forward_op: &'a S) -> Self { PreadjointHelper { forward_op, _domain: PhantomData, } } } impl<'a, X, Ypre, S> Adjointable<Ypre, X> for PreadjointHelper<'a, S, X> where X: Space, Ypre: Space, Self: Linear<Ypre>, S: Clone + Linear<X>, { type AdjointCodomain = S::Codomain; type Adjoint<'b> = S where Self: 'b; fn adjoint(&self) -> Self::Adjoint<'_> { self.forward_op.clone() } } impl<'a, F, X, Ypre, ExpXpre, ExpYpre, S> BoundedLinear<Ypre, ExpYpre, ExpXpre, F> for PreadjointHelper<'a, S, X> where ExpXpre: HasDualExponent, ExpYpre: HasDualExponent, F: Float, X: Space + Norm<ExpXpre::DualExp, F>, Ypre: Space + Norm<ExpYpre, F>, Self: Linear<Ypre>, S: 'a + Clone + BoundedLinear<X, ExpXpre::DualExp, ExpYpre::DualExp, F>, { fn opnorm_bound(&self, expy: ExpYpre, expx: ExpXpre) -> DynResult<F> { self.forward_op .opnorm_bound(expx.dual_exponent(), expy.dual_exponent()) } }