예제 #1
0
파일: ql_test.go 프로젝트: hrautila/gomas
// 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)
}
예제 #2
0
파일: ql_test.go 프로젝트: hrautila/gomas
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)
}
예제 #3
0
파일: lq_test.go 프로젝트: hrautila/gomas
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)
}
예제 #4
0
파일: qr_test.go 프로젝트: hrautila/gomas
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)
}
예제 #5
0
파일: lqbld.go 프로젝트: hrautila/gomas
/*
 * 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)
	}
}
예제 #6
0
파일: qlbld.go 프로젝트: hrautila/gomas
/*
 * 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)
	}
}
예제 #7
0
파일: evd_test.go 프로젝트: hrautila/gomas
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)
}
예제 #8
0
파일: lqbld.go 프로젝트: hrautila/gomas
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)
	}
}
예제 #9
0
파일: svd_test.go 프로젝트: hrautila/gomas
// 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)
}
예제 #10
0
파일: qlbld.go 프로젝트: hrautila/gomas
/*
 * 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)
	}

}