mirror of
https://github.com/gonum/gonum.git
synced 2025-10-16 20:20:41 +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"
|
"gonum.org/v1/gonum/lapack"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dgecon estimates the reciprocal of the condition number of the n×n matrix A
|
// Dgecon estimates and returns the reciprocal of the condition number of the
|
||||||
// given the LU decomposition of the matrix. The condition number computed may
|
// n×n matrix A, in either the 1-norm or the ∞-norm, using the LU factorization
|
||||||
// be based on the 1-norm or the ∞-norm.
|
// 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
|
// rcond 1 / ( norm(A) * norm(A⁻¹) ).
|
||||||
// must be non-negative.
|
//
|
||||||
|
// 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,
|
// work must have length at least 4*n and iwork must have length at least n,
|
||||||
// otherwise Dgecon will panic.
|
// otherwise Dgecon will panic.
|
||||||
@@ -50,14 +56,14 @@ func (impl Implementation) Dgecon(norm lapack.MatrixNorm, n int, a []float64, ld
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Quick return if possible.
|
// Quick return if possible.
|
||||||
if anorm == 0 {
|
switch {
|
||||||
|
case anorm == 0:
|
||||||
return 0
|
return 0
|
||||||
}
|
case math.IsNaN(anorm):
|
||||||
if math.IsNaN(anorm) {
|
// Propagate NaN.
|
||||||
// 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.
|
|
||||||
return anorm
|
return anorm
|
||||||
|
case math.IsInf(anorm, 1):
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
bi := blas64.Implementation()
|
bi := blas64.Implementation()
|
||||||
|
@@ -6,6 +6,7 @@ package testlapack
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/exp/rand"
|
"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)",
|
t.Errorf("%v: unexpected value of rcond; got=%v, want=%v (ratio=%v)",
|
||||||
name, rcondGot, rcondWant, ratio)
|
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