github.com/gopherd/gonum@v0.0.4/lapack/gonum/dlantr.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/lapack"
    12  )
    13  
    14  // Dlantr computes the specified norm of an m×n trapezoidal matrix A. If
    15  // norm == lapack.MaxColumnSum work must have length at least n, otherwise work
    16  // is unused.
    17  func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 {
    18  	switch {
    19  	case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs:
    20  		panic(badNorm)
    21  	case uplo != blas.Upper && uplo != blas.Lower:
    22  		panic(badUplo)
    23  	case diag != blas.Unit && diag != blas.NonUnit:
    24  		panic(badDiag)
    25  	case m < 0:
    26  		panic(mLT0)
    27  	case n < 0:
    28  		panic(nLT0)
    29  	case lda < max(1, n):
    30  		panic(badLdA)
    31  	}
    32  
    33  	// Quick return if possible.
    34  	minmn := min(m, n)
    35  	if minmn == 0 {
    36  		return 0
    37  	}
    38  
    39  	switch {
    40  	case len(a) < (m-1)*lda+n:
    41  		panic(shortA)
    42  	case norm == lapack.MaxColumnSum && len(work) < n:
    43  		panic(shortWork)
    44  	}
    45  
    46  	switch norm {
    47  	case lapack.MaxAbs:
    48  		if diag == blas.Unit {
    49  			value := 1.0
    50  			if uplo == blas.Upper {
    51  				for i := 0; i < m; i++ {
    52  					for j := i + 1; j < n; j++ {
    53  						tmp := math.Abs(a[i*lda+j])
    54  						if math.IsNaN(tmp) {
    55  							return tmp
    56  						}
    57  						if tmp > value {
    58  							value = tmp
    59  						}
    60  					}
    61  				}
    62  				return value
    63  			}
    64  			for i := 1; i < m; i++ {
    65  				for j := 0; j < min(i, n); j++ {
    66  					tmp := math.Abs(a[i*lda+j])
    67  					if math.IsNaN(tmp) {
    68  						return tmp
    69  					}
    70  					if tmp > value {
    71  						value = tmp
    72  					}
    73  				}
    74  			}
    75  			return value
    76  		}
    77  		var value float64
    78  		if uplo == blas.Upper {
    79  			for i := 0; i < m; i++ {
    80  				for j := i; j < n; j++ {
    81  					tmp := math.Abs(a[i*lda+j])
    82  					if math.IsNaN(tmp) {
    83  						return tmp
    84  					}
    85  					if tmp > value {
    86  						value = tmp
    87  					}
    88  				}
    89  			}
    90  			return value
    91  		}
    92  		for i := 0; i < m; i++ {
    93  			for j := 0; j <= min(i, n-1); j++ {
    94  				tmp := math.Abs(a[i*lda+j])
    95  				if math.IsNaN(tmp) {
    96  					return tmp
    97  				}
    98  				if tmp > value {
    99  					value = tmp
   100  				}
   101  			}
   102  		}
   103  		return value
   104  	case lapack.MaxColumnSum:
   105  		if diag == blas.Unit {
   106  			for i := 0; i < minmn; i++ {
   107  				work[i] = 1
   108  			}
   109  			for i := minmn; i < n; i++ {
   110  				work[i] = 0
   111  			}
   112  			if uplo == blas.Upper {
   113  				for i := 0; i < m; i++ {
   114  					for j := i + 1; j < n; j++ {
   115  						work[j] += math.Abs(a[i*lda+j])
   116  					}
   117  				}
   118  			} else {
   119  				for i := 1; i < m; i++ {
   120  					for j := 0; j < min(i, n); j++ {
   121  						work[j] += math.Abs(a[i*lda+j])
   122  					}
   123  				}
   124  			}
   125  		} else {
   126  			for i := 0; i < n; i++ {
   127  				work[i] = 0
   128  			}
   129  			if uplo == blas.Upper {
   130  				for i := 0; i < m; i++ {
   131  					for j := i; j < n; j++ {
   132  						work[j] += math.Abs(a[i*lda+j])
   133  					}
   134  				}
   135  			} else {
   136  				for i := 0; i < m; i++ {
   137  					for j := 0; j <= min(i, n-1); j++ {
   138  						work[j] += math.Abs(a[i*lda+j])
   139  					}
   140  				}
   141  			}
   142  		}
   143  		var max float64
   144  		for _, v := range work[:n] {
   145  			if math.IsNaN(v) {
   146  				return math.NaN()
   147  			}
   148  			if v > max {
   149  				max = v
   150  			}
   151  		}
   152  		return max
   153  	case lapack.MaxRowSum:
   154  		var maxsum float64
   155  		if diag == blas.Unit {
   156  			if uplo == blas.Upper {
   157  				for i := 0; i < m; i++ {
   158  					var sum float64
   159  					if i < minmn {
   160  						sum = 1
   161  					}
   162  					for j := i + 1; j < n; j++ {
   163  						sum += math.Abs(a[i*lda+j])
   164  					}
   165  					if math.IsNaN(sum) {
   166  						return math.NaN()
   167  					}
   168  					if sum > maxsum {
   169  						maxsum = sum
   170  					}
   171  				}
   172  				return maxsum
   173  			} else {
   174  				for i := 0; i < m; i++ {
   175  					var sum float64
   176  					if i < minmn {
   177  						sum = 1
   178  					}
   179  					for j := 0; j < min(i, n); j++ {
   180  						sum += math.Abs(a[i*lda+j])
   181  					}
   182  					if math.IsNaN(sum) {
   183  						return math.NaN()
   184  					}
   185  					if sum > maxsum {
   186  						maxsum = sum
   187  					}
   188  				}
   189  				return maxsum
   190  			}
   191  		} else {
   192  			if uplo == blas.Upper {
   193  				for i := 0; i < m; i++ {
   194  					var sum float64
   195  					for j := i; j < n; j++ {
   196  						sum += math.Abs(a[i*lda+j])
   197  					}
   198  					if math.IsNaN(sum) {
   199  						return sum
   200  					}
   201  					if sum > maxsum {
   202  						maxsum = sum
   203  					}
   204  				}
   205  				return maxsum
   206  			} else {
   207  				for i := 0; i < m; i++ {
   208  					var sum float64
   209  					for j := 0; j <= min(i, n-1); j++ {
   210  						sum += math.Abs(a[i*lda+j])
   211  					}
   212  					if math.IsNaN(sum) {
   213  						return sum
   214  					}
   215  					if sum > maxsum {
   216  						maxsum = sum
   217  					}
   218  				}
   219  				return maxsum
   220  			}
   221  		}
   222  	default:
   223  		// lapack.Frobenius:
   224  		var scale, sum float64
   225  		if diag == blas.Unit {
   226  			scale = 1
   227  			sum = float64(min(m, n))
   228  			if uplo == blas.Upper {
   229  				for i := 0; i < min(m, n); i++ {
   230  					scale, sum = impl.Dlassq(n-i-1, a[i*lda+i+1:], 1, scale, sum)
   231  				}
   232  			} else {
   233  				for i := 1; i < m; i++ {
   234  					scale, sum = impl.Dlassq(min(i, n), a[i*lda:], 1, scale, sum)
   235  				}
   236  			}
   237  		} else {
   238  			scale = 0
   239  			sum = 1
   240  			if uplo == blas.Upper {
   241  				for i := 0; i < min(m, n); i++ {
   242  					scale, sum = impl.Dlassq(n-i, a[i*lda+i:], 1, scale, sum)
   243  				}
   244  			} else {
   245  				for i := 0; i < m; i++ {
   246  					scale, sum = impl.Dlassq(min(i+1, n), a[i*lda:], 1, scale, sum)
   247  				}
   248  			}
   249  		}
   250  		return scale * math.Sqrt(sum)
   251  	}
   252  }