mat: change factorization inputs to use bit types (#872)

* mat: change factorization inputs to use bit types

Fixes #756 and #748.
This commit is contained in:
Brendan Tracey
2019-03-23 17:20:14 +00:00
committed by GitHub
parent 9dd6aa72d7
commit 1d8caee34e
7 changed files with 205 additions and 123 deletions

View File

@@ -11,6 +11,29 @@ import (
"gonum.org/v1/gonum/lapack/lapack64"
)
// GSVDKind specifies the treatment of singular vectors during a GSVD
// factorization.
type GSVDKind int
const (
// GSVDNone specifies that no singular vectors should be computed during
// the decomposition.
GSVDNone GSVDKind = 0
// GSVDU specifies that the U singular vectors should be computed during
// the decomposition.
GSVDU GSVDKind = 1 << iota
// GSVDV specifies that the V singular vectors should be computed during
// the decomposition.
GSVDV
// GSVDQ specifies that the Q singular vectors should be computed during
// the decomposition.
GSVDQ
// GSVDAll is a convenience value for computing all of the singular vectors.
GSVDAll = GSVDU | GSVDV | GSVDQ
)
// GSVD is a type for creating and using the Generalized Singular Value Decomposition
// (GSVD) of a matrix.
//
@@ -28,12 +51,17 @@ type GSVD struct {
iwork []int
}
// succFact returns whether the receiver contains a successful factorization.
func (gsvd *GSVD) succFact() bool {
return gsvd.r != 0
}
// Factorize computes the generalized singular value decomposition (GSVD) of the input
// the r×c matrix A and the p×c matrix B. The singular values of A and B are computed
// in all cases, while the singular vectors are optionally computed depending on the
// input kind.
//
// The full singular value decomposition (kind == GSVDU|GSVDV|GSVDQ) deconstructs A and B as
// The full singular value decomposition (kind == GSVDAll) deconstructs A and B as
// A = U * Σ₁ * [ 0 R ] * Q^T
//
// B = V * Σ₂ * [ 0 R ] * Q^T
@@ -49,6 +77,10 @@ type GSVD struct {
// Factorize returns whether the decomposition succeeded. If the decomposition
// failed, routines that require a successful factorization will panic.
func (gsvd *GSVD) Factorize(a, b Matrix, kind GSVDKind) (ok bool) {
// kill the previous decomposition
gsvd.r = 0
gsvd.kind = 0
r, c := a.Dims()
gsvd.r, gsvd.c = r, c
p, c := b.Dims()
@@ -64,7 +96,7 @@ func (gsvd *GSVD) Factorize(a, b Matrix, kind GSVDKind) (ok bool) {
jobU = lapack.GSVDNone
jobV = lapack.GSVDNone
jobQ = lapack.GSVDNone
case (GSVDU|GSVDV|GSVDQ)&kind != 0:
case GSVDAll&kind != 0:
if GSVDU&kind != 0 {
jobU = lapack.GSVDU
gsvd.u = blas64.General{
@@ -115,9 +147,12 @@ func (gsvd *GSVD) Factorize(a, b Matrix, kind GSVDKind) (ok bool) {
return ok
}
// Kind returns the matrix.GSVDKind of the decomposition. If no decomposition has been
// computed, Kind returns 0.
// Kind returns the GSVDKind of the decomposition. If no decomposition has been
// computed, Kind returns -1.
func (gsvd *GSVD) Kind() GSVDKind {
if !gsvd.succFact() {
return -1
}
return gsvd.kind
}
@@ -134,8 +169,8 @@ func (gsvd *GSVD) Rank() (k, l int) {
//
// GeneralizedValues will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) GeneralizedValues(v []float64) []float64 {
if gsvd.kind == 0 {
panic("gsvd: no decomposition computed")
if !gsvd.succFact() {
panic(badFact)
}
r := gsvd.r
c := gsvd.c
@@ -159,8 +194,8 @@ func (gsvd *GSVD) GeneralizedValues(v []float64) []float64 {
//
// ValuesA will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) ValuesA(s []float64) []float64 {
if gsvd.kind == 0 {
panic("gsvd: no decomposition computed")
if !gsvd.succFact() {
panic(badFact)
}
r := gsvd.r
c := gsvd.c
@@ -184,8 +219,8 @@ func (gsvd *GSVD) ValuesA(s []float64) []float64 {
//
// ValuesB will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) ValuesB(s []float64) []float64 {
if gsvd.kind == 0 {
panic("gsvd: no decomposition computed")
if !gsvd.succFact() {
panic(badFact)
}
r := gsvd.r
c := gsvd.c
@@ -207,8 +242,8 @@ func (gsvd *GSVD) ValuesB(s []float64) []float64 {
//
// ZeroRTo will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) ZeroRTo(dst *Dense) *Dense {
if gsvd.kind == 0 {
panic("gsvd: no decomposition computed")
if !gsvd.succFact() {
panic(badFact)
}
r := gsvd.r
c := gsvd.c
@@ -245,8 +280,8 @@ func (gsvd *GSVD) ZeroRTo(dst *Dense) *Dense {
//
// SigmaATo will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) SigmaATo(dst *Dense) *Dense {
if gsvd.kind == 0 {
panic("gsvd: no decomposition computed")
if !gsvd.succFact() {
panic(badFact)
}
r := gsvd.r
k := gsvd.k
@@ -271,8 +306,8 @@ func (gsvd *GSVD) SigmaATo(dst *Dense) *Dense {
//
// SigmaBTo will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) SigmaBTo(dst *Dense) *Dense {
if gsvd.kind == 0 {
panic("gsvd: no decomposition computed")
if !gsvd.succFact() {
panic(badFact)
}
r := gsvd.r
p := gsvd.p
@@ -298,6 +333,9 @@ func (gsvd *GSVD) SigmaBTo(dst *Dense) *Dense {
//
// UTo will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) UTo(dst *Dense) *Dense {
if !gsvd.succFact() {
panic(badFact)
}
if gsvd.kind&GSVDU == 0 {
panic("mat: improper GSVD kind")
}
@@ -324,6 +362,9 @@ func (gsvd *GSVD) UTo(dst *Dense) *Dense {
//
// VTo will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) VTo(dst *Dense) *Dense {
if !gsvd.succFact() {
panic(badFact)
}
if gsvd.kind&GSVDV == 0 {
panic("mat: improper GSVD kind")
}
@@ -350,6 +391,9 @@ func (gsvd *GSVD) VTo(dst *Dense) *Dense {
//
// QTo will panic if the receiver does not contain a successful factorization.
func (gsvd *GSVD) QTo(dst *Dense) *Dense {
if !gsvd.succFact() {
panic(badFact)
}
if gsvd.kind&GSVDQ == 0 {
panic("mat: improper GSVD kind")
}