Пример #1
0
/*
 * Applies a real elementary reflector H to a real m by n matrix A,
 * from either the left or the right. H is represented in the form
 *
 *       H = I - tau * ( 1 ) * ( 1 v.T )
 *                     ( v )
 *
 * where tau is a real scalar and v is a real vector.
 *
 * If tau = 0, then H is taken to be the unit cmat.
 *
 * A is /a1\   a1 := a1 - w1
 *      \A2/   A2 := A2 - v*w1
 *             w1 := tau*(a1 + A2.T*v) if side == LEFT
 *                := tau*(a1 + A2*v)   if side == RIGHT
 *
 * Intermediate work space w1 required as parameter, no allocation.
 */
func applyHouseholder2x1(tau, v, a1, A2, w1 *cmat.FloatMatrix, flags int) *gomas.Error {
	var err *gomas.Error = nil
	tval := tau.Get(0, 0)
	if tval == 0.0 {
		return err
	}

	// shape oblivious vector copy.
	blasd.Axpby(w1, a1, 1.0, 0.0)
	if flags&gomas.LEFT != 0 {
		// w1 = a1 + A2.T*v
		err = blasd.MVMult(w1, A2, v, 1.0, 1.0, gomas.TRANSA)
	} else {
		// w1 = a1 + A2*v
		err = blasd.MVMult(w1, A2, v, 1.0, 1.0, gomas.NONE)
	}
	// w1 = tau*w1
	blasd.Scale(w1, tval)

	// a1 = a1 - w1
	blasd.Axpy(a1, w1, -1.0)

	// A2 = A2 - v*w1
	if flags&gomas.LEFT != 0 {
		err = blasd.MVUpdate(A2, v, w1, -1.0)
	} else {
		err = blasd.MVUpdate(A2, w1, v, -1.0)
	}
	return err
}
Пример #2
0
func TestDSyr1(t *testing.T) {

	const N = 911

	A := cmat.NewMatrix(N, N)
	X := cmat.NewMatrix(N, 1)
	B := cmat.NewMatrix(N, N)

	//ones := cmat.NewFloatConstSource(1.0)
	zeromean := cmat.NewFloatUniformSource(0.5, 2.0)

	A.SetFrom(zeromean, cmat.LOWER)
	X.SetFrom(zeromean)
	B.Copy(A)

	// B = A*B
	blasd.MVUpdate(B, X, X, 1.0)
	cmat.TriL(B, cmat.NONE)
	blasd.MVUpdateSym(A, X, 1.0, gomas.LOWER)
	ok := B.AllClose(A)
	t.Logf("MVUpdateSym(A, X, L) == TriL(MVUpdate(A, X, X)) : %v\n", ok)

	A.SetFrom(zeromean, cmat.UPPER)
	cmat.TriU(A, cmat.NONE)
	B.Copy(A)
	blasd.MVUpdate(B, X, X, 1.0)
	cmat.TriU(B, cmat.NONE)
	blasd.MVUpdateSym(A, X, 1.0, gomas.UPPER)
	ok = B.AllClose(A)
	t.Logf("MVUpdateSym(A, X, U) == TriU(MVUpdate(A, X, X)) : %v\n", ok)
}
Пример #3
0
func TestDSyrOther(t *testing.T) {

	const N = 911

	var vec, As, Bs cmat.FloatMatrix
	P := N / 3
	A := cmat.NewMatrix(P, P)
	X := cmat.NewMatrix(P, 1)
	B := cmat.NewMatrix(P, P)

	//ones := cmat.NewFloatConstSource(1.0)
	zeromean := cmat.NewFloatUniformSource(0.5, 2.0)

	A.SetFrom(zeromean, cmat.UPPER)
	X.SetFrom(zeromean)
	B.Copy(A)

	// update submatrices
	for i := 1; i < P; i++ {
		vec.SubMatrix(A, i-1, i, 1, P-i)
		As.SubMatrix(A, i, i)
		Bs.SubMatrix(B, i, i)
		// update with normal and symmetric
		blasd.MVUpdate(&Bs, &vec, &vec, 1.0)
		blasd.MVUpdateSym(&As, &vec, 1.0, gomas.UPPER)
	}
	// make normal update triangular and compare
	cmat.TriU(B, cmat.NONE)
	ok := B.AllClose(A)
	t.Logf("submatrix updates on upper triangular : %v\n", ok)

	A.SetFrom(zeromean, cmat.LOWER)
	cmat.TriL(A, cmat.NONE)
	B.Copy(A)
	// update submatrices
	for i := 1; i < P; i++ {
		vec.SubMatrix(A, i-1, i, 1, P-i)
		As.SubMatrix(A, i, i)
		Bs.SubMatrix(B, i, i)
		// update with normal and symmetric
		blasd.MVUpdate(&Bs, &vec, &vec, 1.0)
		blasd.MVUpdateSym(&As, &vec, 1.0, gomas.LOWER)
	}
	// make normal update triangular and compare
	cmat.TriL(B, cmat.NONE)
	ok = B.AllClose(A)
	t.Logf("submatrix updates on lower triangular : %v\n", ok)
}
Пример #4
0
// unblocked LU decomposition w/o pivots, FLAME LU nopivots variant 5
func unblockedLUnoPiv(A *cmat.FloatMatrix, conf *gomas.Config) *gomas.Error {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a01, A02, a10, a11, a12, A20, a21, A22 cmat.FloatMatrix
	var err *gomas.Error = nil

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)

	for m(&ATL) < m(A) {
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			&a10, &a11, &a12,
			&A20, &a21, &A22, A, 1, util.PBOTTOMRIGHT)

		// a21 = a21/a11
		blasd.InvScale(&a21, a11.Get(0, 0))
		// A22 = A22 - a21*a12
		blasd.MVUpdate(&A22, &a21, &a12, -1.0)

		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
	}
	return err
}
Пример #5
0
func TestDSyr2(t *testing.T) {

	const N = 911

	A := cmat.NewMatrix(N, N)
	X := cmat.NewMatrix(N, 1)
	Y := cmat.NewMatrix(N, 1)
	B := cmat.NewMatrix(N, N)

	ones := cmat.NewFloatConstSource(1.0)
	twos := cmat.NewFloatConstSource(2.0)
	zeromean := cmat.NewFloatUniformSource(0.5, 2.0)

	A.SetFrom(zeromean, cmat.LOWER)
	X.SetFrom(ones)
	Y.SetFrom(twos)
	B.Copy(A)

	// B = A*B
	blasd.MVUpdate(B, X, Y, 1.0)
	blasd.MVUpdate(B, Y, X, 1.0)
	cmat.TriL(B, cmat.NONE)
	blasd.MVUpdate2Sym(A, X, Y, 1.0, gomas.LOWER)
	ok := B.AllClose(A)
	if N < 10 {
		t.Logf("A:\n%v\n", A)
		t.Logf("B:\n%v\n", B)
	}
	t.Logf("MVUpdate2Sym(A, X, Y, L) == TriL(MVUpdate(A, X, Y);MVUpdate(A, Y, X)) : %v\n", ok)

	A.SetFrom(zeromean, cmat.UPPER)
	cmat.TriU(A, cmat.NONE)
	B.Copy(A)
	blasd.MVUpdate(B, X, Y, 1.0)
	blasd.MVUpdate(B, Y, X, 1.0)
	cmat.TriU(B, cmat.NONE)
	blasd.MVUpdate2Sym(A, X, Y, 1.0, gomas.UPPER)
	ok = B.AllClose(A)
	if N < 10 {
		t.Logf("A:\n%v\n", A)
		t.Logf("B:\n%v\n", B)
	}
	t.Logf("MVUpdate2Sym(A, X, Y, U) == TriU(MVUpdate(A, X, Y);MVUpdate(A, Y, X)) : %v\n", ok)
}
Пример #6
0
/*
 *  Apply elementary Householder reflector v to matrix A2.
 *
 *    H = I - tau*v*v.t;
 *
 *  RIGHT:  A = A*H = A - tau*A*v*v.T = A - tau*w1*v.T
 *  LEFT:   A = H*A = A - tau*v*v.T*A = A - tau*v*A.T*v = A - tau*v*w1
 */
