// Copyright ©2018 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 ( "gonum.org/v1/gonum/blas" "gonum.org/v1/gonum/blas/blas64" ) // Dlauum computes the product // U * U^T if uplo is blas.Upper // L^T * L if uplo is blas.Lower // where U or L is stored in the upper or lower triangular part of A. // Only the upper or lower triangle of the result is stored, overwriting // the corresponding factor in A. func (impl Implementation) Dlauum(uplo blas.Uplo, n int, a []float64, lda int) { switch { case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) case n < 0: panic(nLT0) case lda < max(1, n): panic(badLdA) } // Quick return if possible. if n == 0 { return } if len(a) < (n-1)*lda+n { panic(shortA) } // Determine the block size. opts := "U" if uplo == blas.Lower { opts = "L" } nb := impl.Ilaenv(1, "DLAUUM", opts, n, -1, -1, -1) if nb <= 1 || n <= nb { // Use unblocked code. impl.Dlauu2(uplo, n, a, lda) return } // Use blocked code. bi := blas64.Implementation() if uplo == blas.Upper { // Compute the product U*U^T. for i := 0; i < n; i += nb { ib := min(nb, n-i) bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.NonUnit, i, ib, 1, a[i*lda+i:], lda, a[i:], lda) impl.Dlauu2(blas.Upper, ib, a[i*lda+i:], lda) if n-i-ib > 0 { bi.Dgemm(blas.NoTrans, blas.Trans, i, ib, n-i-ib, 1, a[i+ib:], lda, a[i*lda+i+ib:], lda, 1, a[i:], lda) bi.Dsyrk(blas.Upper, blas.NoTrans, ib, n-i-ib, 1, a[i*lda+i+ib:], lda, 1, a[i*lda+i:], lda) } } } else { // Compute the product L^T*L. for i := 0; i < n; i += nb { ib := min(nb, n-i) bi.Dtrmm(blas.Left, blas.Lower, blas.Trans, blas.NonUnit, ib, i, 1, a[i*lda+i:], lda, a[i*lda:], lda) impl.Dlauu2(blas.Lower, ib, a[i*lda+i:], lda) if n-i-ib > 0 { bi.Dgemm(blas.Trans, blas.NoTrans, ib, i, n-i-ib, 1, a[(i+ib)*lda+i:], lda, a[(i+ib)*lda:], lda, 1, a[i*lda:], lda) bi.Dsyrk(blas.Lower, blas.Trans, ib, n-i-ib, 1, a[(i+ib)*lda+i:], lda, 1, a[i*lda+i:], lda) } } } }