github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/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/jingcheng-WU/gonum/blas"
    11  	"github.com/jingcheng-WU/gonum/blas/blas64"
    12  	"github.com/jingcheng-WU/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  }