src/linops.rs

branch
dev
changeset 110
a1278320be26
parent 104
e7f1cb4bec78
child 124
6aa955ad8122
--- a/src/linops.rs	Wed Apr 30 01:06:25 2025 -0500
+++ b/src/linops.rs	Wed Apr 30 16:39:01 2025 -0500
@@ -3,6 +3,7 @@
 */
 
 use crate::direct_product::Pair;
+use crate::error::DynResult;
 use crate::instance::Instance;
 pub use crate::mapping::{Composition, DifferentiableImpl, Mapping, Space};
 use crate::norms::{Linfinity, Norm, NormExponent, PairNorm, L1, L2};
@@ -84,7 +85,9 @@
     /// 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;
+    ///
+    /// This may fail with an error if the bound is for some reason incalculable.
+    fn opnorm_bound(&self, xexp: XExp, codexp: CodExp) -> DynResult<F>;
 }
 
 // Linear operator application into mutable target. The [`AsRef`] bound
@@ -183,8 +186,8 @@
     F: Num,
     E: NormExponent,
 {
-    fn opnorm_bound(&self, _xexp: E, _codexp: E) -> F {
-        F::ONE
+    fn opnorm_bound(&self, _xexp: E, _codexp: E) -> DynResult<F> {
+        Ok(F::ONE)
     }
 }
 
@@ -267,8 +270,8 @@
     E1: NormExponent,
     E2: NormExponent,
 {
-    fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> F {
-        F::ZERO
+    fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult<F> {
+        Ok(F::ZERO)
     }
 }
 
@@ -351,9 +354,9 @@
     T: BoundedLinear<X, Xexp, Zexp, F, Codomain = Z>,
     S: BoundedLinear<Z, Zexp, Yexp, F>,
 {
-    fn opnorm_bound(&self, xexp: Xexp, yexp: Yexp) -> F {
+    fn opnorm_bound(&self, xexp: Xexp, yexp: Yexp) -> DynResult<F> {
         let zexp = self.intermediate_norm_exponent;
-        self.outer.opnorm_bound(zexp, yexp) * self.inner.opnorm_bound(xexp, zexp)
+        Ok(self.outer.opnorm_bound(zexp, yexp)? * self.inner.opnorm_bound(xexp, zexp)?)
     }
 }
 
@@ -691,12 +694,12 @@
                 &self,
                 PairNorm(expa, expb, _): PairNorm<ExpA, ExpB, $expj>,
                 expr: ExpR,
-            ) -> F {
+            ) -> DynResult<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.
-                let na = self.0.opnorm_bound(expa, expr);
-                let nb = self.1.opnorm_bound(expb, expr);
-                na.max(nb)
+                let na = self.0.opnorm_bound(expa, expr)?;
+                let nb = self.1.opnorm_bound(expb, expr)?;
+                Ok(na.max(nb))
             }
         }
 
@@ -715,12 +718,12 @@
                 &self,
                 expa: ExpA,
                 PairNorm(exps, expt, _): PairNorm<ExpS, ExpT, $expj>,
-            ) -> F {
+            ) -> DynResult<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‖}
-                let ns = self.0.opnorm_bound(expa, exps);
-                let nt = self.1.opnorm_bound(expa, expt);
-                ns.max(nt)
+                let ns = self.0.opnorm_bound(expa, exps)?;
+                let nt = self.1.opnorm_bound(expa, expt)?;
+                Ok(ns.max(nt))
             }
         }
     };

mercurial