func applyHouseholder1x1(tau, v, A2, w1 *cmat.FloatMatrix, flags int) *gomas.Error {
	var err *gomas.Error = nil
	tval := tau.Get(0, 0)
	if tval == 0.0 {
		return nil
	}
	if flags&gomas.LEFT != 0 {
		// w1 = A2.T*v
		err = blasd.MVMult(w1, A2, v, 1.0, 0.0, gomas.TRANSA)
		if err == nil {
			// A2 = A2 - tau*v*w1; m(A2) == len(v) && n(A2) == len(w1)
			err = blasd.MVUpdate(A2, v, w1, -tval)
		}
	} else {
		// w1 = A2*v
		err = blasd.MVMult(w1, A2, v, 1.0, 0.0, gomas.NONE)
		if err == nil {
			// A2 = A2 - tau*w1*v; m(A2) == len(w1) && n(A2) == len(v)
			err = blasd.MVUpdate(A2, w1, v, -tval)
		}
	}
	return err
}
Пример #7
0
/* From LAPACK/dlarf.f
 *
 * Applies a real elementary reflector H to a real m by n matrix A,
 * from either the left or the right. H is represented in the form
 *
 *       H = I - tau * ( 1 ) * ( 1 v.T )
 *                     ( v )
 *
 * where tau is a real scalar and v is a real vector.
 *
 * If tau = 0, then H is taken to be the unit cmat.
 *
 * A is /a1\   a1 := a1 - w1
 *      \A2/   A2 := A2 - v*w1
 *             w1 := tau*(a1 + A2.T*v) if side == LEFT
 *                := tau*(a1 + A2*v)   if side == RIGHT
 *
 * Allocates/frees intermediate work space matrix w1.
 */
