github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/native/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 native 6 7 import ( 8 "math" 9 10 "github.com/gonum/blas" 11 "github.com/gonum/blas/blas64" 12 "github.com/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 checkMatrix(n, n, a, lda) 28 if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { 29 panic(badNorm) 30 } 31 if len(work) < 4*n { 32 panic(badWork) 33 } 34 if len(iwork) < n { 35 panic(badWork) 36 } 37 38 if n == 0 { 39 return 1 40 } else if anorm == 0 { 41 return 0 42 } 43 44 bi := blas64.Implementation() 45 var rcond, ainvnm float64 46 var kase int 47 var normin bool 48 isave := new([3]int) 49 onenrm := norm == lapack.MaxColumnSum 50 smlnum := dlamchS 51 kase1 := 2 52 if onenrm { 53 kase1 = 1 54 } 55 for { 56 ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) 57 if kase == 0 { 58 if ainvnm != 0 { 59 rcond = (1 / ainvnm) / anorm 60 } 61 return rcond 62 } 63 var sl, su float64 64 if kase == kase1 { 65 sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.Unit, normin, n, a, lda, work, work[2*n:]) 66 su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) 67 } else { 68 su = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) 69 sl = impl.Dlatrs(blas.Lower, blas.Trans, blas.Unit, normin, n, a, lda, work, work[2*n:]) 70 } 71 scale := sl * su 72 normin = true 73 if scale != 1 { 74 ix := bi.Idamax(n, work, 1) 75 if scale == 0 || scale < math.Abs(work[ix])*smlnum { 76 return rcond 77 } 78 impl.Drscl(n, scale, work, 1) 79 } 80 } 81 }