// test that unblocked QR and QRT are equal func TestQRFactor(t *testing.T) { M := 411 N := 375 nb := 16 conf := gomas.NewConf() conf.LB = nb A := cmat.NewMatrix(M, N) //W := cmat.NewMatrix(N, nb) tau := cmat.NewMatrix(N, 1) zeromean := cmat.NewFloatNormSource() A.SetFrom(zeromean) A0 := cmat.NewCopy(A) tau0 := cmat.NewCopy(tau) // blocked: QR = A = Q*R W := lapackd.Workspace(lapackd.QRFactorWork(A, conf)) lapackd.QRFactor(A, tau, W, conf) conf.LB = 0 lapackd.QRFactor(A0, tau0, W, conf) ok := A.AllClose(A0) t.Logf("blk.QRFactor(A) == unblk.QRFactor(A): %v\n", ok) ok = tau0.AllClose(tau) t.Logf("blk QR.tau == unblk QR.tau: %v\n", ok) }
// test: min ||X|| s.t A.T*X = B func TestSolveQR(t *testing.T) { M := 799 N := 711 K := 241 nb := 32 conf := gomas.NewConf() conf.LB = nb tau := cmat.NewMatrix(N, 1) A := cmat.NewMatrix(M, N) src := cmat.NewFloatNormSource() A.SetFrom(src) A0 := cmat.NewCopy(A) B0 := cmat.NewMatrix(M, K) B0.SetFrom(src) B := cmat.NewCopy(B0) W := lapackd.Workspace(lapackd.QRFactorWork(A, conf)) lapackd.QRFactor(A, tau, W, conf) lapackd.QRSolve(B, A, tau, W, gomas.TRANS, conf) var Bmin cmat.FloatMatrix Bmin.SubMatrix(B0, 0, 0, N, K) blasd.Mult(&Bmin, A0, B, 1.0, -1.0, gomas.TRANSA, conf) nrm := lapackd.NormP(&Bmin, lapackd.NORM_ONE) t.Logf("M=%d, N=%d ||B - A.T*X||_1: %e\n", M, N, nrm) }
// QR decompose A, then compute ||A - (R.T*Q.T).T||_1, should be small func TestUnblkQRMultRight(t *testing.T) { M := 711 N := 593 A := cmat.NewMatrix(M, N) C := cmat.NewMatrix(N, M) tau := cmat.NewMatrix(N, 1) zeromean := cmat.NewFloatNormSource() A.SetFrom(zeromean) A0 := cmat.NewCopy(A) conf := gomas.NewConf() conf.LB = 0 // QR = A = Q*R W := lapackd.Workspace(lapackd.QRFactorWork(A, conf)) lapackd.QRFactor(A, tau, W, conf) // C = transpose(TriU(QR)) = R.T C.Transpose(cmat.TriU(cmat.NewCopy(A), cmat.NONE)) // C = C*Q.T = R.T*Q.T W = lapackd.Workspace(lapackd.QRMultWork(C, gomas.RIGHT, conf)) err := lapackd.QRMult(C, A, tau, W, gomas.RIGHT|gomas.TRANS, conf) if err != nil { t.Logf("err: %v\n", err) } // A = A - QR blasd.Plus(A0, C, 1.0, -1.0, gomas.TRANSB) // ||A - Q*R||_1 nrm := lapackd.NormP(A0, lapackd.NORM_ONE) t.Logf("M=%d,N=%d ||A - (R.T*Q.T).T||_1: %e\n", M, N, nrm) }
// QR decompose A, then compute ||A - Q*R||_1, should be small func TestUnblkQRMultLeft(t *testing.T) { M := 711 N := 593 A := cmat.NewMatrix(M, N) tau := cmat.NewMatrix(N, 1) zeromean := cmat.NewFloatNormSource() A.SetFrom(zeromean) A0 := cmat.NewCopy(A) conf := gomas.NewConf() conf.LB = 0 // QR = A = Q*R W := lapackd.Workspace(lapackd.QRFactorWork(A, conf)) lapackd.QRFactor(A, tau, W, conf) // C = TriU(QR) = R C := cmat.TriU(cmat.NewCopy(A), cmat.NONE) // C = Q*C W = lapackd.Workspace(lapackd.QRMultWork(C, gomas.LEFT, conf)) err := lapackd.QRMult(C, A, tau, W, gomas.LEFT, conf) if err != nil { t.Logf("err: %v\n", err) } // A = A - QR blasd.Plus(A0, C, 1.0, -1.0, gomas.NONE) // ||A - Q*R||_1 nrm := lapackd.NormP(A0, lapackd.NORM_ONE) t.Logf("M=%d,N=%d ||A - Q*R||_1: %e\n", M, N, nrm) }
// m > n: A[m,n], I[m,m] --> A.T == A.T*I == A.T*Q*Q.T func TestBlockedQRMultRightIdent(t *testing.T) { M := 511 N := 489 A := cmat.NewMatrix(M, N) C := cmat.NewMatrix(N, M) tau := cmat.NewMatrix(N, 1) zeromean := cmat.NewFloatNormSource() A.SetFrom(zeromean) A0 := cmat.NewCopy(A) C.Transpose(A) conf := gomas.NewConf() conf.LB = 32 // QR = A = Q*R W := lapackd.Workspace(lapackd.QRFactorWork(A, conf)) lapackd.QRFactor(A, tau, W, conf) // C = A.T*Q W = lapackd.Workspace(lapackd.QRMultWork(C, gomas.RIGHT, conf)) lapackd.QRMult(C, A, tau, W, gomas.RIGHT, conf) // C = C*Q.T == A.T*Q*Q.T lapackd.QRMult(C, A, tau, W, gomas.RIGHT|gomas.TRANS, conf) //t.Logf("A*Q*Q.T:\n%v\n", C) // A = A - (A.T*Q*Q.T).T blasd.Plus(A0, C, 1.0, -1.0, gomas.TRANSB) // ||A - (A.T*Q*Q.T).T||_1 nrm := lapackd.NormP(A0, lapackd.NORM_ONE) t.Logf("M=%d,N=%d ||A - (A.T*Q*Q.T).T||_1: %e\n", M, N, nrm) }
// m > n: A[m,n], I[m,m] --> A == I*A == Q*Q.T*A func TestBlkQRMultLeftIdent(t *testing.T) { M := 411 N := 399 A := cmat.NewMatrix(M, N) tau := cmat.NewMatrix(N, 1) zeromean := cmat.NewFloatNormSource() A.SetFrom(zeromean) A0 := cmat.NewCopy(A) C := cmat.NewCopy(A) conf := gomas.NewConf() conf.LB = 32 // QR = A = Q*R W := lapackd.Workspace(lapackd.QRFactorWork(A, conf)) lapackd.QRFactor(A, tau, W, conf) //t.Logf("T:\n%v\n", T) // C = Q.T*A W = lapackd.Workspace(lapackd.QRMultWork(C, gomas.LEFT, conf)) lapackd.QRMult(C, A, tau, W, gomas.LEFT|gomas.TRANS, conf) // C = Q*C == Q*Q.T*A lapackd.QRMult(C, A, tau, W, gomas.LEFT, conf) //t.Logf("A*Q*Q.T:\n%v\n", C) // A = A - Q*Q.T*A blasd.Plus(A0, C, 1.0, -1.0, gomas.NONE) // ||A - Q*Q.T*A||_1 nrm := lapackd.NormP(A0, lapackd.NORM_ONE) t.Logf("M=%d,N=%d ||A - Q*Q.T*A||_1: %e\n", M, N, nrm) }
func main() { flag.Parse() M := N + N/10 conf := gomas.CurrentConf() A := cmat.NewMatrix(M, N) A0 := cmat.NewCopy(A) tau := cmat.NewMatrix(N, 1) W := lapackd.Workspace(lapackd.QRFactorWork(A, conf)) zeromean := cmat.NewFloatNormSource() A.SetFrom(zeromean) cumtime := 0.0 mintime := 0.0 maxtime := 0.0 for i := 0; i < count; i++ { flushCache() t1 := time.Now() // ---------------------------------------------- lapackd.QRFactor(A, tau, W, conf) // ---------------------------------------------- t2 := time.Now() tm := t2.Sub(t1) if mintime == 0.0 || tm.Seconds() < mintime { mintime = tm.Seconds() } if maxtime == 0.0 || tm.Seconds() > maxtime { maxtime = tm.Seconds() } cumtime += tm.Seconds() if verbose { fmt.Printf("%3d %12.4f msec, %9.4f gflops\n", i, 1e+3*tm.Seconds(), gflops(M, N, tm.Seconds())) } blasd.Copy(A, A0) } cumtime /= float64(count) minflops := gflops(M, N, maxtime) avgflops := gflops(M, N, cumtime) maxflops := gflops(M, N, mintime) fmt.Printf("%5d %5d %3d %9.4f %9.4f %9.4f Gflops\n", M, N, conf.LB, minflops, avgflops, maxflops) }
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) }
// test: min || B - A*X || func TestLeastSquaresQR(t *testing.T) { M := 811 N := 723 K := 311 nb := 32 conf := gomas.NewConf() conf.LB = nb tau := cmat.NewMatrix(N, 1) A := cmat.NewMatrix(M, N) src := cmat.NewFloatNormSource() A.SetFrom(src) B0 := cmat.NewMatrix(N, K) B0.SetFrom(src) B := cmat.NewMatrix(M, K) // B = A*B0 blasd.Mult(B, A, B0, 1.0, 0.0, gomas.NONE, conf) W := lapackd.Workspace(lapackd.QRFactorWork(A, conf)) err := lapackd.QRFactor(A, tau, W, conf) if err != nil { t.Logf("DecomposeQR: %v\n", err) } // B' = A.-1*B err = lapackd.QRSolve(B, A, tau, W, gomas.NONE, conf) if err != nil { t.Logf("SolveQR: %v\n", err) } // expect B[0:N,0:K] == B0[0:N,0:K], B[N:M,0:K] == 0 var X cmat.FloatMatrix X.SubMatrix(B, 0, 0, N, K) blasd.Plus(&X, B0, 1.0, -1.0, gomas.NONE) nrm := lapackd.NormP(&X, lapackd.NORM_ONE) t.Logf("M=%d, N=%d ||B0 - min( ||A*X - B0|| ) ||_1: %e\n", M, N, nrm) }