func applyHouseholder(tau, v, a1, A2 *cmat.FloatMatrix, flags int) {

	tval := tau.Get(0, 0)
	if tval == 0.0 {
		return
	}
	w1 := cmat.NewCopy(a1)
	if flags&gomas.LEFT != 0 {
		// w1 = a1 + A2.T*v
		blasd.MVMult(w1, A2, v, 1.0, 1.0, gomas.TRANSA)
	} else {
		// w1 = a1 + A2*v
		blasd.MVMult(w1, A2, v, 1.0, 1.0, gomas.NONE)
	}

	// w1 = tau*w1
	blasd.Scale(w1, tval)

	// a1 = a1 - w1
	blasd.Axpy(a1, w1, -1.0)

	// A2 = A2 - v*w1
	blasd.MVUpdate(A2, v, w1, -1.0)
}
Пример #8
0
/*
 * Computes upper Hessenberg reduction of N-by-N matrix A using unblocked
 * algorithm as described in (1).
 *
 * Hessengerg reduction: A = Q.T*B*Q, Q unitary, B upper Hessenberg
 *  Q = H(0)*H(1)*...*H(k) where H(k) is k'th Householder reflector.
 *
 * Compatible with lapack.DGEHD2.
 */
func unblkHessGQvdG(A, Tvec, W *cmat.FloatMatrix, row int) {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a11, a21, A22 cmat.FloatMatrix
	var AL, AR, A0, a1, A2 cmat.FloatMatrix
	var tT, tB cmat.FloatMatrix
	var t0, tau1, t2, w12, v1 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, row, 0, util.PTOPLEFT)
	util.Partition1x2(
		&AL, &AR, A, 0, util.PLEFT)
	util.Partition2x1(
		&tT,
		&tB, Tvec, 0, util.PTOP)

	v1.SubMatrix(W, 0, 0, m(A), 1)

	for m(&ABR) > 1 && n(&ABR) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			nil, &a11, nil,
			nil, &a21, &A22, A, 1, util.PBOTTOMRIGHT)
		util.Repartition1x2to1x3(&AL,
			&A0, &a1, &A2, A, 1, util.PRIGHT)
		util.Repartition2x1to3x1(&tT,
			&t0,
			&tau1,
			&t2, Tvec, 1, util.PBOTTOM)

		// ------------------------------------------------------
		// a21 = [beta; H(k)].T
		computeHouseholderVec(&a21, &tau1)
		tauval := tau1.Get(0, 0)
		beta := a21.Get(0, 0)
		a21.Set(0, 0, 1.0)

		// v1 := A2*a21
		blasd.MVMult(&v1, &A2, &a21, 1.0, 0.0, gomas.NONE)

		// A2 := A2 - tau*v1*a21   (A2 := A2*H(k))
		blasd.MVUpdate(&A2, &v1, &a21, -tauval)

		w12.SubMatrix(W, 0, 0, n(&A22), 1)
		// w12 := a21.T*A22 = A22.T*a21
		blasd.MVMult(&w12, &A22, &a21, 1.0, 0.0, gomas.TRANS)
		// A22 := A22 - tau*a21*w12   (A22 := H(k)*A22)
		blasd.MVUpdate(&A22, &a21, &w12, -tauval)

		a21.Set(0, 0, beta)
		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue1x3to1x2(
			&AL, &AR, &A0, &a1, A, util.PRIGHT)
		util.Continue3x1to2x1(
			&tT,
			&tB, &t0, &tau1, Tvec, util.PBOTTOM)
	}
}
Пример #9
0
/*
 * Unblocked solve A*X = B for Bunch-Kauffman factorized symmetric real matrix.
 */
