mirror of
https://github.com/gonum/gonum.git
synced 2025-10-04 14:52:57 +08:00
lapack/gonum: require exact length of tau in QR routines
This commit is contained in:

committed by
Vladimír Chalupecký

parent
bd767ae5eb
commit
6e2f5c5890
@@ -131,7 +131,7 @@ func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float
|
|||||||
// Solve the minimization problem using a QR or an LQ decomposition.
|
// Solve the minimization problem using a QR or an LQ decomposition.
|
||||||
var scllen int
|
var scllen int
|
||||||
if m >= n {
|
if m >= n {
|
||||||
impl.Dgeqrf(m, n, a, lda, work, work[mn:], lwork-mn)
|
impl.Dgeqrf(m, n, a, lda, work[:n], work[mn:], lwork-mn)
|
||||||
if trans == blas.NoTrans {
|
if trans == blas.NoTrans {
|
||||||
impl.Dormqr(blas.Left, blas.Trans, m, nrhs, n,
|
impl.Dormqr(blas.Left, blas.Trans, m, nrhs, n,
|
||||||
a, lda,
|
a, lda,
|
||||||
|
@@ -123,7 +123,7 @@ func (impl Implementation) Dgeqp3(m, n int, a []float64, lda int, jpvt []int, ta
|
|||||||
// Compute the QR factorization of nfxd columns and update remaining columns.
|
// Compute the QR factorization of nfxd columns and update remaining columns.
|
||||||
if nfxd > 0 {
|
if nfxd > 0 {
|
||||||
na := min(m, nfxd)
|
na := min(m, nfxd)
|
||||||
impl.Dgeqrf(m, na, a, lda, tau, work, lwork)
|
impl.Dgeqrf(m, na, a, lda, tau[:na], work, lwork)
|
||||||
iws = max(iws, int(work[0]))
|
iws = max(iws, int(work[0]))
|
||||||
if na < n {
|
if na < n {
|
||||||
impl.Dormqr(blas.Left, blas.Trans, m, n-na, na, a, lda, tau[:na], a[na:], lda,
|
impl.Dormqr(blas.Left, blas.Trans, m, n-na, na, a, lda, tau[:na], a[na:], lda,
|
||||||
|
@@ -14,7 +14,7 @@ import "gonum.org/v1/gonum/blas"
|
|||||||
// A is modified to contain the information to construct Q and R.
|
// A is modified to contain the information to construct Q and R.
|
||||||
// The upper triangle of a contains the matrix R. The lower triangular elements
|
// The upper triangle of a contains the matrix R. The lower triangular elements
|
||||||
// (not including the diagonal) contain the elementary reflectors. tau is modified
|
// (not including the diagonal) contain the elementary reflectors. tau is modified
|
||||||
// to contain the reflector scales. tau must have length at least min(m,n), and
|
// to contain the reflector scales. tau must have length min(m,n), and
|
||||||
// this function will panic otherwise.
|
// this function will panic otherwise.
|
||||||
//
|
//
|
||||||
// The ith elementary reflector can be explicitly constructed by first extracting
|
// The ith elementary reflector can be explicitly constructed by first extracting
|
||||||
@@ -57,8 +57,8 @@ func (impl Implementation) Dgeqr2(m, n int, a []float64, lda int, tau, work []fl
|
|||||||
switch {
|
switch {
|
||||||
case len(a) < (m-1)*lda+n:
|
case len(a) < (m-1)*lda+n:
|
||||||
panic(shortA)
|
panic(shortA)
|
||||||
case len(tau) < k:
|
case len(tau) != k:
|
||||||
panic(shortTau)
|
panic(badLenTau)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < k; i++ {
|
for i := 0; i < k; i++ {
|
||||||
|
@@ -20,7 +20,7 @@ import (
|
|||||||
// by the temporary space available. If lwork == -1, instead of performing Dgeqrf,
|
// by the temporary space available. If lwork == -1, instead of performing Dgeqrf,
|
||||||
// the optimal work length will be stored into work[0].
|
// the optimal work length will be stored into work[0].
|
||||||
//
|
//
|
||||||
// tau must have length at least min(m,n), and this function will panic otherwise.
|
// tau must have length min(m,n), and this function will panic otherwise.
|
||||||
func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) {
|
func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) {
|
||||||
switch {
|
switch {
|
||||||
case m < 0:
|
case m < 0:
|
||||||
@@ -52,8 +52,8 @@ func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []fl
|
|||||||
if len(a) < (m-1)*lda+n {
|
if len(a) < (m-1)*lda+n {
|
||||||
panic(shortA)
|
panic(shortA)
|
||||||
}
|
}
|
||||||
if len(tau) < k {
|
if len(tau) != k {
|
||||||
panic(shortTau)
|
panic(badLenTau)
|
||||||
}
|
}
|
||||||
|
|
||||||
nbmin := 2 // Minimal block size.
|
nbmin := 2 // Minimal block size.
|
||||||
@@ -83,7 +83,7 @@ func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []fl
|
|||||||
for i = 0; i < k-nx; i += nb {
|
for i = 0; i < k-nx; i += nb {
|
||||||
ib := min(k-i, nb)
|
ib := min(k-i, nb)
|
||||||
// Compute the QR factorization of the current block.
|
// Compute the QR factorization of the current block.
|
||||||
impl.Dgeqr2(m-i, ib, a[i*lda+i:], lda, tau[i:], work)
|
impl.Dgeqr2(m-i, ib, a[i*lda+i:], lda, tau[i:i+ib], work)
|
||||||
if i+ib < n {
|
if i+ib < n {
|
||||||
// Form the triangular factor of the block reflector and apply Hᵀ
|
// Form the triangular factor of the block reflector and apply Hᵀ
|
||||||
// In Dlarft, work becomes the T matrix.
|
// In Dlarft, work becomes the T matrix.
|
||||||
|
@@ -406,7 +406,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
|
|
||||||
// Compute A = Q * R.
|
// Compute A = Q * R.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
|
|
||||||
// Zero out below R.
|
// Zero out below R.
|
||||||
impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda)
|
impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda)
|
||||||
@@ -455,14 +455,14 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
itau := ir + ldworkr*n
|
itau := ir + ldworkr*n
|
||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
// Compute A = Q * R.
|
// Compute A = Q * R.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
|
|
||||||
// Copy R to work[ir:], zeroing out below it.
|
// Copy R to work[ir:], zeroing out below it.
|
||||||
impl.Dlacpy(blas.Upper, n, n, a, lda, work[ir:], ldworkr)
|
impl.Dlacpy(blas.Upper, n, n, a, lda, work[ir:], ldworkr)
|
||||||
impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr)
|
impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr)
|
||||||
|
|
||||||
// Generate Q in A.
|
// Generate Q in A.
|
||||||
impl.Dorgqr(m, n, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dorgqr(m, n, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
ie := itau
|
ie := itau
|
||||||
itauq := ie + n
|
itauq := ie + n
|
||||||
itaup := itauq + n
|
itaup := itauq + n
|
||||||
@@ -492,11 +492,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
|
|
||||||
// Compute A = Q*R, copying result to U.
|
// Compute A = Q*R, copying result to U.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
||||||
|
|
||||||
// Generate Q in U.
|
// Generate Q in U.
|
||||||
impl.Dorgqr(m, n, n, u, ldu, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dorgqr(m, n, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
ie := itau
|
ie := itau
|
||||||
itauq := ie + n
|
itauq := ie + n
|
||||||
itaup := itauq + n
|
itaup := itauq + n
|
||||||
@@ -537,13 +537,13 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
|
|
||||||
// Compute A = Q * R.
|
// Compute A = Q * R.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
// Copy R to work[iu:], zeroing out below it.
|
// Copy R to work[iu:], zeroing out below it.
|
||||||
impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku)
|
impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku)
|
||||||
impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[iu+ldworku:], ldworku)
|
impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[iu+ldworku:], ldworku)
|
||||||
|
|
||||||
// Generate Q in A.
|
// Generate Q in A.
|
||||||
impl.Dorgqr(m, n, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dorgqr(m, n, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
|
|
||||||
ie := itau
|
ie := itau
|
||||||
itauq := ie + n
|
itauq := ie + n
|
||||||
@@ -580,11 +580,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
|
|
||||||
// Compute A = Q * R, copying result to U.
|
// Compute A = Q * R, copying result to U.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
||||||
|
|
||||||
// Generate Q in U.
|
// Generate Q in U.
|
||||||
impl.Dorgqr(m, n, n, u, ldu, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dorgqr(m, n, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
|
|
||||||
// Copy R to VT, zeroing out below it.
|
// Copy R to VT, zeroing out below it.
|
||||||
impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt)
|
impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt)
|
||||||
@@ -631,7 +631,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
|
|
||||||
// Compute A = Q*R, copying result to U.
|
// Compute A = Q*R, copying result to U.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
||||||
|
|
||||||
// Copy R to work[ir:], zeroing out below it.
|
// Copy R to work[ir:], zeroing out below it.
|
||||||
@@ -639,7 +639,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr)
|
impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr)
|
||||||
|
|
||||||
// Generate Q in U.
|
// Generate Q in U.
|
||||||
impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dorgqr(m, m, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
ie := itau
|
ie := itau
|
||||||
itauq := ie + n
|
itauq := ie + n
|
||||||
itaup := itauq + n
|
itaup := itauq + n
|
||||||
@@ -672,11 +672,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
|
|
||||||
// Compute A = Q*R, copying result to U.
|
// Compute A = Q*R, copying result to U.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
||||||
|
|
||||||
// Generate Q in U.
|
// Generate Q in U.
|
||||||
impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dorgqr(m, m, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
ie := itau
|
ie := itau
|
||||||
itauq := ie + n
|
itauq := ie + n
|
||||||
itaup := itauq + n
|
itaup := itauq + n
|
||||||
@@ -717,11 +717,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
|
|
||||||
// Compute A = Q * R, copying result to U.
|
// Compute A = Q * R, copying result to U.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
||||||
|
|
||||||
// Generate Q in U.
|
// Generate Q in U.
|
||||||
impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dorgqr(m, m, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
|
|
||||||
// Copy R to work[iu:], zeroing out below it.
|
// Copy R to work[iu:], zeroing out below it.
|
||||||
impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku)
|
impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku)
|
||||||
@@ -786,11 +786,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float
|
|||||||
iwork := itau + n
|
iwork := itau + n
|
||||||
|
|
||||||
// Compute A = Q*R, copying result to U.
|
// Compute A = Q*R, copying result to U.
|
||||||
impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu)
|
||||||
|
|
||||||
// Generate Q in U.
|
// Generate Q in U.
|
||||||
impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork)
|
impl.Dorgqr(m, m, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork)
|
||||||
|
|
||||||
// Copy R from A to VT, zeroing out below it.
|
// Copy R from A to VT, zeroing out below it.
|
||||||
impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt)
|
impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt)
|
||||||
|
@@ -154,7 +154,7 @@ func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int,
|
|||||||
if p > 1 {
|
if p > 1 {
|
||||||
impl.Dlacpy(blas.Lower, p-1, min(p, n), b[ldb:], ldb, v[ldv:], ldv)
|
impl.Dlacpy(blas.Lower, p-1, min(p, n), b[ldb:], ldb, v[ldv:], ldv)
|
||||||
}
|
}
|
||||||
impl.Dorg2r(p, p, min(p, n), v, ldv, tau, work)
|
impl.Dorg2r(p, p, min(p, n), v, ldv, tau[:min(p, n)], work)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up B.
|
// Clean up B.
|
||||||
@@ -216,7 +216,7 @@ func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update A12 := Uᵀ*A12, where A12 = A[0:m, n-l:n].
|
// Update A12 := Uᵀ*A12, where A12 = A[0:m, n-l:n].
|
||||||
impl.Dorm2r(blas.Left, blas.Trans, m, l, min(m, n-l), a, lda, tau, a[n-l:], lda, work)
|
impl.Dorm2r(blas.Left, blas.Trans, m, l, min(m, n-l), a, lda, tau[:min(m, n-l)], a[n-l:], lda, work)
|
||||||
|
|
||||||
if wantu {
|
if wantu {
|
||||||
// Copy the details of U, and form U.
|
// Copy the details of U, and form U.
|
||||||
@@ -224,7 +224,8 @@ func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int,
|
|||||||
if m > 1 {
|
if m > 1 {
|
||||||
impl.Dlacpy(blas.Lower, m-1, min(m, n-l), a[lda:], lda, u[ldu:], ldu)
|
impl.Dlacpy(blas.Lower, m-1, min(m, n-l), a[lda:], lda, u[ldu:], ldu)
|
||||||
}
|
}
|
||||||
impl.Dorg2r(m, m, min(m, n-l), u, ldu, tau, work)
|
k := min(m, n-l)
|
||||||
|
impl.Dorg2r(m, m, k, u, ldu, tau[:k], work)
|
||||||
}
|
}
|
||||||
|
|
||||||
if wantq {
|
if wantq {
|
||||||
@@ -250,7 +251,7 @@ func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int,
|
|||||||
|
|
||||||
if wantq {
|
if wantq {
|
||||||
// Update Q[0:n, 0:n-l] := Q[0:n, 0:n-l]*Z1ᵀ.
|
// Update Q[0:n, 0:n-l] := Q[0:n, 0:n-l]*Z1ᵀ.
|
||||||
impl.Dorm2r(blas.Right, blas.Trans, n, n-l, k, a, lda, tau, q, ldq, work)
|
impl.Dorm2r(blas.Right, blas.Trans, n, n-l, k, a, lda, tau[:k], q, ldq, work)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up A.
|
// Clean up A.
|
||||||
@@ -265,10 +266,10 @@ func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int,
|
|||||||
|
|
||||||
if m > k {
|
if m > k {
|
||||||
// QR factorization of A[k:m, n-l:n].
|
// QR factorization of A[k:m, n-l:n].
|
||||||
impl.Dgeqr2(m-k, l, a[k*lda+n-l:], lda, tau, work)
|
impl.Dgeqr2(m-k, l, a[k*lda+n-l:], lda, tau[:min(m-k, l)], work)
|
||||||
if wantu {
|
if wantu {
|
||||||
// Update U[:, k:m) := U[:, k:m]*U1.
|
// Update U[:, k:m) := U[:, k:m]*U1.
|
||||||
impl.Dorm2r(blas.Right, blas.NoTrans, m, m-k, min(m-k, l), a[k*lda+n-l:], lda, tau, u[k:], ldu, work)
|
impl.Dorm2r(blas.Right, blas.NoTrans, m, m-k, min(m-k, l), a[k*lda+n-l:], lda, tau[:min(m-k, l)], u[k:], ldu, work)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up A.
|
// Clean up A.
|
||||||
|
@@ -14,7 +14,7 @@ import (
|
|||||||
//
|
//
|
||||||
// Q = H_0 * H_1 * ... * H_{k-1}
|
// Q = H_0 * H_1 * ... * H_{k-1}
|
||||||
//
|
//
|
||||||
// len(tau) >= k, 0 <= k <= n, 0 <= n <= m, len(work) >= n.
|
// len(tau) = k, 0 <= k <= n, 0 <= n <= m, len(work) >= n.
|
||||||
// Dorg2r will panic if these conditions are not met.
|
// Dorg2r will panic if these conditions are not met.
|
||||||
//
|
//
|
||||||
// Dorg2r is an internal routine. It is exported for testing purposes.
|
// Dorg2r is an internal routine. It is exported for testing purposes.
|
||||||
@@ -41,8 +41,8 @@ func (impl Implementation) Dorg2r(m, n, k int, a []float64, lda int, tau []float
|
|||||||
switch {
|
switch {
|
||||||
case len(a) < (m-1)*lda+n:
|
case len(a) < (m-1)*lda+n:
|
||||||
panic(shortA)
|
panic(shortA)
|
||||||
case len(tau) < k:
|
case len(tau) != k:
|
||||||
panic(shortTau)
|
panic(badLenTau)
|
||||||
case len(work) < n:
|
case len(work) < n:
|
||||||
panic(shortWork)
|
panic(shortWork)
|
||||||
}
|
}
|
||||||
|
@@ -91,7 +91,7 @@ func (impl Implementation) Dorgbr(vect lapack.GenOrtho, m, n, k int, a []float64
|
|||||||
if wantq {
|
if wantq {
|
||||||
// Form Q, determined by a call to Dgebrd to reduce an m×k matrix.
|
// Form Q, determined by a call to Dgebrd to reduce an m×k matrix.
|
||||||
if m >= k {
|
if m >= k {
|
||||||
impl.Dorgqr(m, n, k, a, lda, tau, work, lwork)
|
impl.Dorgqr(m, n, k, a, lda, tau[:k], work, lwork)
|
||||||
} else {
|
} else {
|
||||||
// Shift the vectors which define the elementary reflectors one
|
// Shift the vectors which define the elementary reflectors one
|
||||||
// column to the right, and set the first row and column of Q to
|
// column to the right, and set the first row and column of Q to
|
||||||
@@ -108,7 +108,7 @@ func (impl Implementation) Dorgbr(vect lapack.GenOrtho, m, n, k int, a []float64
|
|||||||
}
|
}
|
||||||
if m > 1 {
|
if m > 1 {
|
||||||
// Form Q[1:m-1, 1:m-1]
|
// Form Q[1:m-1, 1:m-1]
|
||||||
impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau, work, lwork)
|
impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau[:m-1], work, lwork)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
// Dorgqr is the blocked version of Dorg2r that makes greater use of level-3 BLAS
|
// Dorgqr is the blocked version of Dorg2r that makes greater use of level-3 BLAS
|
||||||
// routines.
|
// routines.
|
||||||
//
|
//
|
||||||
// The length of tau must be at least k, and the length of work must be at least n.
|
// The length of tau must be k, and the length of work must be at least n.
|
||||||
// It also must be that 0 <= k <= n and 0 <= n <= m.
|
// It also must be that 0 <= k <= n and 0 <= n <= m.
|
||||||
//
|
//
|
||||||
// work is temporary storage, and lwork specifies the usable memory length. At
|
// work is temporary storage, and lwork specifies the usable memory length. At
|
||||||
@@ -70,8 +70,8 @@ func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work [
|
|||||||
switch {
|
switch {
|
||||||
case len(a) < (m-1)*lda+n:
|
case len(a) < (m-1)*lda+n:
|
||||||
panic(shortA)
|
panic(shortA)
|
||||||
case len(tau) < k:
|
case len(tau) != k:
|
||||||
panic(shortTau)
|
panic(badLenTau)
|
||||||
}
|
}
|
||||||
|
|
||||||
nbmin := 2 // Minimum block size
|
nbmin := 2 // Minimum block size
|
||||||
@@ -123,7 +123,7 @@ func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work [
|
|||||||
a[i*lda+i+ib:], lda,
|
a[i*lda+i+ib:], lda,
|
||||||
work[ib*ldwork:], ldwork)
|
work[ib*ldwork:], ldwork)
|
||||||
}
|
}
|
||||||
impl.Dorg2r(m-i, ib, ib, a[i*lda+i:], lda, tau[i:], work)
|
impl.Dorg2r(m-i, ib, ib, a[i*lda+i:], lda, tau[i:i+ib], work)
|
||||||
// Set rows 0:i-1 of current block to zero.
|
// Set rows 0:i-1 of current block to zero.
|
||||||
for j := i; j < i+ib; j++ {
|
for j := i; j < i+ib; j++ {
|
||||||
for l := 0; l < i; l++ {
|
for l := 0; l < i; l++ {
|
||||||
|
@@ -99,7 +99,7 @@ func (impl Implementation) Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, t
|
|||||||
}
|
}
|
||||||
if n > 1 {
|
if n > 1 {
|
||||||
// Generate Q[1:n, 1:n].
|
// Generate Q[1:n, 1:n].
|
||||||
impl.Dorgqr(n-1, n-1, n-1, a[lda+1:], lda, tau, work, lwork)
|
impl.Dorgqr(n-1, n-1, n-1, a[lda+1:], lda, tau[:n-1], work, lwork)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
work[0] = float64(lworkopt)
|
work[0] = float64(lworkopt)
|
||||||
|
@@ -17,7 +17,7 @@ import "gonum.org/v1/gonum/blas"
|
|||||||
// If side == blas.Left, a is a matrix of size m×k, and if side == blas.Right
|
// If side == blas.Left, a is a matrix of size m×k, and if side == blas.Right
|
||||||
// a is of size n×k.
|
// a is of size n×k.
|
||||||
//
|
//
|
||||||
// tau contains the Householder factors and is of length at least k and this function
|
// tau contains the Householder factors and must have length k and this function
|
||||||
// will panic otherwise.
|
// will panic otherwise.
|
||||||
//
|
//
|
||||||
// work is temporary storage of length at least n if side == blas.Left
|
// work is temporary storage of length at least n if side == blas.Left
|
||||||
@@ -59,8 +59,8 @@ func (impl Implementation) Dorm2r(side blas.Side, trans blas.Transpose, m, n, k
|
|||||||
panic(shortA)
|
panic(shortA)
|
||||||
case len(c) < (m-1)*ldc+n:
|
case len(c) < (m-1)*ldc+n:
|
||||||
panic(shortC)
|
panic(shortC)
|
||||||
case len(tau) < k:
|
case len(tau) != k:
|
||||||
panic(shortTau)
|
panic(badLenTau)
|
||||||
case left && len(work) < n:
|
case left && len(work) < n:
|
||||||
panic(shortWork)
|
panic(shortWork)
|
||||||
case !left && len(work) < m:
|
case !left && len(work) < m:
|
||||||
|
@@ -267,7 +267,7 @@ func Geqp3(a blas64.General, jpvt []int, tau, work []float64, lwork int) {
|
|||||||
// algorithm. A is modified to contain the information to construct Q and R.
|
// algorithm. A is modified to contain the information to construct Q and R.
|
||||||
// The upper triangle of a contains the matrix R. The lower triangular elements
|
// The upper triangle of a contains the matrix R. The lower triangular elements
|
||||||
// (not including the diagonal) contain the elementary reflectors. tau is modified
|
// (not including the diagonal) contain the elementary reflectors. tau is modified
|
||||||
// to contain the reflector scales. tau must have length at least min(m,n), and
|
// to contain the reflector scales. tau must have length min(m,n), and
|
||||||
// this function will panic otherwise.
|
// this function will panic otherwise.
|
||||||
//
|
//
|
||||||
// The ith elementary reflector can be explicitly constructed by first extracting
|
// The ith elementary reflector can be explicitly constructed by first extracting
|
||||||
|
@@ -62,8 +62,9 @@ func DgeqrfTest(t *testing.T, impl Dgeqrfer) {
|
|||||||
|
|
||||||
// Allocate a slice for scalar factors of elementary reflectors
|
// Allocate a slice for scalar factors of elementary reflectors
|
||||||
// and fill it with random numbers.
|
// and fill it with random numbers.
|
||||||
tau := make([]float64, n)
|
k := min(m, n)
|
||||||
for i := 0; i < n; i++ {
|
tau := make([]float64, k)
|
||||||
|
for i := range tau {
|
||||||
tau[i] = rnd.Float64()
|
tau[i] = rnd.Float64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -84,7 +84,7 @@ func DlarfbTest(t *testing.T, impl Dlarfber) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use dgeqr2 to find the v vectors
|
// Use dgeqr2 to find the v vectors
|
||||||
tau := make([]float64, na)
|
tau := make([]float64, k)
|
||||||
work := make([]float64, na)
|
work := make([]float64, na)
|
||||||
impl.Dgeqr2(ma, k, a, lda, tau, work)
|
impl.Dgeqr2(ma, k, a, lda, tau, work)
|
||||||
|
|
||||||
|
@@ -52,7 +52,8 @@ func DlarftTest(t *testing.T, impl Dlarfter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Use dgeqr2 to find the v vectors
|
// Use dgeqr2 to find the v vectors
|
||||||
tau := make([]float64, n)
|
k := min(m, n)
|
||||||
|
tau := make([]float64, k)
|
||||||
work := make([]float64, n)
|
work := make([]float64, n)
|
||||||
impl.Dgeqr2(m, n, a, lda, tau, work)
|
impl.Dgeqr2(m, n, a, lda, tau, work)
|
||||||
|
|
||||||
@@ -64,7 +65,6 @@ func DlarftTest(t *testing.T, impl Dlarfter) {
|
|||||||
|
|
||||||
h := constructH(tau, vMat, store, direct)
|
h := constructH(tau, vMat, store, direct)
|
||||||
|
|
||||||
k := min(m, n)
|
|
||||||
ldt := test.ldt
|
ldt := test.ldt
|
||||||
if ldt == 0 {
|
if ldt == 0 {
|
||||||
ldt = k
|
ldt = k
|
||||||
|
@@ -59,7 +59,7 @@ func Dorg2rTest(t *testing.T, impl Dorg2rer) {
|
|||||||
q := constructQK("QR", m, n, k, a, lda, tau)
|
q := constructQK("QR", m, n, k, a, lda, tau)
|
||||||
|
|
||||||
// Compute the matrix Q using Dorg2r.
|
// Compute the matrix Q using Dorg2r.
|
||||||
impl.Dorg2r(m, n, k, a, lda, tau, work)
|
impl.Dorg2r(m, n, k, a, lda, tau[:k], work)
|
||||||
|
|
||||||
// Check that the first n columns of both results match.
|
// Check that the first n columns of both results match.
|
||||||
same := true
|
same := true
|
||||||
|
@@ -57,7 +57,7 @@ func DorgqrTest(t *testing.T, impl Dorgqrer) {
|
|||||||
a[i] = rnd.Float64()
|
a[i] = rnd.Float64()
|
||||||
}
|
}
|
||||||
work := make([]float64, 1)
|
work := make([]float64, 1)
|
||||||
tau := make([]float64, n)
|
tau := make([]float64, min(m, n))
|
||||||
for i := range tau {
|
for i := range tau {
|
||||||
tau[i] = math.NaN()
|
tau[i] = math.NaN()
|
||||||
}
|
}
|
||||||
@@ -71,12 +71,12 @@ func DorgqrTest(t *testing.T, impl Dorgqrer) {
|
|||||||
for i := range work {
|
for i := range work {
|
||||||
work[i] = math.NaN()
|
work[i] = math.NaN()
|
||||||
}
|
}
|
||||||
impl.Dorg2r(m, n, k, aUnblocked, lda, tau, work)
|
impl.Dorg2r(m, n, k, aUnblocked, lda, tau[:k], work)
|
||||||
// make sure work isn't used before initialized
|
// make sure work isn't used before initialized
|
||||||
for i := range work {
|
for i := range work {
|
||||||
work[i] = math.NaN()
|
work[i] = math.NaN()
|
||||||
}
|
}
|
||||||
impl.Dorgqr(m, n, k, a, lda, tau, work, len(work))
|
impl.Dorgqr(m, n, k, a, lda, tau[:k], work, len(work))
|
||||||
if !floats.EqualApprox(a, aUnblocked, 1e-10) {
|
if !floats.EqualApprox(a, aUnblocked, 1e-10) {
|
||||||
t.Errorf("Q Mismatch. m = %d, n = %d, k = %d, lda = %d", m, n, k, lda)
|
t.Errorf("Q Mismatch. m = %d, n = %d, k = %d, lda = %d", m, n, k, lda)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user