diff --git a/math-lib/math/private/matrix/matrix-basic.rkt b/math-lib/math/private/matrix/matrix-basic.rkt index cc024b9..3ead762 100644 --- a/math-lib/math/private/matrix/matrix-basic.rkt +++ b/math-lib/math/private/matrix/matrix-basic.rkt @@ -229,11 +229,11 @@ (define (matrix-2norm M) (parameterize ([array-strictness #f]) (let ([M (array-strict (inline-array-map nonstupid-magnitude M))]) - ;; Compute this divided by the maximum to avoid underflow and overflow - (define mx (array-all-max M)) - (cond [(and (rational? mx) (positive? mx)) - (* mx (sqrt (array-all-sum (inline-array-map (λ (x) (sqr (/ x mx))) M))))] - [else mx])))) + (cond + [(array-all-and (inline-array-map exact? M)) + (sqrt (array-all-sum (inline-array-map sqr M)))] + [else + (array-all-fold (inline-array-map fl M) flhypot 0.0)])))) (: matrix-inf-norm (case-> ((Matrix Flonum) -> Nonnegative-Flonum) ((Matrix Real) -> Nonnegative-Real) diff --git a/math-test/math/tests/matrix-tests.rkt b/math-test/math/tests/matrix-tests.rkt index bbb92aa..b32e67b 100644 --- a/math-test/math/tests/matrix-tests.rkt +++ b/math-test/math/tests/matrix-tests.rkt @@ -641,6 +641,13 @@ (check-equal? (matrix-norm (matrix [[1e200 1e199]])) (flhypot 1e200 1e199)) +;; Mixed exact and inexact entries use the flonum hypot path. +(check-equal? (matrix-norm (matrix [[1 2.0]])) + (flhypot 1.0 2.0)) + +;; A NaN entry should propagate through the flonum hypot path. +(check-true (nan? (matrix-norm (matrix [[+nan.0]])))) + ;; Taxicab (Manhattan) norm (check-equal? (matrix-norm (matrix [[1 2 3] [4 5 6]]) 1) (+ 1 2 3 4 5 6))