func unblkSolveBKUpper(B, A *cmat.FloatMatrix, p Pivots, phase int, conf *gomas.Config) *gomas.Error {
	var err *gomas.Error = nil
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a01, A02, a11, a12t, A22 cmat.FloatMatrix
	var Aref *cmat.FloatMatrix
	var BT, BB, B0, b1, B2, Bx cmat.FloatMatrix
	var pT, pB, p0, p1, p2 Pivots
	var aStart, aDir, bStart, bDir util.Direction
	var nc int

	np := 0

	if phase == 2 {
		aStart = util.PTOPLEFT
		aDir = util.PBOTTOMRIGHT
		bStart = util.PTOP
		bDir = util.PBOTTOM
		nc = 1
		Aref = &ABR
	} else {
		aStart = util.PBOTTOMRIGHT
		aDir = util.PTOPLEFT
		bStart = util.PBOTTOM
		bDir = util.PTOP
		nc = m(A)
		Aref = &ATL
	}
	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, aStart)
	util.Partition2x1(
		&BT,
		&BB, B, 0, bStart)
	partitionPivot2x1(
		&pT,
		&pB, p, 0, bStart)

	// phase 1:
	//   - solve U*D*X = B, overwriting B with X
	//   - looping from BOTTOM to TOP
	// phase 1:
	//   - solve U*X = B, overwriting B with X
	//   - looping from TOP to BOTTOM
	for n(Aref) > 0 {
		// see if next diagonal block is 1x1 or 2x2
		np = 1
		if p[nc-1] < 0 {
			np = 2
		}

		// repartition according the pivot size
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			nil, &a11, &a12t,
			nil, nil, &A22 /**/, A, np, aDir)
		util.Repartition2x1to3x1(&BT,
			&B0,
			&b1,
			&B2 /**/, B, np, bDir)
		repartPivot2x1to3x1(&pT,
			&p0,
			&p1,
			&p2 /**/, p, np, bDir)
		// ------------------------------------------------------------

		switch phase {
		case 1:
			// computes D.-1*(U.-1*B);
			// b1 is current row, last row of BT
			if np == 1 {
				if p1[0] != nc {
					// swap rows on top part of B
					swapRows(&BT, m(&BT)-1, p1[0]-1)
				}
				// B0 = B0 - a01*b1
				blasd.MVUpdate(&B0, &a01, &b1, -1.0)
				// b1 = b1/d1
				blasd.InvScale(&b1, a11.Get(0, 0))
				nc -= 1
			} else if np == 2 {
				if p1[0] != -nc {
					// swap rows on top part of B
					swapRows(&BT, m(&BT)-2, -p1[0]-1)
				}
				b := a11.Get(0, 1)
				apb := a11.Get(0, 0) / b
				dpb := a11.Get(1, 1) / b
				// (a/b)*(d/b)-1.0 == (a*d - b^2)/b^2
				scale := apb*dpb - 1.0
				scale *= b

				// B0 = B0 - a01*b1
				blasd.Mult(&B0, &a01, &b1, -1.0, 1.0, gomas.NONE, conf)
				// b1 = a11.-1*b1.T
				//(2x2 block, no subroutine for doing this in-place)
				for k := 0; k < n(&b1); k++ {
					s0 := b1.Get(0, k)
					s1 := b1.Get(1, k)
					b1.Set(0, k, (dpb*s0-s1)/scale)
					b1.Set(1, k, (apb*s1-s0)/scale)
				}
				nc -= 2
			}
		case 2:
			// compute X = U.-T*B
			if np == 1 {
				blasd.MVMult(&b1, &B0, &a01, -1.0, 1.0, gomas.TRANS)
				if p1[0] != nc {
					// swap rows on bottom part of B
					util.Merge2x1(&Bx, &B0, &b1)
					swapRows(&Bx, m(&Bx)-1, p1[0]-1)
				}
				nc += 1
			} else if np == 2 {
				blasd.Mult(&b1, &a01, &B0, -1.0, 1.0, gomas.TRANSA, conf)
				if p1[0] != -nc {
					// swap rows on bottom part of B
					util.Merge2x1(&Bx, &B0, &b1)
					swapRows(&Bx, m(&Bx)-2, -p1[0]-1)
				}
				nc += 2
			}
		}
		// ------------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, aDir)
		util.Continue3x1to2x1(
			&BT,
			&BB, &B0, &b1, B, bDir)
		contPivot3x1to2x1(
			&pT,
			&pB, p0, p1, p, bDir)

	}
	return err
}
Пример #10
0
/*
 * Compute unblocked bidiagonal reduction for A when M >= N
 *
 * Diagonal and first super/sub diagonal are overwritten with the
 * upper/lower bidiagonal matrix B.
 *
 * This computing (1-tauq*v*v.T)*A*(1-taup*u.u.T) from left to right.
 */
