mirror of
https://github.com/gonum/gonum.git
synced 2025-10-24 15:43:07 +08:00
Improved function documentation Fixed dlarfb and dlarft and added full tests Added dgelq2 Working Dgels Fix many comments and tests Many PR comment responses Responded to more PR comments Many PR comments
140 lines
3.7 KiB
Go
140 lines
3.7 KiB
Go
// 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 (
|
||
"github.com/gonum/blas"
|
||
"github.com/gonum/lapack"
|
||
)
|
||
|
||
// Dormqr multiplies the matrix c by the othogonal matrix q defined by the
|
||
// slices a and tau. A and tau are as returned from Dgeqrf.
|
||
// C = Q * C if side == blas.Left and trans == blas.NoTrans
|
||
// C = Q^T * C if side == blas.Left and trans == blas.Trans
|
||
// C = C * Q if side == blas.Right and trans == blas.NoTrans
|
||
// C = C * Q^T if side == blas.Right and trans == blas.Trans
|
||
// If side == blas.Left, a is a matrix of side k×m, and if side == blas.Right
|
||
// a is of size k×n. This uses a blocked algorithm.
|
||
//
|
||
// Work is temporary storage, and lwork specifies the usable memory length.
|
||
// At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right,
|
||
// and this function will panic otherwise.
|
||
// Dormqr uses a block algorithm, but the block size is limited
|
||
// by the temporary space available. If lwork == -1, instead of performing Dormqr,
|
||
// the optimal work length will be stored into work[0].
|
||
//
|
||
// Tau contains the householder scales and must have length at least k, and
|
||
// this function will panic otherwise.
|
||
func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) {
|
||
left := side == blas.Left
|
||
notran := trans == blas.NoTrans
|
||
if left {
|
||
checkMatrix(m, k, a, lda)
|
||
} else {
|
||
checkMatrix(n, k, a, lda)
|
||
}
|
||
checkMatrix(m, n, c, ldc)
|
||
|
||
const nbmax = 64
|
||
nw := n
|
||
if side == blas.Right {
|
||
nw = m
|
||
}
|
||
opts := string(side) + string(trans)
|
||
nb := min(nbmax, impl.Ilaenv(1, "DORMQR", opts, m, n, k, -1))
|
||
lworkopt := max(1, nw) * nb
|
||
if lwork == -1 {
|
||
work[0] = float64(lworkopt)
|
||
return
|
||
}
|
||
if left {
|
||
if lwork < n {
|
||
panic(badWork)
|
||
}
|
||
} else {
|
||
if lwork < m {
|
||
panic(badWork)
|
||
}
|
||
}
|
||
if m == 0 || n == 0 || k == 0 {
|
||
return
|
||
}
|
||
nbmin := 2
|
||
|
||
ldwork := nb
|
||
if nb > 1 && nb < k {
|
||
iws := nw * nb
|
||
if lwork < iws {
|
||
nb = lwork / nw
|
||
nbmin = max(2, impl.Ilaenv(2, "DORMQR", opts, m, n, k, -1))
|
||
}
|
||
}
|
||
if nb < nbmin || nb >= k {
|
||
// Call unblocked code
|
||
impl.Dorm2r(side, trans, m, n, k, a, lda, tau, c, ldc, work)
|
||
return
|
||
}
|
||
ldt := nb
|
||
t := make([]float64, nb*ldt)
|
||
switch {
|
||
case left && notran:
|
||
for i := ((k - 1) / nb) * nb; i >= 0; i -= nb {
|
||
ib := min(nb, k-i)
|
||
impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib,
|
||
a[i*lda+i:], lda,
|
||
tau[i:],
|
||
t, ldt)
|
||
impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m-i, n, ib,
|
||
a[i*lda+i:], lda,
|
||
t, ldt,
|
||
c[i*ldc:], ldc,
|
||
work, ldwork)
|
||
}
|
||
return
|
||
case left && !notran:
|
||
for i := 0; i < k; i += nb {
|
||
ib := min(nb, k-i)
|
||
impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib,
|
||
a[i*lda+i:], lda,
|
||
tau[i:],
|
||
t, ldt)
|
||
impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m-i, n, ib,
|
||
a[i*lda+i:], lda,
|
||
t, ldt,
|
||
c[i*ldc:], ldc,
|
||
work, ldwork)
|
||
}
|
||
return
|
||
case !left && notran:
|
||
for i := 0; i < k; i += nb {
|
||
ib := min(nb, k-i)
|
||
impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib,
|
||
a[i*lda+i:], lda,
|
||
tau[i:],
|
||
t, ldt)
|
||
impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m, n-i, ib,
|
||
a[i*lda+i:], lda,
|
||
t, ldt,
|
||
c[i:], ldc,
|
||
work, ldwork)
|
||
}
|
||
return
|
||
case !left && !notran:
|
||
for i := ((k - 1) / nb) * nb; i >= 0; i -= nb {
|
||
ib := min(nb, k-i)
|
||
impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib,
|
||
a[i*lda+i:], lda,
|
||
tau[i:],
|
||
t, ldt)
|
||
impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m, n-i, ib,
|
||
a[i*lda+i:], lda,
|
||
t, ldt,
|
||
c[i:], ldc,
|
||
work, ldwork)
|
||
}
|
||
return
|
||
}
|
||
}
|