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