mirror of
https://github.com/gonum/gonum.git
synced 2025-10-16 12:10:37 +08:00
lapack/gonum: handle NaN and Inf input to Dgecon
See https://github.com/Reference-LAPACK/lapack/pull/926
This commit is contained in:

committed by
Vladimír Chalupecký

parent
db43f45c2b
commit
fa306f215a
@@ -12,14 +12,20 @@ import (
|
||||
"gonum.org/v1/gonum/lapack"
|
||||
)
|
||||
|
||||
// Dgecon estimates the reciprocal of the condition number of the n×n matrix A
|
||||
// given the LU decomposition of the matrix. The condition number computed may
|
||||
// be based on the 1-norm or the ∞-norm.
|
||||
// Dgecon estimates and returns the reciprocal of the condition number of the
|
||||
// n×n matrix A, in either the 1-norm or the ∞-norm, using the LU factorization
|
||||
// computed by Dgetrf.
|
||||
//
|
||||
// The slice a contains the result of the LU decomposition of A as computed by Dgetrf.
|
||||
// An estimate is obtained for norm(A⁻¹), and the reciprocal of the condition
|
||||
// number rcond is computed as
|
||||
//
|
||||
// anorm is the corresponding 1-norm or ∞-norm of the original matrix A. anorm
|
||||
// must be non-negative.
|
||||
// rcond 1 / ( norm(A) * norm(A⁻¹) ).
|
||||
//
|
||||
// If n is zero, rcond is always 1.
|
||||
//
|
||||
// anorm is the 1-norm or the ∞-norm of the original matrix A. anorm must be
|
||||
// non-negative, otherwise Dgecon will panic. If anorm is 0 or infinity, Dgecon
|
||||
// returns 0. If anorm is NaN, Dgecon returns NaN.
|
||||
//
|
||||
// work must have length at least 4*n and iwork must have length at least n,
|
||||
// otherwise Dgecon will panic.
|
||||
@@ -50,14 +56,14 @@ func (impl Implementation) Dgecon(norm lapack.MatrixNorm, n int, a []float64, ld
|
||||
}
|
||||
|
||||
// Quick return if possible.
|
||||
if anorm == 0 {
|
||||
switch {
|
||||
case anorm == 0:
|
||||
return 0
|
||||
}
|
||||
if math.IsNaN(anorm) {
|
||||
// The reference implementation treats the NaN anorm as invalid and
|
||||
// returns an error code. Our error handling is to panic which seems too
|
||||
// harsh for a runtime condition, so we just propagate the NaN instead.
|
||||
case math.IsNaN(anorm):
|
||||
// Propagate NaN.
|
||||
return anorm
|
||||
case math.IsInf(anorm, 1):
|
||||
return 0
|
||||
}
|
||||
|
||||
bi := blas64.Implementation()
|
||||
|
@@ -6,6 +6,7 @@ package testlapack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/exp/rand"
|
||||
@@ -87,5 +88,25 @@ func dgeconTest(t *testing.T, impl Dgeconer, rnd *rand.Rand, n, lda int) {
|
||||
t.Errorf("%v: unexpected value of rcond; got=%v, want=%v (ratio=%v)",
|
||||
name, rcondGot, rcondWant, ratio)
|
||||
}
|
||||
|
||||
// Check for corner-case values of anorm.
|
||||
for _, anorm := range []float64{0, math.Inf(1), math.NaN()} {
|
||||
rcondGot = impl.Dgecon(norm, n, aFac, lda, anorm, work, iwork)
|
||||
if n == 0 {
|
||||
if rcondGot != 1 {
|
||||
t.Errorf("%v: unexpected rcond when anorm=%v: got=%v, want=1", name, anorm, rcondGot)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if math.IsNaN(anorm) {
|
||||
if !math.IsNaN(rcondGot) {
|
||||
t.Errorf("%v: NaN not propagated when anorm=NaN: got=%v", name, rcondGot)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if rcondGot != 0 {
|
||||
t.Errorf("%v: unexpected rcond when anorm=%v: got=%v, want=0", name, anorm, rcondGot)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user