Skip to content
This repository was archived by the owner on Nov 24, 2018. It is now read-only.

Commit 376807a

Browse files
committed
Add the linear solve routines (Dgetrs, Dgels) to the lapack64 interface
1 parent 6c115f0 commit 376807a

File tree

6 files changed

+137
-10
lines changed

6 files changed

+137
-10
lines changed

cgo/lapack.go

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ func min(m, n int) int {
3636
return n
3737
}
3838

39+
func max(m, n int) int {
40+
if m < n {
41+
return n
42+
}
43+
return m
44+
}
45+
3946
// checkMatrix verifies the parameters of a matrix input.
4047
// Copied from lapack/native. Keep in sync.
4148
func checkMatrix(m, n int, a []float64, lda int) {
@@ -193,6 +200,50 @@ func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []fl
193200
clapack.Dgeqrf(m, n, a, lda, tau)
194201
}
195202

203+
// Dgels finds a minimum-norm solution based on the matrices A and B using the
204+
// QR or LQ factorization. Dgels returns false if the matrix
205+
// A is singular, and true if this solution was successfully found.
206+
//
207+
// The minimization problem solved depends on the input parameters.
208+
//
209+
// 1. If m >= n and trans == blas.NoTrans, Dgels finds X such that || A*X - B||_2
210+
// is minimized.
211+
// 2. If m < n and trans == blas.NoTrans, Dgels finds the minimum norm solution of
212+
// A * X = B.
213+
// 3. If m >= n and trans == blas.Trans, Dgels finds the minimum norm solution of
214+
// A^T * X = B.
215+
// 4. If m < n and trans == blas.Trans, Dgels finds X such that || A*X - B||_2
216+
// is minimized.
217+
// Note that the least-squares solutions (cases 1 and 3) perform the minimization
218+
// per column of B. This is not the same as finding the minimum-norm matrix.
219+
//
220+
// The matrix A is a general matrix of size m×n and is modified during this call.
221+
// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry,
222+
// the elements of b specify the input matrix B. B has size m×nrhs if
223+
// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the
224+
// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans,
225+
// this submatrix is of size n×nrhs, and of size m×nrhs otherwise.
226+
//
227+
// The C interface does not support providing temporary storage. To provide compatibility
228+
// with native, lwork == -1 will not run Dgeqrf but will instead write the minimum
229+
// work necessary to work[0]. If len(work) < lwork, Dgeqrf will panic.
230+
func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool {
231+
mn := min(m, n)
232+
if lwork == -1 {
233+
work[0] = float64(mn + max(mn, nrhs))
234+
return true
235+
}
236+
checkMatrix(m, n, a, lda)
237+
checkMatrix(mn, nrhs, b, ldb)
238+
if len(work) < lwork {
239+
panic(shortWork)
240+
}
241+
if lwork < mn+max(mn, nrhs) {
242+
panic(badWork)
243+
}
244+
return clapack.Dgels(trans, m, n, nrhs, a, lda, b, ldb)
245+
}
246+
196247
// Dgetf2 computes the LU decomposition of the m×n matrix A.
197248
// The LU decomposition is a factorization of a into
198249
// A = P * L * U
@@ -223,7 +274,7 @@ func (Implementation) Dgetf2(m, n int, a []float64, lda int, ipiv []int) (ok boo
223274
}
224275

225276
// Dgetrf computes the LU decomposition of the m×n matrix A.
226-
// The LU decomposition is a factorization of a into
277+
// The LU decomposition is a factorization of A into
227278
// A = P * L * U
228279
// where P is a permutation matrix, L is a unit lower triangular matrix, and
229280
// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored

cgo/lapack_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ func TestDgelq2(t *testing.T) {
2020
testlapack.Dgelq2Test(t, impl)
2121
}
2222

23+
func TestDgels(t *testing.T) {
24+
testlapack.DgelsTest(t, impl)
25+
}
26+
2327
func TestDgelqf(t *testing.T) {
2428
testlapack.DgelqfTest(t, impl)
2529
}

lapack.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@ type Complex128 interface{}
2323

2424
// Float64 defines the public float64 LAPACK API supported by gonum/lapack.
2525
type Float64 interface {
26+
Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool
2627
Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int)
2728
Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int)
2829
Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool)
30+
Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool)
31+
Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int)
2932
}
3033

3134
// Direct specifies the direction of the multiplication for the Householder matrix.

lapack64/lapack64.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,39 @@ func Potrf(a blas64.Symmetric) (t blas64.Triangular, ok bool) {
4848
return
4949
}
5050

