// test: C = C*Q.T func TestQLMultRightTrans(t *testing.T) { var d, di0, di1 cmat.FloatMatrix M := 891 N := 853 lb := 36 conf := gomas.NewConf() A := cmat.NewMatrix(M, N) src := cmat.NewFloatNormSource() A.SetFrom(src) C0 := cmat.NewMatrix(N, M) d.Diag(C0, M-N) ones := cmat.NewFloatConstSource(1.0) d.SetFrom(ones) C1 := cmat.NewCopy(C0) I0 := cmat.NewMatrix(N, N) I1 := cmat.NewCopy(I0) di0.Diag(I0) di1.Diag(I1) tau := cmat.NewMatrix(N, 1) W := cmat.NewMatrix(lb*(M+N), 1) conf.LB = lb lapackd.QLFactor(A, tau, W, conf) conf.LB = 0 lapackd.QLMult(C0, A, tau, W, gomas.RIGHT|gomas.TRANS, conf) // I = Q*Q.T - I blasd.Mult(I0, C0, C0, 1.0, 0.0, gomas.TRANSB, conf) blasd.Add(&di0, -1.0) n0 := lapackd.NormP(I0, lapackd.NORM_ONE) conf.LB = lb lapackd.QLMult(C1, A, tau, W, gomas.RIGHT|gomas.TRANS, conf) // I = Q*Q.T - I blasd.Mult(I1, C1, C1, 1.0, 0.0, gomas.TRANSB, conf) blasd.Add(&di1, -1.0) n1 := lapackd.NormP(I1, lapackd.NORM_ONE) if N < 10 { t.Logf("unblk C0*Q:\n%v\n", C0) t.Logf("blk. C2*Q:\n%v\n", C1) } blasd.Plus(C0, C1, 1.0, -1.0, gomas.NONE) n2 := lapackd.NormP(C0, lapackd.NORM_ONE) t.Logf("M=%d, N=%d ||unblk.QLMult(C) - blk.QLMult(C)||_1: %e\n", M, N, n2) t.Logf("unblk M=%d, N=%d ||I - Q*Q.T||_1: %e\n", M, N, n0) t.Logf("blk M=%d, N=%d ||I - Q*Q.T||_1: %e\n", M, N, n1) }
func TestQLBuildwithK(t *testing.T) { var dc cmat.FloatMatrix M := 711 N := 707 K := 691 lb := 36 conf := gomas.NewConf() A := cmat.NewMatrix(M, N) src := cmat.NewFloatNormSource() A.SetFrom(src) tau := cmat.NewMatrix(N, 1) W := cmat.NewMatrix(M+N, 1) C := cmat.NewMatrix(N, N) conf.LB = lb lapackd.QLFactor(A, tau, W, conf) A1 := cmat.NewCopy(A) conf.LB = 0 lapackd.QLBuild(A, tau, W, K, conf) blasd.Mult(C, A, A, 1.0, 0.0, gomas.TRANSA, conf) dc.Diag(C) blasd.Add(&dc, -1.0) if N < 10 { t.Logf("unblk.QLBuild Q:\n%v\n", A) t.Logf("unblk.QLBuild Q.T*Q:\n%v\n", C) } n0 := lapackd.NormP(C, lapackd.NORM_ONE) conf.LB = lb W1 := lapackd.Workspace(lapackd.QLBuildWork(A1, conf)) lapackd.QLBuild(A1, tau, W1, K, conf) if N < 10 { t.Logf("blk.QLBuild Q:\n%v\n", A1) } // compute: I - Q.T*Q blasd.Mult(C, A1, A1, 1.0, 0.0, gomas.TRANSA, conf) blasd.Add(&dc, -1.0) n1 := lapackd.NormP(C, lapackd.NORM_ONE) blasd.Plus(A, A1, 1.0, -1.0, gomas.NONE) n2 := lapackd.NormP(A, lapackd.NORM_ONE) t.Logf("M=%d, N=%d, K=%d ||unblk.QLBuild(A) - blk.QLBuild(A)||_1 :%e\n", M, N, K, n2) t.Logf("unblk M=%d, N=%d, K=%d ||Q.T*Q - I||_1 : %e\n", M, N, K, n0) t.Logf("blk M=%d, N=%d, K=%d ||Q.T*Q - I||_1 : %e\n", M, N, K, n1) }
func TestLQBuild(t *testing.T) { var dc cmat.FloatMatrix M := 877 N := 913 K := 831 lb := 48 conf := gomas.NewConf() _ = lb A := cmat.NewMatrix(M, N) src := cmat.NewFloatNormSource() A.SetFrom(src) tau := cmat.NewMatrix(M, 1) W := cmat.NewMatrix(M, 1) C := cmat.NewMatrix(M, M) dc.Diag(C) conf.LB = lb lapackd.LQFactor(A, tau, W, conf) A1 := cmat.NewCopy(A) conf.LB = 0 lapackd.LQBuild(A, tau, W, K, conf) if N < 10 { t.Logf("unblk.LQBuild Q:\n%v\n", A) } blasd.Mult(C, A, A, 1.0, 0.0, gomas.TRANSB, conf) blasd.Add(&dc, -1.0) n0 := lapackd.NormP(C, lapackd.NORM_ONE) conf.LB = lb W2 := lapackd.Workspace(lapackd.LQBuildWork(A, conf)) lapackd.LQBuild(A1, tau, W2, K, conf) if N < 10 { t.Logf("blk.LQBuild Q:\n%v\n", A1) } blasd.Mult(C, A1, A1, 1.0, 0.0, gomas.TRANSB, conf) blasd.Add(&dc, -1.0) n1 := lapackd.NormP(C, lapackd.NORM_ONE) blasd.Plus(A, A1, 1.0, -1.0, gomas.NONE) n2 := lapackd.NormP(A, lapackd.NORM_ONE) t.Logf("M=%d, N=%d, K=%d ||unblk.LQBuild(A) - blk.LQBuild(A)||_1 :%e\n", M, N, K, n2) t.Logf("unblk M=%d, N=%d, K=%d ||I - Q*Q.T||_1 : %e\n", M, N, K, n0) t.Logf(" blk M=%d, N=%d, K=%d ||I - Q*Q.T||_1 : %e\n", M, N, K, n1) }
func TestQRBuild(t *testing.T) { var d cmat.FloatMatrix M := 911 N := 899 K := 873 lb := 36 conf := gomas.NewConf() A := cmat.NewMatrix(M, N) src := cmat.NewFloatNormSource() A.SetFrom(src) tau := cmat.NewMatrix(N, 1) W := cmat.NewMatrix(N+M, 1) C := cmat.NewMatrix(N, N) d.Diag(C) conf.LB = lb lapackd.QRFactor(A, tau, W, conf) A1 := cmat.NewCopy(A) conf.LB = 0 lapackd.QRBuild(A, tau, W, K, conf) blasd.Mult(C, A, A, 1.0, 0.0, gomas.TRANSA, conf) blasd.Add(&d, -1.0) n0 := lapackd.NormP(C, lapackd.NORM_ONE) conf.LB = lb W2 := lapackd.Workspace(lapackd.QRBuildWork(A, conf)) lapackd.QRBuild(A1, tau, W2, K, conf) blasd.Mult(C, A1, A1, 1.0, 0.0, gomas.TRANSA, conf) blasd.Add(&d, -1.0) n1 := lapackd.NormP(C, lapackd.NORM_ONE) blasd.Plus(A, A1, 1.0, -1.0, gomas.NONE) n2 := lapackd.NormP(A, lapackd.NORM_ONE) t.Logf("M=%d, N=%d, K=%d ||unblk.QRBuild(A) - blk.QRBuild(A)||_1 :%e\n", M, N, K, n2) t.Logf("unblk M=%d, N=%d, K=%d ||I - Q.T*Q||_1: %e\n", M, N, K, n0) t.Logf(" blk M=%d, N=%d, K=%d ||I - Q.T*Q||_1: %e\n", M, N, K, n1) }
/* * Unblocked code for generating M by N matrix Q with orthogonal columns which * are defined as the first N columns of the product of K first elementary * reflectors. * * Parameters nk = n(A)-K, mk = m(A)-K define the initial partitioning of * matrix A. * * Q = H(k)H(k-1)...H(1) , 0 < k <= M, where H(i) = I - tau*v*v.T * * Computation is ordered as H(k)*H(k-1)...*H(1)*I ie. from bottom to top. * * If k < M rows k+1:M are cleared and diagonal entries [k+1:M,k+1:M] are * set to unit. Then the matrix Q is generated by right multiplying elements below * of i'th elementary reflector H(i). * * Compatible to lapack.xORG2L subroutine. */ func unblkBuildLQ(A, Tvec, W *cmat.FloatMatrix, mk, nk int, mayClear bool) { var ATL, ATR, ABL, ABR cmat.FloatMatrix var A00, a10, a11, a12, a21, A22 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau1, t2, w12, D cmat.FloatMatrix util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, mk, nk, util.PBOTTOMRIGHT) util.Partition2x1( &tT, &tB, Tvec, mk, util.PBOTTOM) // zero the bottom part if mk > 0 && mayClear { blasd.Scale(&ABL, 0.0) blasd.Scale(&ABR, 0.0) D.Diag(&ABR) blasd.Add(&D, 1.0) } for m(&ATL) > 0 && n(&ATL) > 0 { util.Repartition2x2to3x3(&ATL, &A00, nil, nil, &a10, &a11, &a12, nil, &a21, &A22, A, 1, util.PTOPLEFT) util.Repartition2x1to3x1(&tT, &t0, &tau1, &t2, Tvec, 1, util.PTOP) // ------------------------------------------------------ w12.SubMatrix(W, 0, 0, a21.Len(), 1) applyHouseholder2x1(&tau1, &a12, &a21, &A22, &w12, gomas.RIGHT) blasd.Scale(&a12, -tau1.Get(0, 0)) a11.Set(0, 0, 1.0-tau1.Get(0, 0)) // zero blasd.Scale(&a10, 0.0) // ------------------------------------------------------ util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &a11, &A22, A, util.PTOPLEFT) util.Continue3x1to2x1( &tT, &tB, &t0, &tau1, Tvec, util.PTOP) } }
/* * Unblocked code for generating M by N matrix Q with orthogonal columns which * are defined as the last N columns of the product of K first elementary * reflectors. * * Parameter nk is last nk elementary reflectors that are not used in computing * the matrix Q. Parameter mk length of the first unused elementary reflectors * First nk columns are zeroed and subdiagonal mk-nk is set to unit. * * Compatible with lapack.DORG2L subroutine. */ func unblkBuildQL(A, Tvec, W *cmat.FloatMatrix, mk, nk int, mayClear bool) { var ATL, ATR, ABL, ABR cmat.FloatMatrix var A00, a01, a10, a11, a21, A22 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau1, t2, w12, D cmat.FloatMatrix // (mk, nk) = (rows, columns) of upper left partition util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, mk, nk, util.PTOPLEFT) util.Partition2x1( &tT, &tB, Tvec, nk, util.PTOP) // zero the left side if nk > 0 && mayClear { blasd.Scale(&ABL, 0.0) blasd.Scale(&ATL, 0.0) D.Diag(&ATL, nk-mk) blasd.Add(&D, 1.0) } for m(&ABR) > 0 && n(&ABR) > 0 { util.Repartition2x2to3x3(&ATL, &A00, &a01, nil, &a10, &a11, nil, nil, &a21, &A22, A, 1, util.PBOTTOMRIGHT) util.Repartition2x1to3x1(&tT, &t0, &tau1, &t2, Tvec, 1, util.PBOTTOM) // ------------------------------------------------------ w12.SubMatrix(W, 0, 0, a10.Len(), 1) applyHouseholder2x1(&tau1, &a01, &a10, &A00, &w12, gomas.LEFT) blasd.Scale(&a01, -tau1.Get(0, 0)) a11.Set(0, 0, 1.0-tau1.Get(0, 0)) // zero bottom elements blasd.Scale(&a21, 0.0) // ------------------------------------------------------ util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT) util.Continue3x1to2x1( &tT, &tB, &t0, &tau1, Tvec, util.PBOTTOM) } }
func testEigen(N int, bits int, t *testing.T) { var A, A0, W, D, V *cmat.FloatMatrix var sD cmat.FloatMatrix var s string = "lower" if bits&gomas.UPPER != 0 { s = "upper" } wsize := N * N if wsize < 100 { wsize = 100 } D = cmat.NewMatrix(N, 1) A = cmat.NewMatrix(N, N) V = cmat.NewMatrix(N, N) src := cmat.NewFloatNormSource() A.SetFrom(src, cmat.SYMM) A0 = cmat.NewCopy(A) W = cmat.NewMatrix(wsize, 1) if err := lapackd.EigenSym(D, A, W, bits|gomas.WANTV); err != nil { t.Errorf("EigenSym error: %v\n", err) return } // ||I - V.T*V|| sD.Diag(V) blasd.Mult(V, A, A, 1.0, 0.0, gomas.TRANSA) blasd.Add(&sD, -1.0) nrm1 := lapackd.NormP(V, lapackd.NORM_ONE) // left vectors are M-by-N V.Copy(A) lapackd.MultDiag(V, D, gomas.RIGHT) blasd.Mult(A0, V, A, -1.0, 1.0, gomas.TRANSB) nrm2 := lapackd.NormP(A0, lapackd.NORM_ONE) t.Logf("N=%d, [%s] ||A - V*D*V.T||_1 :%e\n", N, s, nrm2) t.Logf(" ||I - V.T*V||_1 : %e\n", nrm1) }
func blkBuildLQ(A, Tvec, Twork, W *cmat.FloatMatrix, K, lb int, conf *gomas.Config) { var ATL, ATR, ABL, ABR, AL cmat.FloatMatrix var A00, A10, A11, A12, A21, A22 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau, t2, Wrk, D, T cmat.FloatMatrix nk := n(A) - K mk := m(A) - K uk := K % lb util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, mk+uk, nk+uk, util.PBOTTOMRIGHT) util.Partition2x1( &tT, &tB, Tvec, mk+uk, util.PBOTTOM) // zero the bottom part __CHECK HERE: nk? or mk? if nk+uk > 0 { blasd.Scale(&ABL, 0.0) if uk > 0 { // number of reflectors is not multiple of blocking factor // do the first part with unblocked code. unblkBuildLQ(&ABR, &tB, W, m(&ABR)-uk, n(&ABR)-uk, true) } else { // blocking factor is multiple of K blasd.Scale(&ABR, 0.0) D.Diag(&ABR) blasd.Add(&D, 1.0) } } for m(&ATL) > 0 && n(&ATL) > 0 { util.Repartition2x2to3x3(&ATL, &A00, nil, nil, &A10, &A11, &A12, nil, &A21, &A22, A, lb, util.PTOPLEFT) util.Repartition2x1to3x1(&tT, &t0, &tau, &t2, Tvec, lb, util.PTOP) // ------------------------------------------------------ util.Merge1x2(&AL, &A11, &A12) // build block reflector T.SubMatrix(Twork, 0, 0, n(&A11), n(&A11)) unblkBlockReflectorLQ(&T, &AL, &tau) // update A21 and A22 with (I - Y*T*Y.T) from right ar, ac := A21.Size() Wrk.SubMatrix(W, 0, 0, ar, ac) updateRightLQ(&A21, &A22, &A11, &A12, &T, &Wrk, false, conf) // update current block unblkBuildLQ(&AL, &tau, W, 0, n(&A12), false) // zero top rows blasd.Scale(&A10, 0.0) // ------------------------------------------------------ util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &A11, &A22, A, util.PTOPLEFT) util.Continue3x1to2x1( &tT, &tB, &t0, &tau, Tvec, util.PTOP) } }
// test: M < N, U=[m,m] and V=[m,n] or V=[n,n] (square) func testWide(M, N int, square bool, t *testing.T) { var A, A0, W, S, U, Uu, V, Vv *cmat.FloatMatrix var sD cmat.FloatMatrix var s string wsize := M * N if wsize < 100 { wsize = 100 } S = cmat.NewMatrix(M, 1) A = cmat.NewMatrix(M, N) U = cmat.NewMatrix(M, M) Uu = cmat.NewMatrix(M, M) if square { V = cmat.NewMatrix(N, N) Vv = cmat.NewMatrix(N, N) } else { V = cmat.NewMatrix(M, N) Vv = cmat.NewMatrix(M, M) } src := cmat.NewFloatNormSource() A.SetFrom(src) A0 = cmat.NewCopy(A) W = cmat.NewMatrix(wsize, 1) if err := lapackd.SVD(S, U, V, A, W, gomas.WANTU|gomas.WANTV); err != nil { t.Errorf("SVD error: %v\n", err) return } // ||I - U.T*U|| sD.Diag(Uu) blasd.Mult(Uu, U, U, 1.0, 0.0, gomas.TRANSA) blasd.Add(&sD, -1.0) nrm0 := lapackd.NormP(Uu, lapackd.NORM_ONE) // ||I - V*V.T|| sD.Diag(Vv) blasd.Mult(Vv, V, V, 1.0, 0.0, gomas.TRANSB) blasd.Add(&sD, -1.0) nrm1 := lapackd.NormP(Vv, lapackd.NORM_ONE) if square { // right vectors are N-by-N Sg := cmat.NewMatrix(M, N) A1 := cmat.NewMatrix(M, N) sD.Diag(Sg) blasd.Copy(&sD, S) blasd.Mult(A1, Sg, V, 1.0, 0.0, gomas.NONE) blasd.Mult(A0, U, A1, -1.0, 1.0, gomas.NONE) s = "U=[m,m], V=[n,n]" } else { // right vectors are M-by-N lapackd.MultDiag(V, S, gomas.LEFT) blasd.Mult(A0, U, V, -1.0, 1.0, gomas.NONE) s = "U=[m,m], V=[m,n]" } nrm2 := lapackd.NormP(A0, lapackd.NORM_ONE) if N < 10 { t.Logf("A - U*S*V.T:\n%v\n", A0) } t.Logf("M=%d, N=%d, %s ||A - U*S*V.T||_1 :%e\n", M, N, s, nrm2) t.Logf(" ||I - U.T*U||_1 : %e\n", nrm0) t.Logf(" ||I - V*V.T||_1 : %e\n", nrm1) }
/* * Blocked code for generating M by N matrix Q with orthogonal columns which * are defined as the last N columns of the product of K first elementary * reflectors. * * If the number K of elementary reflectors is not multiple of the blocking * factor lb, then unblocked code is used first to generate the upper left corner * of the matrix Q. * * Compatible with lapack.DORGQL subroutine. */ func blkBuildQL(A, Tvec, Twork, W *cmat.FloatMatrix, K, lb int, conf *gomas.Config) { var ATL, ATR, ABL, ABR, AL cmat.FloatMatrix var A00, A01, A10, A11, A21, A22 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau, t2, Wrk, D, T cmat.FloatMatrix nk := n(A) - K mk := m(A) - K uk := K % lb util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, mk+uk, nk+uk, util.PTOPLEFT) util.Partition2x1( &tT, &tB, Tvec, nk+uk, util.PTOP) // zero the left side if nk+uk > 0 { blasd.Scale(&ABL, 0.0) if uk > 0 { // number of reflectors is not multiple of blocking factor // do the first part with unblocked code. unblkBuildQL(&ATL, &tT, W, m(&ATL)-uk, n(&ATL)-uk, true) } else { // blocking factor is multiple of K blasd.Scale(&ATL, 0.0) D.Diag(&ATL) blasd.Add(&D, 1.0) } } for m(&ABR) > 0 && n(&ABR) > 0 { util.Repartition2x2to3x3(&ATL, &A00, &A01, nil, &A10, &A11, nil, nil, &A21, &A22, A, lb, util.PBOTTOMRIGHT) util.Repartition2x1to3x1(&tT, &t0, &tau, &t2, Tvec, lb, util.PBOTTOM) // ------------------------------------------------------ util.Merge2x1(&AL, &A01, &A11) // build block reflector T.SubMatrix(Twork, 0, 0, n(&A11), n(&A11)) unblkQLBlockReflector(&T, &AL, &tau) // update left side i.e. A10 and A00 with (I - Y*T*Y.T) ar, ac := A10.Size() Wrk.SubMatrix(W, 0, 0, ac, ar) updateQLLeft(&A10, &A00, &A11, &A01, &T, &Wrk, false, conf) // update current block unblkBuildQL(&AL, &tau, W, m(&A01), 0, false) // zero bottom rows blasd.Scale(&A21, 0.0) // ------------------------------------------------------ util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &A11, &A22, A, util.PBOTTOMRIGHT) util.Continue3x1to2x1( &tT, &tB, &t0, &tau, Tvec, util.PBOTTOM) } }