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  }