github.com/gopherd/gonum@v0.0.4/lapack/gonum/dgecon.go (about) 1 // Copyright ©2015 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gonum 6 7 import ( 8 "math" 9 10 "github.com/gopherd/gonum/blas" 11 "github.com/gopherd/gonum/blas/blas64" 12 "github.com/gopherd/gonum/lapack" 13 ) 14 15 // Dgecon estimates the reciprocal of the condition number of the n×n matrix A 16 // given the LU decomposition of the matrix. The condition number computed may 17 // be based on the 1-norm or the ∞-norm. 18 // 19 // The slice a contains the result of the LU decomposition of A as computed by Dgetrf. 20 // 21 // anorm is the corresponding 1-norm or ∞-norm of the original matrix A. 22 // 23 // work is a temporary data slice of length at least 4*n and Dgecon will panic otherwise. 24 // 25 // iwork is a temporary data slice of length at least n and Dgecon will panic otherwise. 26 func (impl Implementation) Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { 27 switch { 28 case norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum: 29 panic(badNorm) 30 case n < 0: 31 panic(nLT0) 32 case lda < max(1, n): 33 panic(badLdA) 34 } 35 36 // Quick return if possible. 37 if n == 0 { 38 return 1 39 } 40 41 switch { 42 case len(a) < (n-1)*lda+n: 43 panic(shortA) 44 case len(work) < 4*n: 45 panic(shortWork) 46 case len(iwork) < n: 47 panic(shortIWork) 48 } 49 50 // Quick return if possible. 51 if anorm == 0 { 52 return 0 53 } 54 55 bi := blas64.Implementation() 56 var rcond, ainvnm float64 57 var kase int 58 var normin bool 59 isave := new([3]int) 60 onenrm := norm == lapack.MaxColumnSum 61 smlnum := dlamchS 62 kase1 := 2 63 if onenrm { 64 kase1 = 1 65 } 66 for { 67 ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) 68 if kase == 0 { 69 if ainvnm != 0 { 70 rcond = (1 / ainvnm) / anorm 71 } 72 return rcond 73 } 74 var sl, su float64 75 if kase == kase1 { 76 sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.Unit, normin, n, a, lda, work, work[2*n:]) 77 su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) 78 } else { 79 su = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) 80 sl = impl.Dlatrs(blas.Lower, blas.Trans, blas.Unit, normin, n, a, lda, work, work[2*n:]) 81 } 82 scale := sl * su 83 normin = true 84 if scale != 1 { 85 ix := bi.Idamax(n, work, 1) 86 if scale == 0 || scale < math.Abs(work[ix])*smlnum { 87 return rcond 88 } 89 impl.Drscl(n, scale, work, 1) 90 } 91 } 92 }