mirror of
				https://github.com/gonum/gonum.git
				synced 2025-10-31 18:42:45 +08:00 
			
		
		
		
	matrix/mat64: reverse API signatures for matrix extraction
This commit is contained in:
		| @@ -203,9 +203,9 @@ func (gsvd *GSVD) ValuesB(s []float64) []float64 { | |||||||
| 	return s | 	return s | ||||||
| } | } | ||||||
|  |  | ||||||
| // ZeroRFromGSVD extracts the matrix [ 0 R ] from the singular value decomposition, storing | // ZeroRTo extracts the matrix [ 0 R ] from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. [ 0 R ] is size (k+l)×c. | // the result in-place into dst. [ 0 R ] is size (k+l)×c. | ||||||
| func (m *Dense) ZeroRFromGSVD(gsvd *GSVD) { | func (gsvd *GSVD) ZeroRTo(dst *Dense) { | ||||||
| 	if gsvd.kind == 0 { | 	if gsvd.kind == 0 { | ||||||
| 		panic("gsvd: no decomposition computed") | 		panic("gsvd: no decomposition computed") | ||||||
| 	} | 	} | ||||||
| @@ -214,13 +214,13 @@ func (m *Dense) ZeroRFromGSVD(gsvd *GSVD) { | |||||||
| 	k := gsvd.k | 	k := gsvd.k | ||||||
| 	l := gsvd.l | 	l := gsvd.l | ||||||
| 	h := min(k+l, r) | 	h := min(k+l, r) | ||||||
| 	m.reuseAsZeroed(k+l, c) | 	dst.reuseAsZeroed(k+l, c) | ||||||
| 	a := Dense{ | 	a := Dense{ | ||||||
| 		mat:     gsvd.a, | 		mat:     gsvd.a, | ||||||
| 		capRows: r, | 		capRows: r, | ||||||
| 		capCols: c, | 		capCols: c, | ||||||
| 	} | 	} | ||||||
| 	m.Slice(0, h, c-k-l, c).(*Dense). | 	dst.Slice(0, h, c-k-l, c).(*Dense). | ||||||
| 		Copy(a.Slice(0, h, c-k-l, c)) | 		Copy(a.Slice(0, h, c-k-l, c)) | ||||||
| 	if r < k+l { | 	if r < k+l { | ||||||
| 		b := Dense{ | 		b := Dense{ | ||||||
| @@ -228,32 +228,32 @@ func (m *Dense) ZeroRFromGSVD(gsvd *GSVD) { | |||||||
| 			capRows: gsvd.p, | 			capRows: gsvd.p, | ||||||
| 			capCols: c, | 			capCols: c, | ||||||
| 		} | 		} | ||||||
| 		m.Slice(r, k+l, c+r-k-l, c).(*Dense). | 		dst.Slice(r, k+l, c+r-k-l, c).(*Dense). | ||||||
| 			Copy(b.Slice(r-k, l, c+r-k-l, c)) | 			Copy(b.Slice(r-k, l, c+r-k-l, c)) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // SigmaAFromGSVD extracts the matrix Σ₁ from the singular value decomposition, storing | // SigmaATo extracts the matrix Σ₁ from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. Σ₁ is size r×(k+l). | // the result in-place into dst. Σ₁ is size r×(k+l). | ||||||
| func (m *Dense) SigmaAFromGSVD(gsvd *GSVD) { | func (gsvd *GSVD) SigmaATo(dst *Dense) { | ||||||
| 	if gsvd.kind == 0 { | 	if gsvd.kind == 0 { | ||||||
| 		panic("gsvd: no decomposition computed") | 		panic("gsvd: no decomposition computed") | ||||||
| 	} | 	} | ||||||
| 	r := gsvd.r | 	r := gsvd.r | ||||||
| 	k := gsvd.k | 	k := gsvd.k | ||||||
| 	l := gsvd.l | 	l := gsvd.l | ||||||
| 	m.reuseAsZeroed(r, k+l) | 	dst.reuseAsZeroed(r, k+l) | ||||||
| 	for i := 0; i < k; i++ { | 	for i := 0; i < k; i++ { | ||||||
| 		m.set(i, i, 1) | 		dst.set(i, i, 1) | ||||||
| 	} | 	} | ||||||
| 	for i := k; i < min(r, k+l); i++ { | 	for i := k; i < min(r, k+l); i++ { | ||||||
| 		m.set(i, i, gsvd.s1[i]) | 		dst.set(i, i, gsvd.s1[i]) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // SigmaBFromGSVD extracts the matrix Σ₂ from the singular value decomposition, storing | // SigmaBTo extracts the matrix Σ₂ from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. Σ₂ is size p×(k+l). | // the result in-place into dst. Σ₂ is size p×(k+l). | ||||||
| func (m *Dense) SigmaBFromGSVD(gsvd *GSVD) { | func (gsvd *GSVD) SigmaBTo(dst *Dense) { | ||||||
| 	if gsvd.kind == 0 { | 	if gsvd.kind == 0 { | ||||||
| 		panic("gsvd: no decomposition computed") | 		panic("gsvd: no decomposition computed") | ||||||
| 	} | 	} | ||||||
| @@ -261,65 +261,65 @@ func (m *Dense) SigmaBFromGSVD(gsvd *GSVD) { | |||||||
| 	p := gsvd.p | 	p := gsvd.p | ||||||
| 	k := gsvd.k | 	k := gsvd.k | ||||||
| 	l := gsvd.l | 	l := gsvd.l | ||||||
| 	m.reuseAsZeroed(p, k+l) | 	dst.reuseAsZeroed(p, k+l) | ||||||
| 	for i := 0; i < min(l, r-k); i++ { | 	for i := 0; i < min(l, r-k); i++ { | ||||||
| 		m.set(i, i+k, gsvd.s2[k+i]) | 		dst.set(i, i+k, gsvd.s2[k+i]) | ||||||
| 	} | 	} | ||||||
| 	for i := r - k; i < l; i++ { | 	for i := r - k; i < l; i++ { | ||||||
| 		m.set(i, i+k, 1) | 		dst.set(i, i+k, 1) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // UFromGSVD extracts the matrix U from the singular value decomposition, storing | // UTo extracts the matrix U from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. U is size r×r. | // the result in-place into dst. U is size r×r. | ||||||
| func (m *Dense) UFromGSVD(gsvd *GSVD) { | func (gsvd *GSVD) UTo(dst *Dense) { | ||||||
| 	if gsvd.kind&matrix.GSVDU == 0 { | 	if gsvd.kind&matrix.GSVDU == 0 { | ||||||
| 		panic("mat64: improper GSVD kind") | 		panic("mat64: improper GSVD kind") | ||||||
| 	} | 	} | ||||||
| 	r := gsvd.u.Rows | 	r := gsvd.u.Rows | ||||||
| 	c := gsvd.u.Cols | 	c := gsvd.u.Cols | ||||||
| 	m.reuseAs(r, c) | 	dst.reuseAs(r, c) | ||||||
|  |  | ||||||
| 	tmp := &Dense{ | 	tmp := &Dense{ | ||||||
| 		mat:     gsvd.u, | 		mat:     gsvd.u, | ||||||
| 		capRows: r, | 		capRows: r, | ||||||
| 		capCols: c, | 		capCols: c, | ||||||
| 	} | 	} | ||||||
| 	m.Copy(tmp) | 	dst.Copy(tmp) | ||||||
| } | } | ||||||
|  |  | ||||||
| // VFromGSVD extracts the matrix V from the singular value decomposition, storing | // VTo extracts the matrix V from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. V is size p×p. | // the result in-place into dst. V is size p×p. | ||||||
| func (m *Dense) VFromGSVD(gsvd *GSVD) { | func (gsvd *GSVD) VTo(dst *Dense) { | ||||||
| 	if gsvd.kind&matrix.GSVDV == 0 { | 	if gsvd.kind&matrix.GSVDV == 0 { | ||||||
| 		panic("mat64: improper GSVD kind") | 		panic("mat64: improper GSVD kind") | ||||||
| 	} | 	} | ||||||
| 	r := gsvd.v.Rows | 	r := gsvd.v.Rows | ||||||
| 	c := gsvd.v.Cols | 	c := gsvd.v.Cols | ||||||
| 	m.reuseAs(r, c) | 	dst.reuseAs(r, c) | ||||||
|  |  | ||||||
| 	tmp := &Dense{ | 	tmp := &Dense{ | ||||||
| 		mat:     gsvd.v, | 		mat:     gsvd.v, | ||||||
| 		capRows: r, | 		capRows: r, | ||||||
| 		capCols: c, | 		capCols: c, | ||||||
| 	} | 	} | ||||||
| 	m.Copy(tmp) | 	dst.Copy(tmp) | ||||||
| } | } | ||||||
|  |  | ||||||
| // QFromGSVD extracts the matrix Q from the singular value decomposition, storing | // QTo extracts the matrix Q from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. Q is size c×c. | // the result in-place into dst. Q is size c×c. | ||||||
| func (m *Dense) QFromGSVD(gsvd *GSVD) { | func (gsvd *GSVD) QTo(dst *Dense) { | ||||||
| 	if gsvd.kind&matrix.GSVDQ == 0 { | 	if gsvd.kind&matrix.GSVDQ == 0 { | ||||||
| 		panic("mat64: improper GSVD kind") | 		panic("mat64: improper GSVD kind") | ||||||
| 	} | 	} | ||||||
| 	r := gsvd.q.Rows | 	r := gsvd.q.Rows | ||||||
| 	c := gsvd.q.Cols | 	c := gsvd.q.Cols | ||||||
| 	m.reuseAs(r, c) | 	dst.reuseAs(r, c) | ||||||
|  |  | ||||||
| 	tmp := &Dense{ | 	tmp := &Dense{ | ||||||
| 		mat:     gsvd.q, | 		mat:     gsvd.q, | ||||||
| 		capRows: r, | 		capRows: r, | ||||||
| 		capCols: c, | 		capCols: c, | ||||||
| 	} | 	} | ||||||
| 	m.Copy(tmp) | 	dst.Copy(tmp) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,8 +26,8 @@ func ExampleGSVD() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var u, v mat64.Dense | 	var u, v mat64.Dense | ||||||
| 	u.UFromGSVD(&gsvd) | 	gsvd.UTo(&u) | ||||||
| 	v.VFromGSVD(&gsvd) | 	gsvd.VTo(&v) | ||||||
|  |  | ||||||
| 	s1 := gsvd.ValuesA(nil) | 	s1 := gsvd.ValuesA(nil) | ||||||
| 	s2 := gsvd.ValuesB(nil) | 	s2 := gsvd.ValuesB(nil) | ||||||
| @@ -38,8 +38,8 @@ func ExampleGSVD() { | |||||||
| 		s2, mat64.Formatted(&v, mat64.Prefix("\t    "), mat64.Excerpt(2))) | 		s2, mat64.Formatted(&v, mat64.Prefix("\t    "), mat64.Excerpt(2))) | ||||||
|  |  | ||||||
| 	var zeroR, q mat64.Dense | 	var zeroR, q mat64.Dense | ||||||
| 	zeroR.ZeroRFromGSVD(&gsvd) | 	gsvd.ZeroRTo(&zeroR) | ||||||
| 	q.QFromGSVD(&gsvd) | 	gsvd.QTo(&q) | ||||||
| 	q.Mul(&zeroR, &q) | 	q.Mul(&zeroR, &q) | ||||||
| 	fmt.Printf("\nCommon basis vectors\n\n\tQ^T = %.4f\n", | 	fmt.Printf("\nCommon basis vectors\n\n\tQ^T = %.4f\n", | ||||||
| 		mat64.Formatted(q.T(), mat64.Prefix("\t      "))) | 		mat64.Formatted(q.T(), mat64.Prefix("\t      "))) | ||||||
|   | |||||||
| @@ -107,12 +107,12 @@ func TestGSVD(t *testing.T) { | |||||||
|  |  | ||||||
| func extractGSVD(gsvd *GSVD) (c, s []float64, s1, s2, zR, u, v, q *Dense) { | func extractGSVD(gsvd *GSVD) (c, s []float64, s1, s2, zR, u, v, q *Dense) { | ||||||
| 	var s1m, s2m, zeroR, um, vm, qm Dense | 	var s1m, s2m, zeroR, um, vm, qm Dense | ||||||
| 	s1m.SigmaAFromGSVD(gsvd) | 	gsvd.SigmaATo(&s1m) | ||||||
| 	s2m.SigmaBFromGSVD(gsvd) | 	gsvd.SigmaBTo(&s2m) | ||||||
| 	zeroR.ZeroRFromGSVD(gsvd) | 	gsvd.ZeroRTo(&zeroR) | ||||||
| 	um.UFromGSVD(gsvd) | 	gsvd.UTo(&um) | ||||||
| 	vm.VFromGSVD(gsvd) | 	gsvd.VTo(&vm) | ||||||
| 	qm.QFromGSVD(gsvd) | 	gsvd.QTo(&qm) | ||||||
| 	c = gsvd.ValuesA(nil) | 	c = gsvd.ValuesA(nil) | ||||||
| 	s = gsvd.ValuesB(nil) | 	s = gsvd.ValuesB(nil) | ||||||
| 	return c, s, &s1m, &s2m, &zeroR, &um, &vm, &qm | 	return c, s, &s1m, &s2m, &zeroR, &um, &vm, &qm | ||||||
|   | |||||||
| @@ -141,11 +141,11 @@ func (gsvd *HOGSVD) Len() int { | |||||||
| 	return gsvd.n | 	return gsvd.n | ||||||
| } | } | ||||||
|  |  | ||||||
| // UFromHOGSVD extracts the matrix U_n from the singular value decomposition, storing | // UTo extracts the matrix U_n from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. U_n is size r×c. | // the result in-place into dst. U_n is size r×c. | ||||||
| // | // | ||||||
| // UFromHOGSVD will panic if the receiver does not contain a successful factorization. | // UTo will panic if the receiver does not contain a successful factorization. | ||||||
| func (m *Dense) UFromHOGSVD(gsvd *HOGSVD, n int) { | func (gsvd *HOGSVD) UTo(dst *Dense, n int) { | ||||||
| 	if gsvd.n == 0 { | 	if gsvd.n == 0 { | ||||||
| 		panic("hogsvd: unsuccessful factorization") | 		panic("hogsvd: unsuccessful factorization") | ||||||
| 	} | 	} | ||||||
| @@ -153,10 +153,10 @@ func (m *Dense) UFromHOGSVD(gsvd *HOGSVD, n int) { | |||||||
| 		panic("hogsvd: invalid index") | 		panic("hogsvd: invalid index") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	m.reuseAs(gsvd.b[n].Dims()) | 	dst.reuseAs(gsvd.b[n].Dims()) | ||||||
| 	m.Copy(&gsvd.b[n]) | 	dst.Copy(&gsvd.b[n]) | ||||||
| 	for j, f := range gsvd.Values(nil, n) { | 	for j, f := range gsvd.Values(nil, n) { | ||||||
| 		v := m.ColView(j) | 		v := dst.ColView(j) | ||||||
| 		v.ScaleVec(1/f, v) | 		v.ScaleVec(1/f, v) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -188,13 +188,14 @@ func (gsvd *HOGSVD) Values(s []float64, n int) []float64 { | |||||||
| 	return s | 	return s | ||||||
| } | } | ||||||
|  |  | ||||||
| // VFromHOGSVD extracts the matrix V from the singular value decomposition, storing | // VTo extracts the matrix V from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. V is size c×c. | // the result in-place into dst. V is size c×c. | ||||||
| // | // | ||||||
| // VFromHOGSVD will panic if the receiver does not contain a successful factorization. | // VTo will panic if the receiver does not contain a successful factorization. | ||||||
| func (m *Dense) VFromHOGSVD(gsvd *HOGSVD) { | func (gsvd *HOGSVD) VTo(dst *Dense) { | ||||||
| 	if gsvd.n == 0 { | 	if gsvd.n == 0 { | ||||||
| 		panic("hogsvd: unsuccessful factorization") | 		panic("hogsvd: unsuccessful factorization") | ||||||
| 	} | 	} | ||||||
| 	*m = *DenseCopyOf(gsvd.v) | 	dst.reuseAs(gsvd.v.Dims()) | ||||||
|  | 	dst.Copy(gsvd.v) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -25,14 +25,14 @@ func ExampleHOGSVD() { | |||||||
|  |  | ||||||
| 	for i, n := range []string{"Africa", "Asia", "Latin America/Caribbean", "Oceania"} { | 	for i, n := range []string{"Africa", "Asia", "Latin America/Caribbean", "Oceania"} { | ||||||
| 		var u mat64.Dense | 		var u mat64.Dense | ||||||
| 		u.UFromHOGSVD(&gsvd, i) | 		gsvd.UTo(&u, i) | ||||||
| 		s := gsvd.Values(nil, i) | 		s := gsvd.Values(nil, i) | ||||||
| 		fmt.Printf("%s\n\ts_%d = %.4f\n\n\tU_%[2]d = %.4[4]f\n", | 		fmt.Printf("%s\n\ts_%d = %.4f\n\n\tU_%[2]d = %.4[4]f\n", | ||||||
| 			n, i, s, mat64.Formatted(&u, mat64.Prefix("\t      "))) | 			n, i, s, mat64.Formatted(&u, mat64.Prefix("\t      "))) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var v mat64.Dense | 	var v mat64.Dense | ||||||
| 	v.VFromHOGSVD(&gsvd) | 	gsvd.VTo(&v) | ||||||
| 	fmt.Printf("\nCommon basis vectors\n\n\tV^T = %.4f", | 	fmt.Printf("\nCommon basis vectors\n\n\tV^T = %.4f", | ||||||
| 		mat64.Formatted(v.T(), mat64.Prefix("\t      "))) | 		mat64.Formatted(v.T(), mat64.Prefix("\t      "))) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -80,10 +80,10 @@ func extractHOGSVD(gsvd *HOGSVD) (u []*Dense, s [][]float64, v *Dense) { | |||||||
| 	s = make([][]float64, gsvd.Len()) | 	s = make([][]float64, gsvd.Len()) | ||||||
| 	for i := 0; i < gsvd.Len(); i++ { | 	for i := 0; i < gsvd.Len(); i++ { | ||||||
| 		u[i] = &Dense{} | 		u[i] = &Dense{} | ||||||
| 		u[i].UFromHOGSVD(gsvd, i) | 		gsvd.UTo(u[i], i) | ||||||
| 		s[i] = gsvd.Values(nil, i) | 		s[i] = gsvd.Values(nil, i) | ||||||
| 	} | 	} | ||||||
| 	v = &Dense{} | 	v = &Dense{} | ||||||
| 	v.VFromHOGSVD(gsvd) | 	gsvd.VTo(v) | ||||||
| 	return u, s, v | 	return u, s, v | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ func (lq *LQ) updateCond() { | |||||||
| // | // | ||||||
| // The LQ decomposition is a factorization of the matrix A such that A = L * Q. | // The LQ decomposition is a factorization of the matrix A such that A = L * Q. | ||||||
| // The matrix Q is an orthonormal n×n matrix, and L is an m×n upper triangular matrix. | // The matrix Q is an orthonormal n×n matrix, and L is an m×n upper triangular matrix. | ||||||
| // L and Q can be extracted from the LFromLQ and QFromLQ methods on Dense. | // L and Q can be extracted from the LTo and QTo methods. | ||||||
| func (lq *LQ) Factorize(a Matrix) { | func (lq *LQ) Factorize(a Matrix) { | ||||||
| 	m, n := a.Dims() | 	m, n := a.Dims() | ||||||
| 	if m > n { | 	if m > n { | ||||||
| @@ -58,10 +58,10 @@ func (lq *LQ) Factorize(a Matrix) { | |||||||
| // TODO(btracey): Add in the "Reduced" forms for extracting the m×m orthogonal | // TODO(btracey): Add in the "Reduced" forms for extracting the m×m orthogonal | ||||||
| // and upper triangular matrices. | // and upper triangular matrices. | ||||||
|  |  | ||||||
| // LFromLQ extracts the m×n lower trapezoidal matrix from a LQ decomposition. | // LTo extracts the m×n lower trapezoidal matrix from a LQ decomposition. | ||||||
| func (m *Dense) LFromLQ(lq *LQ) { | func (lq *LQ) LTo(dst *Dense) { | ||||||
| 	r, c := lq.lq.Dims() | 	r, c := lq.lq.Dims() | ||||||
| 	m.reuseAs(r, c) | 	dst.reuseAs(r, c) | ||||||
|  |  | ||||||
| 	// Disguise the LQ as a lower triangular | 	// Disguise the LQ as a lower triangular | ||||||
| 	t := &TriDense{ | 	t := &TriDense{ | ||||||
| @@ -74,25 +74,25 @@ func (m *Dense) LFromLQ(lq *LQ) { | |||||||
| 		}, | 		}, | ||||||
| 		cap: lq.lq.capCols, | 		cap: lq.lq.capCols, | ||||||
| 	} | 	} | ||||||
| 	m.Copy(t) | 	dst.Copy(t) | ||||||
|  |  | ||||||
| 	if r == c { | 	if r == c { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// Zero right of the triangular. | 	// Zero right of the triangular. | ||||||
| 	for i := 0; i < r; i++ { | 	for i := 0; i < r; i++ { | ||||||
| 		zero(m.mat.Data[i*m.mat.Stride+r : i*m.mat.Stride+c]) | 		zero(dst.mat.Data[i*dst.mat.Stride+r : i*dst.mat.Stride+c]) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // QFromLQ extracts the n×n orthonormal matrix Q from an LQ decomposition. | // QTo extracts the n×n orthonormal matrix Q from an LQ decomposition. | ||||||
| func (m *Dense) QFromLQ(lq *LQ) { | func (lq *LQ) QTo(dst *Dense) { | ||||||
| 	r, c := lq.lq.Dims() | 	r, c := lq.lq.Dims() | ||||||
| 	m.reuseAs(c, c) | 	dst.reuseAs(c, c) | ||||||
|  |  | ||||||
| 	// Set Q = I. | 	// Set Q = I. | ||||||
| 	for i := 0; i < c; i++ { | 	for i := 0; i < c; i++ { | ||||||
| 		v := m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c] | 		v := dst.mat.Data[i*dst.mat.Stride : i*dst.mat.Stride+c] | ||||||
| 		zero(v) | 		zero(v) | ||||||
| 		v[i] = 1 | 		v[i] = 1 | ||||||
| 	} | 	} | ||||||
| @@ -127,10 +127,10 @@ func (m *Dense) QFromLQ(lq *LQ) { | |||||||
|  |  | ||||||
| 		// Compute the multiplication matrix. | 		// Compute the multiplication matrix. | ||||||
| 		blas64.Ger(-lq.tau[i], v, v, h) | 		blas64.Ger(-lq.tau[i], v, v, h) | ||||||
| 		qCopy.Copy(m) | 		qCopy.Copy(dst) | ||||||
| 		blas64.Gemm(blas.NoTrans, blas.NoTrans, | 		blas64.Gemm(blas.NoTrans, blas.NoTrans, | ||||||
| 			1, h, qCopy.mat, | 			1, h, qCopy.mat, | ||||||
| 			0, m.mat) | 			0, dst.mat) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,16 +27,16 @@ func TestLQ(t *testing.T) { | |||||||
| 		var want Dense | 		var want Dense | ||||||
| 		want.Clone(a) | 		want.Clone(a) | ||||||
|  |  | ||||||
| 		lq := &LQ{} | 		var lq LQ | ||||||
| 		lq.Factorize(a) | 		lq.Factorize(a) | ||||||
| 		var l, q Dense | 		var l, q Dense | ||||||
| 		q.QFromLQ(lq) | 		lq.QTo(&q) | ||||||
|  |  | ||||||
| 		if !isOrthonormal(&q, 1e-10) { | 		if !isOrthonormal(&q, 1e-10) { | ||||||
| 			t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n) | 			t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		l.LFromLQ(lq) | 		lq.LTo(&l) | ||||||
|  |  | ||||||
| 		var got Dense | 		var got Dense | ||||||
| 		got.Mul(&l, &q) | 		got.Mul(&l, &q) | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ func (lu *LU) updateCond(norm float64) { | |||||||
| // The LU factorization is computed with pivoting, and so really the decomposition | // The LU factorization is computed with pivoting, and so really the decomposition | ||||||
| // is a PLU decomposition where P is a permutation matrix. The individual matrix | // is a PLU decomposition where P is a permutation matrix. The individual matrix | ||||||
| // factors can be extracted from the factorization using the Permutation method | // factors can be extracted from the factorization using the Permutation method | ||||||
| // on Dense, and the LFrom and UFrom methods on TriDense. | // on Dense, and the LU LTo and UTo methods. | ||||||
| func (lu *LU) Factorize(a Matrix) { | func (lu *LU) Factorize(a Matrix) { | ||||||
| 	r, c := a.Dims() | 	r, c := a.Dims() | ||||||
| 	if r != c { | 	if r != c { | ||||||
| @@ -204,30 +204,30 @@ func (lu *LU) RankOne(orig *LU, alpha float64, x, y *Vector) { | |||||||
| 	lu.updateCond(-1) | 	lu.updateCond(-1) | ||||||
| } | } | ||||||
|  |  | ||||||
| // LFromLU extracts the lower triangular matrix from an LU factorization. | // LTo extracts the lower triangular matrix from an LU factorization. | ||||||
| func (t *TriDense) LFromLU(lu *LU) { | func (lu *LU) LTo(dst *TriDense) { | ||||||
| 	_, n := lu.lu.Dims() | 	_, n := lu.lu.Dims() | ||||||
| 	t.reuseAs(n, false) | 	dst.reuseAs(n, false) | ||||||
| 	// Extract the lower triangular elements. | 	// Extract the lower triangular elements. | ||||||
| 	for i := 0; i < n; i++ { | 	for i := 0; i < n; i++ { | ||||||
| 		for j := 0; j < i; j++ { | 		for j := 0; j < i; j++ { | ||||||
| 			t.mat.Data[i*t.mat.Stride+j] = lu.lu.mat.Data[i*lu.lu.mat.Stride+j] | 			dst.mat.Data[i*dst.mat.Stride+j] = lu.lu.mat.Data[i*lu.lu.mat.Stride+j] | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// Set ones on the diagonal. | 	// Set ones on the diagonal. | ||||||
| 	for i := 0; i < n; i++ { | 	for i := 0; i < n; i++ { | ||||||
| 		t.mat.Data[i*t.mat.Stride+i] = 1 | 		dst.mat.Data[i*dst.mat.Stride+i] = 1 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // UFromLU extracts the upper triangular matrix from an LU factorization. | // UTo extracts the upper triangular matrix from an LU factorization. | ||||||
| func (t *TriDense) UFromLU(lu *LU) { | func (lu *LU) UTo(dst *TriDense) { | ||||||
| 	_, n := lu.lu.Dims() | 	_, n := lu.lu.Dims() | ||||||
| 	t.reuseAs(n, true) | 	dst.reuseAs(n, true) | ||||||
| 	// Extract the upper triangular elements. | 	// Extract the upper triangular elements. | ||||||
| 	for i := 0; i < n; i++ { | 	for i := 0; i < n; i++ { | ||||||
| 		for j := i; j < n; j++ { | 		for j := i; j < n; j++ { | ||||||
| 			t.mat.Data[i*t.mat.Stride+j] = lu.lu.mat.Data[i*lu.lu.mat.Stride+j] | 			dst.mat.Data[i*dst.mat.Stride+j] = lu.lu.mat.Data[i*lu.lu.mat.Stride+j] | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,12 +20,12 @@ func TestLUD(t *testing.T) { | |||||||
| 		var want Dense | 		var want Dense | ||||||
| 		want.Clone(a) | 		want.Clone(a) | ||||||
|  |  | ||||||
| 		lu := &LU{} | 		var lu LU | ||||||
| 		lu.Factorize(a) | 		lu.Factorize(a) | ||||||
|  |  | ||||||
| 		var l, u TriDense | 		var l, u TriDense | ||||||
| 		l.LFromLU(lu) | 		lu.LTo(&l) | ||||||
| 		u.UFromLU(lu) | 		lu.UTo(&u) | ||||||
| 		var p Dense | 		var p Dense | ||||||
| 		pivot := lu.Pivot(nil) | 		pivot := lu.Pivot(nil) | ||||||
| 		p.Permutation(n, pivot) | 		p.Permutation(n, pivot) | ||||||
| @@ -93,8 +93,8 @@ func TestLURankOne(t *testing.T) { | |||||||
| // luReconstruct reconstructs the original A matrix from an LU decomposition. | // luReconstruct reconstructs the original A matrix from an LU decomposition. | ||||||
| func luReconstruct(lu *LU) *Dense { | func luReconstruct(lu *LU) *Dense { | ||||||
| 	var L, U TriDense | 	var L, U TriDense | ||||||
| 	L.LFromLU(lu) | 	lu.LTo(&L) | ||||||
| 	U.UFromLU(lu) | 	lu.UTo(&U) | ||||||
| 	var P Dense | 	var P Dense | ||||||
| 	pivot := lu.Pivot(nil) | 	pivot := lu.Pivot(nil) | ||||||
| 	P.Permutation(len(pivot), pivot) | 	P.Permutation(len(pivot), pivot) | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ func (qr *QR) updateCond() { | |||||||
| // | // | ||||||
| // The QR decomposition is a factorization of the matrix A such that A = Q * R. | // The QR decomposition is a factorization of the matrix A such that A = Q * R. | ||||||
| // The matrix Q is an orthonormal m×m matrix, and R is an m×n upper triangular matrix. | // The matrix Q is an orthonormal m×m matrix, and R is an m×n upper triangular matrix. | ||||||
| // Q and R can be extracted from the QFromQR and RFromQR methods on Dense. | // Q and R can be extracted using the QTo and RTo methods. | ||||||
| func (qr *QR) Factorize(a Matrix) { | func (qr *QR) Factorize(a Matrix) { | ||||||
| 	m, n := a.Dims() | 	m, n := a.Dims() | ||||||
| 	if m < n { | 	if m < n { | ||||||
| @@ -60,10 +60,10 @@ func (qr *QR) Factorize(a Matrix) { | |||||||
| // TODO(btracey): Add in the "Reduced" forms for extracting the n×n orthogonal | // TODO(btracey): Add in the "Reduced" forms for extracting the n×n orthogonal | ||||||
| // and upper triangular matrices. | // and upper triangular matrices. | ||||||
|  |  | ||||||
| // RFromQR extracts the m×n upper trapezoidal matrix from a QR decomposition. | // RTo extracts the m×n upper trapezoidal matrix from a QR decomposition. | ||||||
| func (m *Dense) RFromQR(qr *QR) { | func (qr *QR) RTo(dst *Dense) { | ||||||
| 	r, c := qr.qr.Dims() | 	r, c := qr.qr.Dims() | ||||||
| 	m.reuseAs(r, c) | 	dst.reuseAs(r, c) | ||||||
|  |  | ||||||
| 	// Disguise the QR as an upper triangular | 	// Disguise the QR as an upper triangular | ||||||
| 	t := &TriDense{ | 	t := &TriDense{ | ||||||
| @@ -76,29 +76,29 @@ func (m *Dense) RFromQR(qr *QR) { | |||||||
| 		}, | 		}, | ||||||
| 		cap: qr.qr.capCols, | 		cap: qr.qr.capCols, | ||||||
| 	} | 	} | ||||||
| 	m.Copy(t) | 	dst.Copy(t) | ||||||
|  |  | ||||||
| 	// Zero below the triangular. | 	// Zero below the triangular. | ||||||
| 	for i := r; i < c; i++ { | 	for i := r; i < c; i++ { | ||||||
| 		zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) | 		zero(dst.mat.Data[i*dst.mat.Stride : i*dst.mat.Stride+c]) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // QFromQR extracts the m×m orthonormal matrix Q from a QR decomposition. | // QTo extracts the m×m orthonormal matrix Q from a QR decomposition. | ||||||
| func (m *Dense) QFromQR(qr *QR) { | func (qr *QR) QTo(dst *Dense) { | ||||||
| 	r, _ := qr.qr.Dims() | 	r, _ := qr.qr.Dims() | ||||||
| 	m.reuseAsZeroed(r, r) | 	dst.reuseAsZeroed(r, r) | ||||||
|  |  | ||||||
| 	// Set Q = I. | 	// Set Q = I. | ||||||
| 	for i := 0; i < r*r; i += r + 1 { | 	for i := 0; i < r*r; i += r + 1 { | ||||||
| 		m.mat.Data[i] = 1 | 		dst.mat.Data[i] = 1 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Construct Q from the elementary reflectors. | 	// Construct Q from the elementary reflectors. | ||||||
| 	work := make([]float64, 1) | 	work := make([]float64, 1) | ||||||
| 	lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, m.mat, work, -1) | 	lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, dst.mat, work, -1) | ||||||
| 	work = make([]float64, int(work[0])) | 	work = make([]float64, int(work[0])) | ||||||
| 	lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, m.mat, work, len(work)) | 	lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, dst.mat, work, len(work)) | ||||||
| } | } | ||||||
|  |  | ||||||
| // SolveQR finds a minimum-norm solution to a system of linear equations defined | // SolveQR finds a minimum-norm solution to a system of linear equations defined | ||||||
|   | |||||||
| @@ -30,16 +30,16 @@ func TestQR(t *testing.T) { | |||||||
| 		var want Dense | 		var want Dense | ||||||
| 		want.Clone(a) | 		want.Clone(a) | ||||||
|  |  | ||||||
| 		qr := &QR{} | 		var qr QR | ||||||
| 		qr.Factorize(a) | 		qr.Factorize(a) | ||||||
| 		var q, r Dense | 		var q, r Dense | ||||||
| 		q.QFromQR(qr) | 		qr.QTo(&q) | ||||||
|  |  | ||||||
| 		if !isOrthonormal(&q, 1e-10) { | 		if !isOrthonormal(&q, 1e-10) { | ||||||
| 			t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n) | 			t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		r.RFromQR(qr) | 		qr.RTo(&r) | ||||||
|  |  | ||||||
| 		var got Dense | 		var got Dense | ||||||
| 		got.Mul(&q, &r) | 		got.Mul(&q, &r) | ||||||
|   | |||||||
| @@ -138,42 +138,42 @@ func (svd *SVD) Values(s []float64) []float64 { | |||||||
| 	return s | 	return s | ||||||
| } | } | ||||||
|  |  | ||||||
| // UFromSVD extracts the matrix U from the singular value decomposition, storing | // UTo extracts the matrix U from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. U is size m×m if svd.Kind() == SVDFull, | // the result in-place into dst. U is size m×m if svd.Kind() == SVDFull, | ||||||
| // of size m×min(m,n) if svd.Kind() == SVDThin, and UFromSVD panics otherwise. | // of size m×min(m,n) if svd.Kind() == SVDThin, and UTo panics otherwise. | ||||||
| func (m *Dense) UFromSVD(svd *SVD) { | func (svd *SVD) UTo(dst *Dense) { | ||||||
| 	kind := svd.kind | 	kind := svd.kind | ||||||
| 	if kind != matrix.SVDFull && kind != matrix.SVDThin { | 	if kind != matrix.SVDFull && kind != matrix.SVDThin { | ||||||
| 		panic("mat64: improper SVD kind") | 		panic("mat64: improper SVD kind") | ||||||
| 	} | 	} | ||||||
| 	r := svd.u.Rows | 	r := svd.u.Rows | ||||||
| 	c := svd.u.Cols | 	c := svd.u.Cols | ||||||
| 	m.reuseAs(r, c) | 	dst.reuseAs(r, c) | ||||||
|  |  | ||||||
| 	tmp := &Dense{ | 	tmp := &Dense{ | ||||||
| 		mat:     svd.u, | 		mat:     svd.u, | ||||||
| 		capRows: r, | 		capRows: r, | ||||||
| 		capCols: c, | 		capCols: c, | ||||||
| 	} | 	} | ||||||
| 	m.Copy(tmp) | 	dst.Copy(tmp) | ||||||
| } | } | ||||||
|  |  | ||||||
| // VFromSVD extracts the matrix V from the singular value decomposition, storing | // VTo extracts the matrix V from the singular value decomposition, storing | ||||||
| // the result in-place into the receiver. V is size n×n if svd.Kind() == SVDFull, | // the result in-place into dst. V is size n×n if svd.Kind() == SVDFull, | ||||||
| // of size n×min(m,n) if svd.Kind() == SVDThin, and VFromSVD panics otherwise. | // of size n×min(m,n) if svd.Kind() == SVDThin, and VTo panics otherwise. | ||||||
| func (m *Dense) VFromSVD(svd *SVD) { | func (svd *SVD) VTo(dst *Dense) { | ||||||
| 	kind := svd.kind | 	kind := svd.kind | ||||||
| 	if kind != matrix.SVDFull && kind != matrix.SVDThin { | 	if kind != matrix.SVDFull && kind != matrix.SVDThin { | ||||||
| 		panic("mat64: improper SVD kind") | 		panic("mat64: improper SVD kind") | ||||||
| 	} | 	} | ||||||
| 	r := svd.vt.Rows | 	r := svd.vt.Rows | ||||||
| 	c := svd.vt.Cols | 	c := svd.vt.Cols | ||||||
| 	m.reuseAs(c, r) | 	dst.reuseAs(c, r) | ||||||
|  |  | ||||||
| 	tmp := &Dense{ | 	tmp := &Dense{ | ||||||
| 		mat:     svd.vt, | 		mat:     svd.vt, | ||||||
| 		capRows: r, | 		capRows: r, | ||||||
| 		capCols: c, | 		capCols: c, | ||||||
| 	} | 	} | ||||||
| 	m.Copy(tmp.T()) | 	dst.Copy(tmp.T()) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -170,8 +170,8 @@ func TestSVD(t *testing.T) { | |||||||
|  |  | ||||||
| func extractSVD(svd *SVD) (s []float64, u, v *Dense) { | func extractSVD(svd *SVD) (s []float64, u, v *Dense) { | ||||||
| 	var um, vm Dense | 	var um, vm Dense | ||||||
| 	um.UFromSVD(svd) | 	svd.UTo(&um) | ||||||
| 	vm.VFromSVD(svd) | 	svd.VTo(&vm) | ||||||
| 	s = svd.Values(nil) | 	s = svd.Values(nil) | ||||||
| 	return s, &um, &vm | 	return s, &um, &vm | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 kortschak
					kortschak