func unblkReduceBidiagLeft(A, tauq, taup, W *cmat.FloatMatrix) {
	var ATL, ABR cmat.FloatMatrix
	var A00, a11, a12t, a21, A22 cmat.FloatMatrix
	var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix
	var tpT, tpB, tp0, taup1, tp2 cmat.FloatMatrix
	var y21, z21 cmat.FloatMatrix
	var v0 float64

	util.Partition2x2(
		&ATL, nil,
		nil, &ABR, A, 0, 0, util.PTOPLEFT)
	util.Partition2x1(
		&tqT,
		&tqB, tauq, 0, util.PTOP)
	util.Partition2x1(
		&tpT,
		&tpB, taup, 0, util.PTOP)

	for m(&ABR) > 0 && n(&ABR) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			nil, &a11, &a12t,
			nil, &a21, &A22, A, 1, util.PBOTTOMRIGHT)
		util.Repartition2x1to3x1(&tqT,
			&tq0,
			&tauq1,
			&tq2, tauq, 1, util.PBOTTOM)
		util.Repartition2x1to3x1(&tpT,
			&tp0,
			&taup1,
			&tp2, taup, 1, util.PBOTTOM)

		// set temp vectors for this round
		y21.SetBuf(n(&a12t), 1, n(&a12t), W.Data())
		z21.SetBuf(m(&a21), 1, m(&a21), W.Data()[y21.Len():])
		// ------------------------------------------------------

		// Compute householder to zero subdiagonal entries
		computeHouseholder(&a11, &a21, &tauq1)

		// y21 := a12 + A22.T*a21
		blasd.Axpby(&y21, &a12t, 1.0, 0.0)
		blasd.MVMult(&y21, &A22, &a21, 1.0, 1.0, gomas.TRANSA)

		// a12t := a12t - tauq*y21
		tauqv := tauq1.Get(0, 0)
		blasd.Axpy(&a12t, &y21, -tauqv)

		// Compute householder to zero elements above 1st superdiagonal
		computeHouseholderVec(&a12t, &taup1)
		v0 = a12t.Get(0, 0)
		a12t.Set(0, 0, 1.0)
		taupv := taup1.Get(0, 0)

		// [v == a12t, u == a21]
		beta := blasd.Dot(&y21, &a12t)
		// z21 := tauq*beta*u
		blasd.Axpby(&z21, &a21, tauqv*beta, 0.0)
		// z21 := A22*v - z21
		blasd.MVMult(&z21, &A22, &a12t, 1.0, -1.0, gomas.NONE)
		// A22 := A22 - tauq*u*y21
		blasd.MVUpdate(&A22, &a21, &y21, -tauqv)
		// A22 := A22 - taup*z21*v
		blasd.MVUpdate(&A22, &z21, &a12t, -taupv)

		a12t.Set(0, 0, v0)
		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, nil,
			nil, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue3x1to2x1(
			&tqT,
			&tqB, &tq0, &tauq1, tauq, util.PBOTTOM)
		util.Continue3x1to2x1(
			&tpT,
			&tpB, &tp0, &taup1, taup, util.PBOTTOM)
	}
}