mirror of
https://github.com/gonum/gonum.git
synced 2025-10-20 21:59:25 +08:00
Add Dorg2r and test
This commit is contained in:
@@ -28,6 +28,9 @@ const (
|
|||||||
badUplo = "lapack: illegal triangle"
|
badUplo = "lapack: illegal triangle"
|
||||||
badWork = "lapack: insufficient working memory"
|
badWork = "lapack: insufficient working memory"
|
||||||
badWorkStride = "lapack: insufficient working array stride"
|
badWorkStride = "lapack: insufficient working array stride"
|
||||||
|
kGTM = "lapack: k > m"
|
||||||
|
kGTN = "lapack: k > n"
|
||||||
|
mLTN = "lapack: m < n"
|
||||||
negDimension = "lapack: negative matrix dimension"
|
negDimension = "lapack: negative matrix dimension"
|
||||||
nLT0 = "lapack: n < 0"
|
nLT0 = "lapack: n < 0"
|
||||||
shortWork = "lapack: working array shorter than declared"
|
shortWork = "lapack: working array shorter than declared"
|
||||||
@@ -462,6 +465,37 @@ func (impl Implementation) Dgetrs(trans blas.Transpose, n, nrhs int, a []float64
|
|||||||
clapack.Dgetrs(trans, n, nrhs, a, lda, ipiv32, b, ldb)
|
clapack.Dgetrs(trans, n, nrhs, a, lda, ipiv32, b, ldb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (impl Implementation) Dorglq(m, n, k int, a []float64, lda int, tau, work []float64) {
|
||||||
|
checkMatrix(m, n, a, lda)
|
||||||
|
if len(tau) < k {
|
||||||
|
panic(badTau)
|
||||||
|
}
|
||||||
|
if k > m {
|
||||||
|
panic(kGTM)
|
||||||
|
}
|
||||||
|
if k > m {
|
||||||
|
panic(kGTM)
|
||||||
|
}
|
||||||
|
clapack.Dorglq(m, n, k, a, lda, tau)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64) {
|
||||||
|
checkMatrix(m, n, a, lda)
|
||||||
|
if len(tau) < k {
|
||||||
|
panic(badTau)
|
||||||
|
}
|
||||||
|
if len(work) < n {
|
||||||
|
panic(badWork)
|
||||||
|
}
|
||||||
|
if k > n {
|
||||||
|
panic(kGTN)
|
||||||
|
}
|
||||||
|
if n > m {
|
||||||
|
panic(mLTN)
|
||||||
|
}
|
||||||
|
clapack.Dorgqr(m, n, k, a, lda, tau)
|
||||||
|
}
|
||||||
|
|
||||||
// Dormlq multiplies the matrix C by the othogonal matrix Q defined by the
|
// Dormlq multiplies the matrix C by the othogonal matrix Q defined by the
|
||||||
// slices a and tau. A and tau are as returned from Dgelqf.
|
// slices a and tau. A and tau are as returned from Dgelqf.
|
||||||
// C = Q * C if side == blas.Left and trans == blas.NoTrans
|
// C = Q * C if side == blas.Left and trans == blas.NoTrans
|
||||||
|
@@ -84,6 +84,22 @@ func (d blockedTranslate) Dorml2(side blas.Side, trans blas.Transpose, m, n, k i
|
|||||||
impl.Dormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, len(work))
|
impl.Dormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, len(work))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d blockedTranslate) Dorg2r(m, n, k int, a []float64, lda int, tau, work []float64) {
|
||||||
|
impl.Dorgqr(m, n, k, a, lda, tau, work)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d blockedTranslate) Dorgl2(m, n, k int, a []float64, lda int, tau, work []float64) {
|
||||||
|
impl.Dorglq(m, n, k, a, lda, tau, work)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDorglq(t *testing.T) {
|
||||||
|
testlapack.Dorgl2Test(t, blockedTranslate{impl})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDorgqr(t *testing.T) {
|
||||||
|
testlapack.Dorg2rTest(t, blockedTranslate{impl})
|
||||||
|
}
|
||||||
|
|
||||||
func TestDormqr(t *testing.T) {
|
func TestDormqr(t *testing.T) {
|
||||||
testlapack.Dorm2rTest(t, blockedTranslate{impl})
|
testlapack.Dorm2rTest(t, blockedTranslate{impl})
|
||||||
}
|
}
|
||||||
|
26
native/dgebd2.go
Normal file
26
native/dgebd2.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
// Dgebd2 reduces an m×n matrix A to upper or lower bidiagonal form by an orthogonal
|
||||||
|
// transformation.
|
||||||
|
// Q^T * A * P = B
|
||||||
|
// if m >= n, B is upper diagonal, otherwise B is lower bidiagonal.
|
||||||
|
// d is the diagonal, len = min(m,n)
|
||||||
|
// e is the off-diagonal len = min(m,n)-1
|
||||||
|
func (impl Implementation) Dgebd2(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64) {
|
||||||
|
checkMatrix(m, n, a, lda)
|
||||||
|
if len(d) < min(m, n) {
|
||||||
|
panic("lapack: insufficient d")
|
||||||
|
}
|
||||||
|
if len(e) < min(m, n)-1 {
|
||||||
|
panic("lapack: insufficient e")
|
||||||
|
}
|
||||||
|
if m > n {
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
impl.Dlarfg(m-i, a[i*lda+i], a[min(i+1, m-1)*lda+i:], 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
native/dorg2r.go
Normal file
61
native/dorg2r.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// 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/blas/blas64"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dorg2r generates an m×n matrix Q with orthonormal columns defined by the
|
||||||
|
// product of elementary reflectors as computed by Dgeqrf.
|
||||||
|
// Q = H(0) * H(2) * ... * H(k-1)
|
||||||
|
// The length of tau must be equal to k, and the length of work must be at least n.
|
||||||
|
// It also must be that 0 <= k <= n. m >= n >= 0. Dorg2r will panic if these
|
||||||
|
// conditions are not met.
|
||||||
|
func (impl Implementation) Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64) {
|
||||||
|
checkMatrix(m, n, a, lda)
|
||||||
|
if len(tau) < k {
|
||||||
|
panic(badTau)
|
||||||
|
}
|
||||||
|
if len(work) < n {
|
||||||
|
panic(badWork)
|
||||||
|
}
|
||||||
|
if k > n {
|
||||||
|
panic(kGTN)
|
||||||
|
}
|
||||||
|
if n > m {
|
||||||
|
panic(mLTN)
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bi := blas64.Implementation()
|
||||||
|
// Initialize columns k+1:n to columns of the unit matrix.
|
||||||
|
for l := 0; l < m; l++ {
|
||||||
|
for j := k; j < n; j++ {
|
||||||
|
a[l*lda+j] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j := k; j < n; j++ {
|
||||||
|
a[j*lda+j] = 1
|
||||||
|
}
|
||||||
|
for i := k - 1; i >= 0; i-- {
|
||||||
|
for i := range work {
|
||||||
|
work[i] = 0
|
||||||
|
}
|
||||||
|
if i < n-1 {
|
||||||
|
a[i*lda+i] = 1
|
||||||
|
impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tau[i], a[i*lda+i+1:], lda, work)
|
||||||
|
}
|
||||||
|
if i < m-1 {
|
||||||
|
bi.Dscal(m-i-1, -tau[i], a[(i+1)*lda+i:], lda)
|
||||||
|
}
|
||||||
|
a[i*lda+i] = 1 - tau[i]
|
||||||
|
for l := 0; l < i; l++ {
|
||||||
|
a[l*lda+i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
native/dorgl2.go
Normal file
56
native/dorgl2.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// 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/blas/blas64"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dorgl2 generates an m×n matrix Q with orthonormal rows defined by the
|
||||||
|
// first m rows product of elementary reflectors as computed by Dgelqf.
|
||||||
|
// Q = H(0) * H(2) * ... * H(k-1)
|
||||||
|
// The length of tau must be equal to k, and the length of work must be at least n.
|
||||||
|
// It also must be that 0 <= k <= m. n >= m >= 0. Dorgl2 will panic if these
|
||||||
|
// conditions are not met.
|
||||||
|
func (impl Implementation) Dorgl2(m, n, k int, a []float64, lda int, tau, work []float64) {
|
||||||
|
checkMatrix(m, n, a, lda)
|
||||||
|
if len(tau) < k {
|
||||||
|
panic(badTau)
|
||||||
|
}
|
||||||
|
if k > m {
|
||||||
|
panic(kGTM)
|
||||||
|
}
|
||||||
|
if k > m {
|
||||||
|
panic(kGTM)
|
||||||
|
}
|
||||||
|
if m == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bi := blas64.Implementation()
|
||||||
|
if k < m-1 {
|
||||||
|
for i := k; i < m; i++ {
|
||||||
|
for j := 0; j < n; j++ {
|
||||||
|
a[i*lda+j] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j := k; j < m; j++ {
|
||||||
|
a[j*lda+j] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := k - 1; i >= 0; i-- {
|
||||||
|
if i < n-1 {
|
||||||
|
if i < m-1 {
|
||||||
|
a[i*lda+i] = 1
|
||||||
|
impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tau[i], a[(i+1)*lda+i:], lda, work)
|
||||||
|
}
|
||||||
|
bi.Dscal(n-i-1, -tau[i], a[i*lda+i+1:], 1)
|
||||||
|
}
|
||||||
|
a[i*lda+i] = 1 - tau[i]
|
||||||
|
for l := 0; l < i; l++ {
|
||||||
|
a[i*lda+l] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -34,6 +34,9 @@ const (
|
|||||||
badUplo = "lapack: illegal triangle"
|
badUplo = "lapack: illegal triangle"
|
||||||
badWork = "lapack: insufficient working memory"
|
badWork = "lapack: insufficient working memory"
|
||||||
badWorkStride = "lapack: insufficient working array stride"
|
badWorkStride = "lapack: insufficient working array stride"
|
||||||
|
kGTM = "lapack: k > m"
|
||||||
|
kGTN = "lapack: k > n"
|
||||||
|
mLTN = "lapack: m < n"
|
||||||
negDimension = "lapack: negative matrix dimension"
|
negDimension = "lapack: negative matrix dimension"
|
||||||
nLT0 = "lapack: n < 0"
|
nLT0 = "lapack: n < 0"
|
||||||
shortWork = "lapack: working array shorter than declared"
|
shortWork = "lapack: working array shorter than declared"
|
||||||
|
@@ -120,6 +120,14 @@ func TestDorm2r(t *testing.T) {
|
|||||||
testlapack.Dorm2rTest(t, impl)
|
testlapack.Dorm2rTest(t, impl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDorg2r(t *testing.T) {
|
||||||
|
testlapack.Dorg2rTest(t, impl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDorgl2(t *testing.T) {
|
||||||
|
testlapack.Dorgl2Test(t, impl)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDpocon(t *testing.T) {
|
func TestDpocon(t *testing.T) {
|
||||||
testlapack.DpoconTest(t, impl)
|
testlapack.DpoconTest(t, impl)
|
||||||
}
|
}
|
||||||
|
70
testlapack/dorg2r.go
Normal file
70
testlapack/dorg2r.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// 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 testlapack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gonum/floats"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Dorg2rer interface {
|
||||||
|
Dgeqrfer
|
||||||
|
Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Dorg2rTest(t *testing.T, impl Dorg2rer) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
m, n, lda int
|
||||||
|
}{
|
||||||
|
{3, 3, 0},
|
||||||
|
{4, 3, 0},
|
||||||
|
|
||||||
|
{5, 5, 20},
|
||||||
|
{10, 5, 20},
|
||||||
|
} {
|
||||||
|
m := test.m
|
||||||
|
n := test.n
|
||||||
|
lda := test.lda
|
||||||
|
if lda == 0 {
|
||||||
|
lda = test.n
|
||||||
|
}
|
||||||
|
a := make([]float64, m*lda)
|
||||||
|
for i := range a {
|
||||||
|
a[i] = rand.NormFloat64()
|
||||||
|
}
|
||||||
|
k := min(m, n)
|
||||||
|
tau := make([]float64, k)
|
||||||
|
work := make([]float64, 1)
|
||||||
|
impl.Dgeqrf(m, n, a, lda, tau, work, -1)
|
||||||
|
work = make([]float64, int(work[0]))
|
||||||
|
impl.Dgeqrf(m, n, a, lda, tau, work, len(work))
|
||||||
|
|
||||||
|
q := constructQ("QR", m, n, a, lda, tau)
|
||||||
|
|
||||||
|
impl.Dorg2r(m, n, k, a, lda, tau, work)
|
||||||
|
|
||||||
|
// Check that the first n columns match.
|
||||||
|
same := true
|
||||||
|
for i := 0; i < m; i++ {
|
||||||
|
for j := 0; j < n; j++ {
|
||||||
|
if !floats.EqualWithinAbsOrRel(q.Data[i*q.Stride+j], a[i*lda+j], 1e-12, 1e-12) {
|
||||||
|
same = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !same {
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("a =")
|
||||||
|
printRowise(a, m, n, lda, false)
|
||||||
|
fmt.Println("q =")
|
||||||
|
printRowise(q.Data, q.Rows, q.Cols, q.Stride, false)
|
||||||
|
t.Errorf("Q mismatch")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
testlapack/dorgl2.go
Normal file
64
testlapack/dorgl2.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// 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 testlapack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gonum/floats"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Dorgl2er interface {
|
||||||
|
Dgelqfer
|
||||||
|
Dorgl2(m, n, k int, a []float64, lda int, tau []float64, work []float64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Dorgl2Test(t *testing.T, impl Dorgl2er) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
m, n, lda int
|
||||||
|
}{
|
||||||
|
{3, 3, 0},
|
||||||
|
{3, 4, 0},
|
||||||
|
|
||||||
|
{5, 5, 20},
|
||||||
|
{5, 10, 20},
|
||||||
|
} {
|
||||||
|
m := test.m
|
||||||
|
n := test.n
|
||||||
|
lda := test.lda
|
||||||
|
if lda == 0 {
|
||||||
|
lda = test.n
|
||||||
|
}
|
||||||
|
a := make([]float64, m*lda)
|
||||||
|
for i := range a {
|
||||||
|
a[i] = rand.NormFloat64()
|
||||||
|
}
|
||||||
|
k := min(m, n)
|
||||||
|
tau := make([]float64, k)
|
||||||
|
work := make([]float64, 1)
|
||||||
|
impl.Dgelqf(m, n, a, lda, tau, work, -1)
|
||||||
|
work = make([]float64, int(work[0]))
|
||||||
|
impl.Dgelqf(m, n, a, lda, tau, work, len(work))
|
||||||
|
|
||||||
|
q := constructQ("LQ", m, n, a, lda, tau)
|
||||||
|
|
||||||
|
impl.Dorgl2(m, n, k, a, lda, tau, work)
|
||||||
|
|
||||||
|
// Check that the first m rows match.
|
||||||
|
same := true
|
||||||
|
for i := 0; i < m; i++ {
|
||||||
|
for j := 0; j < n; j++ {
|
||||||
|
if !floats.EqualWithinAbsOrRel(q.Data[i*q.Stride+j], a[i*lda+j], 1e-12, 1e-12) {
|
||||||
|
same = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !same {
|
||||||
|
t.Errorf("Q mismatch")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user