--- /dev/null
+// Copyright ©2015 The Gonum Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gonum
+
+import (
+ "math"
+
+ "gonum.org/v1/gonum/blas"
+ "gonum.org/v1/gonum/lapack"
+)
+
+// Dlantr computes the specified norm of an m×n trapezoidal matrix A. If
+// norm == lapack.MaxColumnSum work must have length at least n, otherwise work
+// is unused.
+func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 {
+ checkMatrix(m, n, a, lda)
+ switch norm {
+ case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs:
+ default:
+ panic(badNorm)
+ }
+ if uplo != blas.Upper && uplo != blas.Lower {
+ panic(badUplo)
+ }
+ if diag != blas.Unit && diag != blas.NonUnit {
+ panic(badDiag)
+ }
+ if norm == lapack.MaxColumnSum && len(work) < n {
+ panic(badWork)
+ }
+ if min(m, n) == 0 {
+ return 0
+ }
+ switch norm {
+ default:
+ panic("unreachable")
+ case lapack.MaxAbs:
+ if diag == blas.Unit {
+ value := 1.0
+ if uplo == blas.Upper {
+ for i := 0; i < m; i++ {
+ for j := i + 1; j < n; j++ {
+ tmp := math.Abs(a[i*lda+j])
+ if math.IsNaN(tmp) {
+ return tmp
+ }
+ if tmp > value {
+ value = tmp
+ }
+ }
+ }
+ return value
+ }
+ for i := 1; i < m; i++ {
+ for j := 0; j < min(i, n); j++ {
+ tmp := math.Abs(a[i*lda+j])
+ if math.IsNaN(tmp) {
+ return tmp
+ }
+ if tmp > value {
+ value = tmp
+ }
+ }
+ }
+ return value
+ }
+ var value float64
+ if uplo == blas.Upper {
+ for i := 0; i < m; i++ {
+ for j := i; j < n; j++ {
+ tmp := math.Abs(a[i*lda+j])
+ if math.IsNaN(tmp) {
+ return tmp
+ }
+ if tmp > value {
+ value = tmp
+ }
+ }
+ }
+ return value
+ }
+ for i := 0; i < m; i++ {
+ for j := 0; j <= min(i, n-1); j++ {
+ tmp := math.Abs(a[i*lda+j])
+ if math.IsNaN(tmp) {
+ return tmp
+ }
+ if tmp > value {
+ value = tmp
+ }
+ }
+ }
+ return value
+ case lapack.MaxColumnSum:
+ if diag == blas.Unit {
+ for i := 0; i < min(m, n); i++ {
+ work[i] = 1
+ }
+ for i := min(m, n); i < n; i++ {
+ work[i] = 0
+ }
+ if uplo == blas.Upper {
+ for i := 0; i < m; i++ {
+ for j := i + 1; j < n; j++ {
+ work[j] += math.Abs(a[i*lda+j])
+ }
+ }
+ } else {
+ for i := 1; i < m; i++ {
+ for j := 0; j < min(i, n); j++ {
+ work[j] += math.Abs(a[i*lda+j])
+ }
+ }
+ }
+ } else {
+ for i := 0; i < n; i++ {
+ work[i] = 0
+ }
+ if uplo == blas.Upper {
+ for i := 0; i < m; i++ {
+ for j := i; j < n; j++ {
+ work[j] += math.Abs(a[i*lda+j])
+ }
+ }
+ } else {
+ for i := 0; i < m; i++ {
+ for j := 0; j <= min(i, n-1); j++ {
+ work[j] += math.Abs(a[i*lda+j])
+ }
+ }
+ }
+ }
+ var max float64
+ for _, v := range work[:n] {
+ if math.IsNaN(v) {
+ return math.NaN()
+ }
+ if v > max {
+ max = v
+ }
+ }
+ return max
+ case lapack.MaxRowSum:
+ var maxsum float64
+ if diag == blas.Unit {
+ if uplo == blas.Upper {
+ for i := 0; i < m; i++ {
+ var sum float64
+ if i < min(m, n) {
+ sum = 1
+ }
+ for j := i + 1; j < n; j++ {
+ sum += math.Abs(a[i*lda+j])
+ }
+ if math.IsNaN(sum) {
+ return math.NaN()
+ }
+ if sum > maxsum {
+ maxsum = sum
+ }
+ }
+ return maxsum
+ } else {
+ for i := 1; i < m; i++ {
+ var sum float64
+ if i < min(m, n) {
+ sum = 1
+ }
+ for j := 0; j < min(i, n); j++ {
+ sum += math.Abs(a[i*lda+j])
+ }
+ if math.IsNaN(sum) {
+ return math.NaN()
+ }
+ if sum > maxsum {
+ maxsum = sum
+ }
+ }
+ return maxsum
+ }
+ } else {
+ if uplo == blas.Upper {
+ for i := 0; i < m; i++ {
+ var sum float64
+ for j := i; j < n; j++ {
+ sum += math.Abs(a[i*lda+j])
+ }
+ if math.IsNaN(sum) {
+ return sum
+ }
+ if sum > maxsum {
+ maxsum = sum
+ }
+ }
+ return maxsum
+ } else {
+ for i := 0; i < m; i++ {
+ var sum float64
+ for j := 0; j <= min(i, n-1); j++ {
+ sum += math.Abs(a[i*lda+j])
+ }
+ if math.IsNaN(sum) {
+ return sum
+ }
+ if sum > maxsum {
+ maxsum = sum
+ }
+ }
+ return maxsum
+ }
+ }
+ case lapack.NormFrob:
+ var nrm float64
+ if diag == blas.Unit {
+ if uplo == blas.Upper {
+ for i := 0; i < m; i++ {
+ for j := i + 1; j < n; j++ {
+ tmp := a[i*lda+j]
+ nrm += tmp * tmp
+ }
+ }
+ } else {
+ for i := 1; i < m; i++ {
+ for j := 0; j < min(i, n); j++ {
+ tmp := a[i*lda+j]
+ nrm += tmp * tmp
+ }
+ }
+ }
+ nrm += float64(min(m, n))
+ } else {
+ if uplo == blas.Upper {
+ for i := 0; i < m; i++ {
+ for j := i; j < n; j++ {
+ tmp := math.Abs(a[i*lda+j])
+ nrm += tmp * tmp
+ }
+ }
+ } else {
+ for i := 0; i < m; i++ {
+ for j := 0; j <= min(i, n-1); j++ {
+ tmp := math.Abs(a[i*lda+j])
+ nrm += tmp * tmp
+ }
+ }
+ }
+ }
+ return math.Sqrt(nrm)
+ }
+}