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 }