pub fn is_good_approx_of_mul(&self, lhs: &Self, rhs: &Self) -> Result<bool, IsNan> {
        let inf_norm = |m: &DokMatrix<f64>| {
            let mut max = 0.0;
            for rsum in (0..m.rows().get()).map(|r| {
                m.entries
                    .range((r, 0)..(r + 1, 0))
                    .map(|(_, t)| t.abs())
                    .sum::<f64>()
            }) {
                if rsum.is_nan() {
                    return Err(IsNan);
                } else if rsum > max {
                    max = rsum;
                }
            }
            Ok(max)
        };
        let n = f64::value_from(self.cols().get()).unwrap();
        let u = f64::EPSILON / 2.0;
        let gamma = n * u / (1.0 - n * u);
        let expected = lhs * rhs;
        if expected.iter().all(|(_, t)| !t.is_nan()) && self.iter().any(|(_, t)| t.is_nan()) {
            Ok(false)
        } else {
            let lhs_norm = inf_norm(lhs)?;
            let rhs_norm = inf_norm(rhs)?;
            Ok(inf_norm(&(expected - self.clone()))?
                <= 2.0
                    * gamma
                    * if lhs_norm == 0.0 || rhs_norm == 0.0 {
                        // don't want 0.0*inf to become NaN
                        0.0
                    } else {
                        lhs_norm * rhs_norm
                    })
        }
    }
// see (3.13) from Accuracy and stability of numerical algorithms by Higham
see (3.13) from Accuracy and stability of numerical algorithms by Higham
see ( 3 . 13 ) from Accuracy and stability of numerical algorithms by Higham
pub fn is_good_approx_of_mul(&self, lhs: &Self, rhs: &Self) -> Result<bool, IsNan> {
        let inf_norm = |m: &DokMatrix<f64>| {
            let mut max = 0.0;
            for rsum in (0..m.rows().get()).map(|r| {
                m.entries
                    .range((r, 0)..(r + 1, 0))
                    .map(|(_, t)| t.abs())
                    .sum::<f64>()
            }) {
                if rsum.is_nan() {
                    return Err(IsNan);
                } else if rsum > max {
                    max = rsum;
                }
            }
            Ok(max)
        };
        let n = f64::value_from(self.cols().get()).unwrap();
        let u = f64::EPSILON / 2.0;
        let gamma = n * u / (1.0 - n * u);
        let expected = lhs * rhs;
        if expected.iter().all(|(_, t)| !t.is_nan()) && self.iter().any(|(_, t)| t.is_nan()) {
            Ok(false)
        } else {
            let lhs_norm = inf_norm(lhs)?;
            let rhs_norm = inf_norm(rhs)?;
            Ok(inf_norm(&(expected - self.clone()))?
                <= 2.0
                    * gamma
                    * if lhs_norm == 0.0 || rhs_norm == 0.0 {
                        // don't want 0.0*inf to become NaN
                        0.0
                    } else {
                        lhs_norm * rhs_norm
                    })
        }
    }
pub fn is_good_approx_of_mul ( & self , lhs : & Self , rhs : & Self ) -> Result < bool , IsNan > { let inf_norm = | m : & DokMatrix < f64 > | { let mut max = 0.0 ; for rsum in ( 0 .. m . rows ( ) . get ( ) ) . map ( | r | { m . entries . range ( ( r , 0 ) .. ( r + 1 , 0 ) ) . map ( | ( _ , t ) | t . abs ( ) ) . sum :: < f64 > ( ) } ) { if rsum . is_nan ( ) { return Err ( IsNan ) ; } else if rsum > max { max = rsum ; } } Ok ( max ) } ; let n = f64 :: value_from ( self . cols ( ) . get ( ) ) . unwrap ( ) ; let u = f64 :: EPSILON / 2.0 ; let gamma = n * u / ( 1.0 - n * u ) ; let expected = lhs * rhs ; if expected . iter ( ) . all ( | ( _ , t ) | ! t . is_nan ( ) ) && self . iter ( ) . any ( | ( _ , t ) | t . is_nan ( ) ) { Ok ( false ) } else { let lhs_norm = inf_norm ( lhs ) ? ; let rhs_norm = inf_norm ( rhs ) ? ; Ok ( inf_norm ( & ( expected - self . clone ( ) ) ) ? <= 2.0 * gamma * if lhs_norm == 0.0 || rhs_norm == 0.0 { // don't want 0.0*inf to become NaN 0.0 } else { lhs_norm * rhs_norm } ) } }
see (3.13) from Accuracy and stability of numerical algorithms by Higham
see ( 3 . 13 ) from Accuracy and stability of numerical algorithms by Higham
&self
lhs
&Self
rhs
&Self
&self
lhs
&Self
rhs
&Self