51+
// Gels finds a minimum-norm solution based on the matrices A and B using the
52+
// QR or LQ factorization. Dgels returns false if the matrix
53+
// A is singular, and true if this solution was successfully found.
54+
//
55+
// The minimization problem solved depends on the input parameters.
56+
//
57+
// 1. If m >= n and trans == blas.NoTrans, Dgels finds X such that || A*X - B||_2
58+
// is minimized.
59+
// 2. If m < n and trans == blas.NoTrans, Dgels finds the minimum norm solution of
60+
// A * X = B.
61+
// 3. If m >= n and trans == blas.Trans, Dgels finds the minimum norm solution of
62+
// A^T * X = B.
63+
// 4. If m < n and trans == blas.Trans, Dgels finds X such that || A*X - B||_2
64+
// is minimized.
65+
// Note that the least-squares solutions (cases 1 and 3) perform the minimization
66+
// per column of B. This is not the same as finding the minimum-norm matrix.
67+
//
68+
// The matrix A is a general matrix of size m×n and is modified during this call.
69+
// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry,
70+
// the elements of b specify the input matrix B. B has size m×nrhs if
71+
// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the
72+
// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans,
73+
// this submatrix is of size n×nrhs, and of size m×nrhs otherwise.
74+
//
75+
// Work is temporary storage, and lwork specifies the usable memory length.
76+
// At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic
77+
// otherwise. A longer work will enable blocked algorithms to be called.
78+
// In the special case that lwork == -1, work[0] will be set to the optimal working
79+
// length.
80+
func Gels(trans blas.Transpose, a blas64.General, b blas64.General, work []float64, lwork int) {
81+
lapack64.Dgels(trans, a.Rows, a.Cols, b.Cols, a.Data, a.Stride, b.Data, b.Stride, work, lwork)
82+
}
83+
5184
// Geqrf computes the QR factorization of the m×n matrix A using a blocked
5285
// algorithm. A is modified to contain the information to construct Q and R.
5386
// The upper triangle of a contains the matrix R. The lower triangular elements
@@ -93,3 +126,39 @@ func Geqrf(a blas64.General, tau, work []float64, lwork int) {
93126
func Gelqf(a blas64.General, tau, work []float64, lwork int) {
94127
lapack64.Dgelqf(a.Rows, a.Cols, a.Data, a.Stride, tau, work, lwork)
95128
}
129+
130+
// Getrf computes the LU decomposition of the m×n matrix A.
131+
// The LU decomposition is a factorization of A into
132+
// A = P * L * U
133+
// where P is a permutation matrix, L is a unit lower triangular matrix, and
134+
// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored
135+
// in place into a.
136+
//
137+
// ipiv is a permutation vector. It indicates that row i of the matrix was
138+
// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic
139+
// otherwise. ipiv is zero-indexed.
140+
//
141+
// Dgetrf is the blocked version of the algorithm.
142+
//
143+
// Dgetrf returns whether the matrix A is singular. The LU decomposition will
144+
// be computed regardless of the singularity of A, but division by zero
145+
// will occur if the false is returned and the result is used to solve a
146+
// system of equations.
147+
func Getrf(a blas64.General, ipiv []int) bool {
148+
return lapack64.Dgetrf(a.Rows, a.Cols, a.Data, a.Stride, ipiv)
149+
}
150+
151+
// Dgetrs solves a system of equations using an LU factorization.
152+
// The system of equations solved is
153+
// A * X = B if trans == blas.Trans
154+
// A^T * X = B if trans == blas.NoTrans
155+
// A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs.
156+
//
157+
// On entry b contains the elements of the matrix B. On exit, b contains the
158+
// elements of X, the solution to the system of equations.
159+
//
160+
// a and ipiv contain the LU factorization of A and the permutation indices as
161+
// computed by Getrf. ipiv is zero-indexed.
162+
func Getrs(trans blas.Transpose, a blas64.General, b blas64.General, ipiv []int) {
163+
lapack64.Dgetrs(trans, a.Cols, b.Cols, a.Data, a.Stride, ipiv, b.Data, b.Stride)
164+
}

native/dgels.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,25 @@ import (
99
"github.com/gonum/lapack"
1010
)
1111

12-
// Dgels finds a minimum-norm solution based on the matrices a and b using the
12+
// Dgels finds a minimum-norm solution based on the matrices A and B using the
1313
// QR or LQ factorization. Dgels returns false if the matrix
1414
// A is singular, and true if this solution was successfully found.
1515
//
1616
// The minimization problem solved depends on the input parameters.
1717
//
1818
// 1. If m >= n and trans == blas.NoTrans, Dgels finds X such that || A*X - B||_2
19-
// is minimized.
19+
// is minimized.
2020
// 2. If m < n and trans == blas.NoTrans, Dgels finds the minimum norm solution of
21-
// A * X = B.
21+
// A * X = B.
2222
// 3. If m >= n and trans == blas.Trans, Dgels finds the minimum norm solution of
23-
// A^T * X = B.
23+
// A^T * X = B.
2424
// 4. If m < n and trans == blas.Trans, Dgels finds X such that || A*X - B||_2
25-
// is minimized.
25+
// is minimized.
2626
// Note that the least-squares solutions (cases 1 and 3) perform the minimization
2727
// per column of B. This is not the same as finding the minimum-norm matrix.
2828
//
29-
// The matrix a is a general matrix of size m×n and is modified during this call.
30-
// The input matrix b is of size max(m,n)×nrhs, and serves two purposes. On entry,
29+
// The matrix A is a general matrix of size m×n and is modified during this call.
30+
// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry,
3131
// the elements of b specify the input matrix B. B has size m×nrhs if
3232
// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the
3333
// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans,

native/dgetrf.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import (
55
"github.com/gonum/blas/blas64"
66
)
77

8-
// Dgetrf computes the LU decomposition of the m×n matrix a.
9-
// The LU decomposition is a factorization of a into
8+
// Dgetrf computes the LU decomposition of the m×n matrix A.
9+
// The LU decomposition is a factorization of A into
1010
// A = P * L * U
1111
// where P is a permutation matrix, L is a unit lower triangular matrix, and
1212
// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored

0 commit comments

Comments
 (0)