// 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 native import ( "math" "gonum.org/v1/gonum/blas" "gonum.org/v1/gonum/lapack" ) // Dlansy computes the specified norm of an n×n symmetric matrix. If // norm == lapack.MaxColumnSum or norm == lapackMaxRowSum work must have length // at least n, otherwise work is unused. func (impl Implementation) Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 { checkMatrix(n, n, a, lda) switch norm { case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: default: panic(badNorm) } if (norm == lapack.MaxColumnSum || norm == lapack.MaxRowSum) && len(work) < n { panic(badWork) } if uplo != blas.Upper && uplo != blas.Lower { panic(badUplo) } if n == 0 { return 0 } switch norm { default: panic("unreachable") case lapack.MaxAbs: if uplo == blas.Upper { var max float64 for i := 0; i < n; i++ { for j := i; j < n; j++ { v := math.Abs(a[i*lda+j]) if math.IsNaN(v) { return math.NaN() } if v > max { max = v } } } return max } var max float64 for i := 0; i < n; i++ { for j := 0; j <= i; j++ { v := math.Abs(a[i*lda+j]) if math.IsNaN(v) { return math.NaN() } if v > max { max = v } } } return max case lapack.MaxRowSum, lapack.MaxColumnSum: // A symmetric matrix has the same 1-norm and ∞-norm. for i := 0; i < n; i++ { work[i] = 0 } if uplo == blas.Upper { for i := 0; i < n; i++ { work[i] += math.Abs(a[i*lda+i]) for j := i + 1; j < n; j++ { v := math.Abs(a[i*lda+j]) work[i] += v work[j] += v } } } else { for i := 0; i < n; i++ { for j := 0; j < i; j++ { v := math.Abs(a[i*lda+j]) work[i] += v work[j] += v } work[i] += math.Abs(a[i*lda+i]) } } var max float64 for i := 0; i < n; i++ { v := work[i] if math.IsNaN(v) { return math.NaN() } if v > max { max = v } } return max case lapack.NormFrob: if uplo == blas.Upper { var sum float64 for i := 0; i < n; i++ { v := a[i*lda+i] sum += v * v for j := i + 1; j < n; j++ { v := a[i*lda+j] sum += 2 * v * v } } return math.Sqrt(sum) } var sum float64 for i := 0; i < n; i++ { for j := 0; j < i; j++ { v := a[i*lda+j] sum += 2 * v * v } v := a[i*lda+i] sum += v * v } return math.Sqrt(sum) } }