예제 #1
0
파일: part_test.go 프로젝트: hrautila/gomas
func TestPartition2D(t *testing.T) {
	var ATL, ATR, ABL, ABR, As cmat.FloatMatrix
	var A00, a01, A02, a10, a11, a12, A20, a21, A22 cmat.FloatMatrix

	csource := cmat.NewFloatConstSource(1.0)
	A := cmat.NewMatrix(6, 6)
	As.SubMatrix(A, 1, 1, 4, 4)
	As.SetFrom(csource)

	Partition2x2(&ATL, &ATR, &ABL, &ABR, &As, 0, 0, PTOPLEFT)
	t.Logf("ATL:\n%v\n", &ATL)

	t.Logf("n(ATL)=%d, n(As)=%d\n", n(&ATL), n(&As))
	k := 0
	for n(&ATL) < n(&As) && k < n(&As) {
		Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			&a10, &a11, &a12,
			&A20, &a21, &A22, &As, 1, PBOTTOMRIGHT)
		t.Logf("n(A00)=%d, n(a01)=%d, n(A02)=%d\n", n(&A00), n(&a01), n(&A02))
		t.Logf("n(a10)=%d, n(a11)=%d, n(a12)=%d\n", n(&a10), n(&a11), n(&a12))
		t.Logf("n(A20)=%d, n(a21)=%d, n(A22)=%d\n", n(&A20), n(&a21), n(&A22))
		//t.Logf("n(a12)=%d [%d], n(a11)=%d\n", n(&a12), a12.Len(), a11.Len())
		a11.Set(0, 0, a11.Get(0, 0)+1.0)
		addConst(&a21, -2.0)

		Continue3x3to2x2(&ATL, &ATR, &ABL, &ABR, &A00, &a11, &A22, &As, PBOTTOMRIGHT)
		t.Logf("n(ATL)=%d, n(As)=%d\n", n(&ATL), n(&As))
		k += 1
	}
	t.Logf("A:\n%v\n", A)
}
예제 #2
0
파일: trired.go 프로젝트: hrautila/gomas
/*
 * Reduce upper triangular matrix to tridiagonal.
 *
 * Elementary reflectors Q = H(n-1)...H(2)H(1) are stored on upper
 * triangular part of A. Reflector H(n-1) saved at column A(n) and
 * scalar multiplier to tau[n-1]. If parameter `tail` is true then
 * this function is used to reduce tail part of partially reduced
 * matrix and tau-vector partitioning is starting from last position.
 */
func unblkReduceTridiagUpper(A, tauq, W *cmat.FloatMatrix, tail bool) {
	var ATL, ABR cmat.FloatMatrix
	var A00, a01, a11, A22 cmat.FloatMatrix
	var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix
	var y21 cmat.FloatMatrix
	var v0 float64

	toff := 1
	if tail {
		toff = 0
	}
	util.Partition2x2(
		&ATL, nil,
		nil, &ABR, A, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x1(
		&tqT,
		&tqB, tauq, toff, util.PBOTTOM)

	for n(&ATL) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, nil,
			nil, &a11, nil,
			nil, nil, &A22, A, 1, util.PTOPLEFT)
		util.Repartition2x1to3x1(&tqT,
			&tq0,
			&tauq1,
			&tq2, tauq, 1, util.PTOP)
		// set temp vectors for this round
		y21.SetBuf(n(&A00), 1, n(&A00), W.Data())
		// ------------------------------------------------------

		// Compute householder to zero super-diagonal entries
		computeHouseholderRev(&a01, &tauq1)
		tauqv := tauq1.Get(0, 0)

		// set superdiagonal to unit
		v0 = a01.Get(-1, 0)
		a01.Set(-1, 0, 1.0)

		// y21 := A22*a12t
		blasd.MVMultSym(&y21, &A00, &a01, tauqv, 0.0, gomas.UPPER)
		// beta := tauq*a12t*y21
		beta := tauqv * blasd.Dot(&a01, &y21)
		// y21  := y21 - 0.5*beta*a125
		blasd.Axpy(&y21, &a01, -0.5*beta)
		// A22 := A22 - a12t*y21.T - y21*a12.T
		blasd.MVUpdate2Sym(&A00, &a01, &y21, -1.0, gomas.UPPER)

		// restore superdiagonal value
		a01.Set(-1, 0, v0)
		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, nil,
			nil, &ABR, &A00, &a11, &A22, A, util.PTOPLEFT)
		util.Continue3x1to2x1(
			&tqT,
			&tqB, &tq0, &tauq1, tauq, util.PTOP)
	}
}
예제 #3
0
파일: trired.go 프로젝트: hrautila/gomas
func blkReduceTridiagUpper(A, tauq, Y, W *cmat.FloatMatrix, lb int, conf *gomas.Config) {
	var ATL, ABR cmat.FloatMatrix
	var A00, A01, A11, A22 cmat.FloatMatrix
	var YT, YB, Y0, Y1, Y2 cmat.FloatMatrix
	var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix
	var v0 float64

	util.Partition2x2(
		&ATL, nil,
		nil, &ABR, A, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x1(
		&YT,
		&YB, Y, 0, util.PBOTTOM)
	util.Partition2x1(
		&tqT,
		&tqB, tauq, 1, util.PBOTTOM)

	for m(&ATL)-lb > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, &A01, nil,
			nil, &A11, nil,
			nil, nil, &A22, A, lb, util.PTOPLEFT)
		util.Repartition2x1to3x1(&YT,
			&Y0,
			&Y1,
			&Y2, Y, lb, util.PTOP)
		util.Repartition2x1to3x1(&tqT,
			&tq0,
			&tauq1,
			&tq2, tauq, lb, util.PTOP)
		// ------------------------------------------------------
		unblkBuildTridiagUpper(&ATL, &tauq1, &YT, W)

		// set subdiagonal entry to unit
		v0 = A01.Get(-1, 0)
		A01.Set(-1, 0, 1.0)

		// A22 := A22 - A01*Y0.T - Y0*A01.T
		blasd.Update2Sym(&A00, &A01, &Y0, -1.0, 1.0, gomas.UPPER, conf)

		// restore subdiagonal entry
		A01.Set(-1, 0, v0)
		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, nil,
			nil, &ABR, &A00, &A11, &A22, A, util.PTOPLEFT)
		util.Continue3x1to2x1(
			&YT,
			&YB, &Y0, &Y1, Y, util.PTOP)
		util.Continue3x1to2x1(
			&tqT,
			&tqB, &tq0, &tauq1, tauq, util.PTOP)
	}

	if m(&ATL) > 0 {
		unblkReduceTridiagUpper(&ATL, &tqT, W, true)
	}
}
예제 #4
0
파일: ql.go 프로젝트: hrautila/gomas
/*
 * like LAPACK/dlafrt.f
 *
 * Build block reflector T from HH reflector stored in TriLU(A) and coefficients
 * in tau.
 *
 * Q = I - Y*T*Y.T; Householder H = I - tau*v*v.T
 *
 * T = | T  z |   z = -tau*T*Y.T*v
 *     | 0  c |   c = tau
 *
 * Q = H(1)H(2)...H(k) building forward here.
 */
func unblkQLBlockReflector(T, A, tau *cmat.FloatMatrix) {
	var ATL, ABR cmat.FloatMatrix
	var A00, a01, a11, A02, a12, A22 cmat.FloatMatrix
	var TTL, TBR cmat.FloatMatrix
	var T00, t11, t21, T22 cmat.FloatMatrix
	var tT, tB cmat.FloatMatrix
	var t0, tau1, t2 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, nil,
		nil, &ABR, A, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x2(
		&TTL, nil,
		nil, &TBR, T, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x1(
		&tT,
		&tB, tau, 0, util.PBOTTOM)

	for m(&ATL) > 0 && n(&ATL) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			nil, &a11, &a12,
			nil, nil, &A22, A, 1, util.PTOPLEFT)
		util.Repartition2x2to3x3(&TTL,
			&T00, nil, nil,
			nil, &t11, nil,
			nil, &t21, &T22, T, 1, util.PTOPLEFT)
		util.Repartition2x1to3x1(&tT,
			&t0,
			&tau1,
			&t2, tau, 1, util.PTOP)
		// --------------------------------------------------

		// t11 := tau
		tauval := tau1.Get(0, 0)
		if tauval != 0.0 {
			t11.Set(0, 0, tauval)

			// t21 := -tauval*(a12.T + &A02.T*a12)
			blasd.Axpby(&t21, &a12, 1.0, 0.0)
			blasd.MVMult(&t21, &A02, &a01, -tauval, -tauval, gomas.TRANSA)
			// t21 := T22*t01
			blasd.MVMultTrm(&t21, &T22, 1.0, gomas.LOWER)
		}

		// --------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, nil,
			nil, &ABR, &A00, &a11, &A22, A, util.PTOPLEFT)
		util.Continue3x3to2x2(
			&TTL, nil,
			nil, &TBR, &T00, &t11, &T22, T, util.PTOPLEFT)
		util.Continue3x1to2x1(
			&tT,
			&tB, &t0, &tau1, tau, util.PTOP)
	}
}
예제 #5
0
파일: rq.go 프로젝트: hrautila/gomas
/*
 * like LAPACK/dlafrt.f
 *
 * Build block reflector T from HH reflector stored in TriLU(A) and coefficients
 * in tau.
 *
 * Q = I - Y*T*Y.T; Householder H = I - tau*v*v.T
 *
 * T = | T  0 |   z = -tau*T*Y.T*v
 *     | z  c |   c = tau
 *
 * Q = H(1)H(2)...H(k) building forward here.
 */
func unblkBlockReflectorRQ(T, A, tau *cmat.FloatMatrix) {
	var ATL, ABR cmat.FloatMatrix
	var A00, a10, A20, a11, a21, A22 cmat.FloatMatrix
	var TTL, TBR cmat.FloatMatrix
	var T00, t11, t21, T22 cmat.FloatMatrix
	var tT, tB cmat.FloatMatrix
	var t0, tau1, t2 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, nil,
		nil, &ABR /**/, A, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x2(
		&TTL, nil,
		nil, &TBR /**/, T, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x1(
		&tT,
		&tB /**/, tau, 0, util.PBOTTOM)

	for m(&ATL) > 0 && n(&ATL) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10, &a11, nil,
			&A20, &a21, &A22 /**/, A, 1, util.PTOPLEFT)
		util.Repartition2x2to3x3(&TTL,
			&T00, nil, nil,
			nil, &t11, nil,
			nil, &t21, &T22 /**/, T, 1, util.PTOPLEFT)
		util.Repartition2x1to3x1(&tT,
			&t0,
			&tau1,
			&t2 /**/, tau, 1, util.PTOP)
		// --------------------------------------------------

		// t11 := tau
		tauval := tau1.Get(0, 0)
		if tauval != 0.0 {
			t11.Set(0, 0, tauval)

			// t21 := -tauval*(a21 + A20*a10)
			blasd.Axpby(&t21, &a21, 1.0, 0.0)
			blasd.MVMult(&t21, &A20, &a10, -tauval, -tauval, gomas.NONE)
			// t21 := T22*t21
			blasd.MVMultTrm(&t21, &T22, 1.0, gomas.LOWER)
		}

		// --------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, nil,
			nil, &ABR /**/, &A00, &a11, &A22, A, util.PTOPLEFT)
		util.Continue3x3to2x2(
			&TTL, nil,
			nil, &TBR /**/, &T00, &t11, &T22, T, util.PTOPLEFT)
		util.Continue3x1to2x1(
			&tT,
			&tB /**/, &t0, &tau1, tau, util.PTOP)
	}
}
예제 #6
0
파일: lq.go 프로젝트: hrautila/gomas
/*
 * like LAPACK/dlafrt.f
 *
 * Build block reflector T from HH reflector stored in TriLU(A) and coefficients
 * in tau.
 *
 * Q = I - Y*T*Y.T; Householder H = I - tau*v*v.T
 *
 * T = | T  z |   z = -tau*T*Y.T*v
 *     | 0  c |   c = tau
 *
 * Q = H(1)H(2)...H(k) building forward here.
 */
func unblkBlockReflectorLQ(T, A, tau *cmat.FloatMatrix) {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a01, A02, a11, a12, A22 cmat.FloatMatrix
	var TTL, TTR, TBL, TBR cmat.FloatMatrix
	var T00, t01, T02, t11, t12, T22 cmat.FloatMatrix
	var tT, tB cmat.FloatMatrix
	var t0, tau1, t2 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)
	util.Partition2x2(
		&TTL, &TTR,
		&TBL, &TBR, T, 0, 0, util.PTOPLEFT)
	util.Partition2x1(
		&tT,
		&tB, tau, 0, util.PTOP)

	for m(&ABR) > 0 && n(&ABR) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			nil, &a11, &a12,
			nil, nil, &A22, A, 1, util.PBOTTOMRIGHT)
		util.Repartition2x2to3x3(&TTL,
			&T00, &t01, &T02,
			nil, &t11, &t12,
			nil, nil, &T22, T, 1, util.PBOTTOMRIGHT)
		util.Repartition2x1to3x1(&tT,
			&t0,
			&tau1,
			&t2, tau, 1, util.PBOTTOM)
		// --------------------------------------------------

		// t11 := tau
		tauval := tau1.Get(0, 0)
		if tauval != 0.0 {
			t11.Set(0, 0, tauval)

			// t01 := -tauval*(a01 + A02*a12)
			blasd.Axpby(&t01, &a01, 1.0, 0.0)
			blasd.MVMult(&t01, &A02, &a12, -tauval, -tauval, gomas.NONE)
			// t01 := T00*t01
			blasd.MVMultTrm(&t01, &T00, 1.0, gomas.UPPER)
		}

		// --------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue3x3to2x2(
			&TTL, &TTR,
			&TBL, &TBR, &T00, &t11, &T22, T, util.PBOTTOMRIGHT)
		util.Continue3x1to2x1(
			&tT,
			&tB, &t0, &tau1, tau, util.PBOTTOM)
	}
}
예제 #7
0
파일: trired.go 프로젝트: hrautila/gomas
/*
 * Tridiagonal reduction of LOWER triangular symmetric matrix, zero elements below 1st
 * subdiagonal:
 *
 *   A =  (1 - tau*u*u.t)*A*(1 - tau*u*u.T)
 *     =  (I - tau*( 0   0   )) (a11 a12) (I - tau*( 0  0   ))
 *        (        ( 0  u*u.t)) (a21 A22) (        ( 0 u*u.t))
 *
 *  a11, a12, a21 not affected
 *
 *  from LEFT:
 *    A22 = A22 - tau*u*u.T*A22
 *  from RIGHT:
 *    A22 = A22 - tau*A22*u.u.T
 *
 *  LEFT and RIGHT:
 *    A22   = A22 - tau*u*u.T*A22 - tau*(A22 - tau*u*u.T*A22)*u*u.T
 *          = A22 - tau*u*u.T*A22 - tau*A22*u*u.T + tau*tau*u*u.T*A22*u*u.T
 *    [x    = tau*A22*u (vector)]  (SYMV)
 *    A22   = A22 - u*x.T - x*u.T + tau*u*u.T*x*u.T
 *    [beta = tau*u.T*x (scalar)]  (DOT)
 *          = A22 - u*x.T - x*u.T + beta*u*u.T
 *          = A22 - u*(x - 0.5*beta*u).T - (x - 0.5*beta*u)*u.T
 *    [w    = x - 0.5*beta*u]      (AXPY)
 *          = A22 - u*w.T - w*u.T  (SYR2)
 *
 * Result of reduction for N = 5:
 *    ( d  .  .  . . )
 *    ( e  d  .  . . )
 *    ( v1 e  d  . . )
 *    ( v1 v2 e  d . )
 *    ( v1 v2 v3 e d )
 */
func unblkReduceTridiagLower(A, tauq, W *cmat.FloatMatrix) {
	var ATL, ABR cmat.FloatMatrix
	var A00, a11, a21, A22 cmat.FloatMatrix
	var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix
	var y21 cmat.FloatMatrix
	var v0 float64

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

	for m(&ABR) > 0 && n(&ABR) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			nil, &a11, nil,
			nil, &a21, &A22, A, 1, util.PBOTTOMRIGHT)
		util.Repartition2x1to3x1(&tqT,
			&tq0,
			&tauq1,
			&tq2, tauq, 1, util.PBOTTOM)
		// set temp vectors for this round
		y21.SetBuf(n(&A22), 1, n(&A22), W.Data())
		// ------------------------------------------------------

		// Compute householder to zero subdiagonal entries
		computeHouseholderVec(&a21, &tauq1)
		tauqv := tauq1.Get(0, 0)

		// set subdiagonal to unit
		v0 = a21.Get(0, 0)
		a21.Set(0, 0, 1.0)

		// y21 := tauq*A22*a21
		blasd.MVMultSym(&y21, &A22, &a21, tauqv, 0.0, gomas.LOWER)
		// beta := tauq*a21.T*y21
		beta := tauqv * blasd.Dot(&a21, &y21)
		// y21  := y21 - 0.5*beta*a21
		blasd.Axpy(&y21, &a21, -0.5*beta)
		// A22 := A22 - a21*y21.T - y21*a21.T
		blasd.MVUpdate2Sym(&A22, &a21, &y21, -1.0, gomas.LOWER)

		// restore subdiagonal
		a21.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)
	}
}
예제 #8
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)
	}
}
예제 #9
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)
	}
}
예제 #10
0
파일: ldlbkl.go 프로젝트: hrautila/gomas
/*
 * Apply diagonal pivot (row and column swapped) to symmetric matrix blocks.
 *
 * LOWER triangular; moving from top-left to bottom-right
 *
 *    -----------------------
 *    | d
 *    | x P1 x  x  x  P2     -- current row/col 'srcix'
 *    | x S2 d  x  x  x
 *    | x S2 x  d  x  x
 *    | x S2 x  x  d  x
 *    | x P2 D2 D2 D2 P3     -- swap with row/col 'dstix'
 *    | x S3 x  x  x  D3 d
 *    | x S3 x  x  x  D3 x d
 *         (AR)
 */
func applyBKPivotSymLower(AR *cmat.FloatMatrix, srcix, dstix int) {
	var s, d cmat.FloatMatrix
	// S2 -- D2
	s.SubMatrix(AR, srcix+1, srcix, dstix-srcix-1, 1)
	d.SubMatrix(AR, dstix, srcix+1, 1, dstix-srcix-1)
	blasd.Swap(&s, &d)
	// S3 -- D3
	s.SubMatrix(AR, dstix+1, srcix, m(AR)-dstix-1, 1)
	d.SubMatrix(AR, dstix+1, dstix, m(AR)-dstix-1, 1)
	blasd.Swap(&s, &d)
	// swap P1 and P3
	p1 := AR.Get(srcix, srcix)
	p3 := AR.Get(dstix, dstix)
	AR.Set(srcix, srcix, p3)
	AR.Set(dstix, dstix, p1)
	return
}
예제 #11
0
파일: ldlbku.go 프로젝트: hrautila/gomas
/*
 * Apply diagonal pivot (row and column swapped) to symmetric matrix blocks.
 *
 * UPPER triangular; moving from bottom-right to top-left
 *
 *    d x D3 x  x  x  S3 x |
 *      d D3 x  x  x  S3 x |
 *        P3 D2 D2 D2 P2 x |  -- dstinx
 *           d  x  x  S2 x |
 *              d  x  S2 x |
 *                 d  S2 x |
 *                    P1 x |  -- srcinx
 *                       d |
 *    ----------------------
 *               (ABR)
 */
func applyBKPivotSymUpper(AR *cmat.FloatMatrix, srcix, dstix int) {
	var s, d cmat.FloatMatrix
	// AL is ATL, AR is ATR; P1 is AL[srcix, srcix];
	// S2 -- D2
	s.SubMatrix(AR, dstix+1, srcix, srcix-dstix-1, 1)
	d.SubMatrix(AR, dstix, dstix+1, 1, srcix-dstix-1)
	blasd.Swap(&s, &d)
	// S3 -- D3
	s.SubMatrix(AR, 0, srcix, dstix, 1)
	d.SubMatrix(AR, 0, dstix, dstix, 1)
	blasd.Swap(&s, &d)
	// swap P1 and P3
	p1 := AR.Get(srcix, srcix)
	p3 := AR.Get(dstix, dstix)
	AR.Set(srcix, srcix, p3)
	AR.Set(dstix, dstix, p1)
	return
}
예제 #12
0
파일: view_test.go 프로젝트: hrautila/cmat
func TestViews(t *testing.T) {
	var As cmat.FloatMatrix
	N := 7
	A := cmat.NewMatrix(N, N)
	zeromean := cmat.NewFloatNormSource()
	A.SetFrom(zeromean)
	dlast := A.Get(-1, -1)
	t.Logf("A[-1,-1] = %10.3e\n", dlast)
	for i := 0; i < N; i++ {
		As.SubMatrix(A, i, i)
		As.Set(0, 0, As.Get(0, 0)+float64(i+1))
		if N < 10 {
			t.Logf("A[%d,%d]   = %10.3e\n", i, i, As.Get(0, 0))
		}
	}
	ok := float64(N)+dlast == A.Get(-1, -1)
	nC := int(A.Get(-1, -1) - dlast)
	t.Logf("add 1.0 %d times [%10.3e to %10.3e]: %v\n", nC, dlast, A.Get(-1, -1), ok)
}
예제 #13
0
파일: trired.go 프로젝트: hrautila/gomas
/*
 * Generates the real orthogonal matrix Q which is defined as the product of K elementary
 * reflectors of order N embedded in matrix A as returned by TRDReduce().
 *
 *   A     On entry tridiagonal reduction as returned by TRDReduce().
 *         On exit the orthogonal matrix Q.
 *
 *  tau    Scalar coefficients of elementary reflectors.
 *
 *  W      Workspace
 *
 *  K      Number of reflectors , 0 < K < N
 *
 *  flags  LOWER or UPPER
 *
 *  confs  Optional blocking configuration
 *
 * If flags has UPPER set then
 *    Q = H(K)...H(1)H(0) where 0 < K < N-1
 *
 * If flags has LOWR set then
 *    Q = H(0)H(1)...H(K) where 0 < K < N-1
 */
func TRDBuild(A, tau, W *cmat.FloatMatrix, K, flags int, confs ...*gomas.Config) *gomas.Error {
	var err *gomas.Error = nil
	var Qh, tauh cmat.FloatMatrix
	var s, d cmat.FloatMatrix

	if K > m(A)-1 {
		K = m(A) - 1
	}

	switch flags & (gomas.LOWER | gomas.UPPER) {
	case gomas.LOWER:
		// Shift Q matrix embedded in A right and fill first column
		// unit column vector
		for j := m(A) - 1; j > 0; j-- {
			s.SubMatrix(A, j, j-1, m(A)-j, 1)
			d.SubMatrix(A, j, j, m(A)-j, 1)
			blasd.Copy(&d, &s)
			A.Set(0, j, 0.0)
		}
		// zero first column and set first entry to one
		d.Column(A, 0)
		blasd.Scale(&d, 0.0)
		d.Set(0, 0, 1.0)

		Qh.SubMatrix(A, 1, 1, m(A)-1, m(A)-1)
		tauh.SubMatrix(tau, 0, 0, m(A)-1, 1)
		err = QRBuild(&Qh, &tauh, W, K, confs...)

	case gomas.UPPER:
		// Shift Q matrix embedded in A left and fill last column
		// unit column vector
		for j := 1; j < m(A); j++ {
			s.SubMatrix(A, 0, j, j, 1)
			d.SubMatrix(A, 0, j-1, j, 1)
			blasd.Copy(&d, &s)
			A.Set(-1, j-1, 0.0)
		}
		// zero last column and set last entry to one
		d.Column(A, m(A)-1)
		blasd.Scale(&d, 0.0)
		d.Set(-1, 0, 1.0)

		Qh.SubMatrix(A, 0, 0, m(A)-1, m(A)-1)
		tauh.SubMatrix(tau, 0, 0, m(A)-1, 1)
		err = QLBuild(&Qh, &tauh, W, K, confs...)
	}
	if err != nil {
		err.Update("TRDBuild")
	}
	return err
}
예제 #14
0
파일: givens.go 프로젝트: hrautila/gomas
/*
 * Compute A[i:i+nr,c1;c2] = A[i:i+nr,c1;c2]*G(c,s)
 *
 * Applies Givens rotation to nr rows of columns c1, c2 of A starting at row.
 *
 */
func ApplyGivensRight(A *cmat.FloatMatrix, c1, c2, row, nrow int, cos, sin float64) {
	if row >= m(A) {
		return
	}
	if c1 == c2 {
		// one column
		for k := row; k < row+nrow; k++ {
			v0 := A.Get(k, c1)
			A.Set(k, c1, cos*v0)
		}
		return
	}
	for k := row; k < row+nrow; k++ {
		v0 := A.Get(k, c1)
		v1 := A.Get(k, c2)
		y0 := cos*v0 + sin*v1
		y1 := cos*v1 - sin*v0
		A.Set(k, c1, y0)
		A.Set(k, c2, y1)
	}
}
예제 #15
0
파일: givens.go 프로젝트: hrautila/gomas
/*
 * Compute A[i:i+1,j:j+nc] = G(c,s)*A[i:i+1,j:j+nc]
 *
 * Applies Givens rotation to nc columns on rows r1,r2 of A starting from col.
 */
func ApplyGivensLeft(A *cmat.FloatMatrix, r1, r2, col, ncol int, cos, sin float64) {
	if col >= n(A) {
		return
	}
	if r1 == r2 {
		// one row
		for k := col; k < col+ncol; k++ {
			v0 := A.Get(r1, k)
			A.Set(r1, k, cos*v0)
		}
		return
	}
	for k := col; k < col+ncol; k++ {
		v0 := A.Get(r1, k)
		v1 := A.Get(r2, k)
		y0 := cos*v0 + sin*v1
		y1 := cos*v1 - sin*v0
		A.Set(r1, k, y0)
		A.Set(r2, k, y1)
	}
}
예제 #16
0
파일: pivot.go 프로젝트: hrautila/gomas
/*
 * Apply diagonal pivot (row and column swapped) to symmetric matrix blocks.
 * AR[0,0] is on diagonal and AL is block to the left of diagonal and AR the
 * triangular diagonal block. Need to swap row and column.
 *
 * LOWER triangular; moving from top-left to bottom-right
 *
 *    d
 *    x  d
 *    x  x  d  |
 *    --------------------------
 *    S1 S1 S1 | P1 x  x  x  P2     -- current row
 *    x  x  x  | S2 d  x  x  x
 *    x  x  x  | S2 x  d  x  x
 *    x  x  x  | S2 x  x  d  x
 *    D1 D1 D1 | P2 D2 D2 D2 P3     -- swap with row 'index'
 *    x  x  x  | S3 x  x  x  D3 d
 *    x  x  x  | S3 x  x  x  D3 x d
 *       (ABL)          (ABR)
 *
 * UPPER triangular; moving from bottom-right to top-left
 *
 *         (ATL)             (ATR)
 *    d  x  x  D3 x  x  x | S3 x  x
 *       d  x  D3 x  x  x | S3 x  x
 *          d  D3 x  x  x | S3 x  x
 *             P3 D2 D2 D2| P2 D1 D1
 *                d  x  x | S2 x  x
 *                   d  x | S2 x  x
 *                      d | S2 x  x
 *    -----------------------------
 *                        | P1 S1 S1
 *                        |    d  x
 *                        |       d
 *                           (ABR)
 */
func applyPivotSym(AL, AR *cmat.FloatMatrix, index int, flags int) {
	var s, d cmat.FloatMatrix
	lr, lc := AL.Size()
	rr, rc := AR.Size()

	if flags&gomas.LOWER != 0 {
		// AL is [ABL]; AR is [ABR]; P1 is AR[0,0], P2 is AR[index, 0]
		// S1 -- D1
		s.SubMatrix(AL, 0, 0, 1, lc)
		d.SubMatrix(AL, index, 0, 1, lc)
		blasd.Swap(&s, &d)
		// S2 -- D2
		s.SubMatrix(AR, 1, 0, index-1, 1)
		d.SubMatrix(AR, index, 1, 1, index-1)
		blasd.Swap(&s, &d)
		// S3 -- D3
		s.SubMatrix(AR, index+1, 0, rr-index-1, 1)
		d.SubMatrix(AR, index+1, index, rr-index-1, 1)
		blasd.Swap(&s, &d)
		// swap P1 and P3
		p1 := AR.Get(0, 0)
		p3 := AR.Get(index, index)
		AR.Set(0, 0, p3)
		AR.Set(index, index, p1)
		return
	}
	if flags&gomas.UPPER != 0 {
		// AL is merged from [ATL, ATR], AR is [ABR]; P1 is AR[0, 0]; P2 is AL[index, -1]
		colno := lc - rc
		// S1 -- D1; S1 is on the first row of AR
		s.SubMatrix(AR, 0, 1, 1, rc-1)
		d.SubMatrix(AL, index, colno+1, 1, rc-1)
		blasd.Swap(&s, &d)
		// S2 -- D2
		s.SubMatrix(AL, index+1, colno, lr-index-2, 1)
		d.SubMatrix(AL, index, index+1, 1, colno-index-1)
		blasd.Swap(&s, &d)
		// S3 -- D3
		s.SubMatrix(AL, 0, index, index, 1)
		d.SubMatrix(AL, 0, colno, index, 1)
		blasd.Swap(&s, &d)
		//fmt.Printf("3, AR=%v\n", AR)
		// swap P1 and P3
		p1 := AR.Get(0, 0)
		p3 := AL.Get(index, index)
		AR.Set(0, 0, p3)
		AL.Set(index, index, p1)
		return
	}
}
예제 #17
0
파일: pivot.go 프로젝트: hrautila/gomas
/*
 * Apply diagonal pivot (row and column swapped) to symmetric matrix blocks.
 * AR[0,0] is on diagonal and AL is block to the left of diagonal and AR the
 * triangular diagonal block. Need to swap row and column.
 *
 * LOWER triangular; moving from top-left to bottom-right
 *
 *    d
 *    x  d |
 *    --------------------------
 *    x  x | d
 *    S1 S1| S1 P1 x  x  x  P2     -- current row/col 'srcix'
 *    x  x | x  S2 d  x  x  x
 *    x  x | x  S2 x  d  x  x
 *    x  x | x  S2 x  x  d  x
 *    D1 D1| D1 P2 D2 D2 D2 P3     -- swap with row/col 'dstix'
 *    x  x | x  S3 x  x  x  D3 d
 *    x  x | x  S3 x  x  x  D3 x d
 *    (ABL)          (ABR)
 *
 * UPPER triangular; moving from bottom-right to top-left
 *
 *         (ATL)                  (ATR)
 *    d  x  x  D3 x  x  x  S3 x | x
 *       d  x  D3 x  x  x  S3 x | x
 *          d  D3 x  x  x  S3 x | x
 *             P3 D2 D2 D2 P2 D1| D1  -- dstinx
 *                d  x  x  S2 x | x
 *                   d  x  S2 x | x
 *                      d  S2 x | x
 *                         P1 S1| S1  -- srcinx
 *                            d | x
 *    -----------------------------
 *                              | d
 *                           (ABR)
 */
func applyPivotSym2(AL, AR *cmat.FloatMatrix, srcix, dstix int, flags int) {
	var s, d cmat.FloatMatrix
	_, lc := AL.Size()
	rr, rc := AR.Size()
	if flags&gomas.LOWER != 0 {
		// AL is [ABL]; AR is [ABR]; P1 is AR[0,0], P2 is AR[index, 0]
		// S1 -- D1
		AL.SubMatrix(&s, srcix, 0, 1, lc)
		AL.SubMatrix(&d, dstix, 0, 1, lc)
		blasd.Swap(&s, &d)
		if srcix > 0 {
			AR.SubMatrix(&s, srcix, 0, 1, srcix)
			AR.SubMatrix(&d, dstix, 0, 1, srcix)
			blasd.Swap(&s, &d)
		}
		// S2 -- D2
		AR.SubMatrix(&s, srcix+1, srcix, dstix-srcix-1, 1)
		AR.SubMatrix(&d, dstix, srcix+1, 1, dstix-srcix-1)
		blasd.Swap(&s, &d)
		// S3 -- D3
		AR.SubMatrix(&s, dstix+1, srcix, rr-dstix-1, 1)
		AR.SubMatrix(&d, dstix+1, dstix, rr-dstix-1, 1)
		blasd.Swap(&s, &d)
		// swap P1 and P3
		p1 := AR.Get(srcix, srcix)
		p3 := AR.Get(dstix, dstix)
		AR.Set(srcix, srcix, p3)
		AR.Set(dstix, dstix, p1)
		return
	}
	if flags&gomas.UPPER != 0 {
		// AL is ATL, AR is ATR; P1 is AL[srcix, srcix];
		// S1 -- D1;
		AR.SubMatrix(&s, srcix, 0, 1, rc)
		AR.SubMatrix(&d, dstix, 0, 1, rc)
		blasd.Swap(&s, &d)
		if srcix < lc-1 {
			// not the corner element
			AL.SubMatrix(&s, srcix, srcix+1, 1, srcix)
			AL.SubMatrix(&d, dstix, srcix+1, 1, srcix)
			blasd.Swap(&s, &d)
		}
		// S2 -- D2
		AL.SubMatrix(&s, dstix+1, srcix, srcix-dstix-1, 1)
		AL.SubMatrix(&d, dstix, dstix+1, 1, srcix-dstix-1)
		blasd.Swap(&s, &d)
		// S3 -- D3
		AL.SubMatrix(&s, 0, srcix, dstix, 1)
		AL.SubMatrix(&d, 0, dstix, dstix, 1)
		blasd.Swap(&s, &d)
		//fmt.Printf("3, AR=%v\n", AR)
		// swap P1 and P3
		p1 := AR.Get(0, 0)
		p3 := AL.Get(dstix, dstix)
		AR.Set(srcix, srcix, p3)
		AL.Set(dstix, dstix, p1)
		return
	}
}
예제 #18
0
파일: trdsec.go 프로젝트: hrautila/gomas
func trdsecEigenBuildInplace(Q, z *cmat.FloatMatrix) {
	var QTL, QBR, Q00, q11, q12, q21, Q22, qi cmat.FloatMatrix
	var zk0, zk1, dk0, dk1 float64

	util.Partition2x2(
		&QTL, nil,
		nil, &QBR /**/, Q, 0, 0, util.PTOPLEFT)

	for m(&QBR) > 0 {
		util.Repartition2x2to3x3(&QTL,
			&Q00, nil, nil,
			nil, &q11, &q12,
			nil, &q21, &Q22 /**/, Q, 1, util.PBOTTOMRIGHT)
		//---------------------------------------------------------------
		k := m(&Q00)
		zk0 = z.GetAt(k)
		dk0 = q11.Get(0, 0)
		q11.Set(0, 0, zk0/dk0)

		for i := 0; i < q12.Len(); i++ {
			zk1 = z.GetAt(k + i + 1)
			dk0 = q12.GetAt(i)
			dk1 = q21.GetAt(i)
			q12.SetAt(i, zk0/dk1)
			q21.SetAt(i, zk1/dk0)
		}
		//---------------------------------------------------------------
		util.Continue3x3to2x2(
			&QTL, nil,
			nil, &QBR /**/, &Q00, &q11, &Q22 /**/, Q, util.PBOTTOMRIGHT)
	}
	// scale column eigenvectors
	for k := 0; k < z.Len(); k++ {
		qi.Column(Q, k)
		t := blasd.Nrm2(&qi)
		blasd.InvScale(&qi, t)
	}
}
예제 #19
0
파일: chol.go 프로젝트: hrautila/gomas
func unblockedLowerCHOL(A *cmat.FloatMatrix, flags int, nr int) (err *gomas.Error) {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a10, a11, A20, a21, A22 cmat.FloatMatrix

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

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

		// a11 = sqrt(a11)
		aval := a11.Get(0, 0)
		if aval < 0.0 {
			if err == nil {
				err = gomas.NewError(gomas.ENEGATIVE, "DecomposeCHOL", m(&ATL)+nr)
			}
		} else {
			a11.Set(0, 0, math.Sqrt(aval))
		}

		// a21 = a21/a11
		blasd.InvScale(&a21, a11.Get(0, 0))
		// A22 = A22 - a21*a21' (SYR)
		blasd.MVUpdateSym(&A22, &a21, -1.0, gomas.LOWER)

		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)

	}
	return
}
예제 #20
0
파일: house.go 프로젝트: hrautila/gomas
/* From LAPACK/dlarfg.f
 *
 * Generates a real elementary reflector H of order n, such
 * that
 *
 *       H * ( alpha ) = ( beta ),   H**T * H = I.
 *           (   x   )   (   0  )
 *
 * where alpha and beta are scalars, and x is an (n-1)-element real
 * vector. 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 (n-1)-element
 * vector.
 *
 * If the elements of x are all zero, then tau = 0 and H is taken to be
 * the unit cmat.
 *
 * Otherwise  1 <= tau <= 2.
 */
func computeHouseholder(a11, x, tau *cmat.FloatMatrix) {

	// norm_x2 = ||x||_2
	norm_x2 := blasd.Nrm2(x)
	if norm_x2 == 0.0 {
		tau.Set(0, 0, 0.0)
		return
	}

	alpha := a11.Get(0, 0)
	sign := 1.0
	if math.Signbit(alpha) {
		sign = -1.0
	}
	// beta = -(alpha / |alpha|) * ||alpha x||
	//      = -sign(alpha) * sqrt(alpha**2, norm_x2**2)
	beta := -sign * sqrtX2Y2(alpha, norm_x2)

	// x = x /(a11 - beta)
	blasd.InvScale(x, alpha-beta)

	tau.Set(0, 0, (beta-alpha)/beta)
	a11.Set(0, 0, beta)
}
예제 #21
0
파일: hess.go 프로젝트: hrautila/gomas
/*
 * 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)
	}
}
예제 #22
0
파일: hess.go 프로젝트: hrautila/gomas
/*
 * Blocked version of Hessenberg reduction algorithm as presented in (1). This
 * version uses compact-WY transformation.
 *
 * Some notes:
 *
 * Elementary reflectors stored in [A11; A21].T are not on diagonal of A11. Update of
 * a block aligned with A11; A21 is as follow
 *
 * 1. Update from left Q(k)*C:
 *                                         c0   0                            c0
 * (I - Y*T*Y.T).T*C = C - Y*(C.T*Y)*T.T = C1 - Y1 * (C1.T.Y1+C2.T*Y2)*T.T = C1-Y1*W
 *                                         C2   Y2                           C2-Y2*W
 *
 * where W = (C1.T*Y1+C2.T*Y2)*T.T and first row of C is not affected by update
 *
 * 2. Update from right C*Q(k):
 *                                       0
 * C - C*Y*T*Y.T = c0;C1;C2 - c0;C1;C2 * Y1 *T*(0;Y1;Y2) = c0; C1-W*Y1; C2-W*Y2
 *                                       Y2
 * where  W = (C1*Y1 + C2*Y2)*T and first column of C is not affected
 *
 */
func blkHessGQvdG(A, Tvec, W *cmat.FloatMatrix, nb int, conf *gomas.Config) *gomas.Error {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, A11, A12, A21, A22, A2 cmat.FloatMatrix
	var tT, tB, td cmat.FloatMatrix
	var t0, t1, t2, T cmat.FloatMatrix
	var V, VT, VB /*V0, V1, V2,*/, Y1, Y2, W0 cmat.FloatMatrix

	//fmt.Printf("blkHessGQvdG...\n")
	T.SubMatrix(W, 0, 0, conf.LB, conf.LB)
	V.SubMatrix(W, conf.LB, 0, m(A), conf.LB)
	td.Diag(&T)

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)
	util.Partition2x1(
		&tT,
		&tB, Tvec, 0, util.PTOP)

	for m(&ABR) > nb+1 && n(&ABR) > nb {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			nil, &A11, &A12,
			nil, &A21, &A22, A, nb, util.PBOTTOMRIGHT)
		util.Repartition2x1to3x1(&tT,
			&t0,
			&t1,
			&t2, Tvec, nb, util.PBOTTOM)

		util.Partition2x1(
			&VT,
			&VB, &V, m(&ATL), util.PTOP)
		// ------------------------------------------------------

		unblkBuildHessGQvdG(&ABR, &T, &VB, nil)
		blasd.Copy(&t1, &td)

		// m(Y) == m(ABR)-1, n(Y) == n(A11)
		Y1.SubMatrix(&ABR, 1, 0, n(&A11), n(&A11))
		Y2.SubMatrix(&ABR, 1+n(&A11), 0, m(&A21)-1, n(&A11))

		// [A01; A02] == ATR := ATR*(I - Y*T*Y.T)
		updateHessRightWY(&ATR, &Y1, &Y2, &T, &VT, conf)

		// A2 = [A12; A22].T
		util.Merge2x1(&A2, &A12, &A22)

		// A2 := A2 - VB*T*A21.T
		be := A21.Get(0, -1)
		A21.Set(0, -1, 1.0)
		blasd.MultTrm(&VB, &T, 1.0, gomas.UPPER|gomas.RIGHT)
		blasd.Mult(&A2, &VB, &A21, -1.0, 1.0, gomas.TRANSB, conf)
		A21.Set(0, -1, be)

		// A2 := (I - Y*T*Y.T).T * A2
		W0.SubMatrix(&V, 0, 0, n(&A2), n(&Y2))
		updateHessLeftWY(&A2, &Y1, &Y2, &T, &W0, conf)

		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &A11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue3x1to2x1(
			&tT,
			&tB, &t0, &t1, Tvec, util.PBOTTOM)
	}

	if m(&ABR) > 1 {
		// do the rest with unblocked
		util.Merge2x1(&A2, &ATR, &ABR)
		W0.SetBuf(m(A), 1, m(A), W.Data())
		unblkHessGQvdG(&A2, &tB, &W0, m(&ATR))
	}
	return nil
}
예제 #23
0
파일: hess.go 프로젝트: hrautila/gomas
/*
 *
 *  Building reduction block for blocked algorithm as described in (1).
 *
 *  A. update next column
 *    a10        [(U00)     (U00)  ]   [(a10)    (V00)            ]
 *    a11 :=  I -[(u10)*T00*(u10).T] * [(a11)  - (v01) * T00 * a10]
 *    a12        [(U20)     (U20)  ]   [(a12)    (V02)            ]
 *
 *  B. compute Householder reflector for updated column
 *    a21, t11 := Householder(a21)
 *
 *  C. update intermediate reductions
 *    v10      A02*a21
 *    v11  :=  a12*a21
 *    v12      A22*a21
 *
 *  D. update block reflector
 *    t01 :=  A20*a21
 *    t11 :=  t11
 */
func unblkBuildHessGQvdG(A, T, V, W *cmat.FloatMatrix) *gomas.Error {

	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a10, a11, A20, a21, A22 cmat.FloatMatrix
	var AL, AR, A0, a1, A2 cmat.FloatMatrix
	var TTL, TTR, TBL, TBR cmat.FloatMatrix
	var T00, t01, t11, T22 cmat.FloatMatrix
	var VL, VR, V0, v1, V2, Y0 cmat.FloatMatrix

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)
	util.Partition2x2(
		&TTL, &TTR,
		&TBL, &TBR, T, 0, 0, util.PTOPLEFT)
	util.Partition1x2(
		&AL, &AR, A, 0, util.PLEFT)
	util.Partition1x2(
		&VL, &VR, V, 0, util.PLEFT)

	var beta float64

	for n(&VR) > 0 {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10, &a11, nil,
			&A20, &a21, &A22, A, 1, util.PBOTTOMRIGHT)
		util.Repartition2x2to3x3(&TTL,
			&T00, &t01, nil,
			nil, &t11, nil,
			nil, nil, &T22, T, 1, util.PBOTTOMRIGHT)
		util.Repartition1x2to1x3(&AL,
			&A0, &a1, &A2, A, 1, util.PRIGHT)
		util.Repartition1x2to1x3(&VL,
			&V0, &v1, &V2, V, 1, util.PRIGHT)

		// ------------------------------------------------------
		// Compute Hessenberg update for next column of A:
		if n(&V0) > 0 {
			// y10 := T00*a10  (use t01 as workspace?)
			blasd.Axpby(&t01, &a10, 1.0, 0.0)
			blasd.MVMultTrm(&t01, &T00, 1.0, gomas.UPPER)

			// a1 := a1 - V0*T00*a10
			blasd.MVMult(&a1, &V0, &t01, -1.0, 1.0, gomas.NONE)

			// update a1 := (I - Y*T*Y.T).T*a1 (here t01 as workspace)
			Y0.SubMatrix(A, 1, 0, n(&A00), n(&A00))
			updateVecLeftWY2(&a1, &Y0, &A20, &T00, &t01, gomas.TRANS)
			a10.Set(0, -1, beta)
		}

		// Compute Householder reflector
		computeHouseholderVec(&a21, &t11)
		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)

		// update T
		tauval := t11.Get(0, 0)
		if tauval != 0.0 {
			// t01 := -tauval*A20.T*a21
			blasd.MVMult(&t01, &A20, &a21, -tauval, 0.0, gomas.TRANS)
			// t01 := T00*t01
			blasd.MVMultTrm(&t01, &T00, 1.0, gomas.UPPER)
		}
		// ------------------------------------------------------
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue3x3to2x2(
			&TTL, &TTR,
			&TBL, &TBR, &T00, &t11, &T22, T, util.PBOTTOMRIGHT)
		util.Continue1x3to1x2(
			&AL, &AR, &A0, &a1, A, util.PRIGHT)
		util.Continue1x3to1x2(
			&VL, &VR, &V0, &v1, V, util.PRIGHT)
	}
	A.Set(n(V), n(V)-1, beta)
	return nil
}
예제 #24
0
파일: ldlbku.go 프로젝트: hrautila/gomas
func unblkBoundedBKUpper(A, wrk *cmat.FloatMatrix, p *Pivots, ncol int, conf *gomas.Config) (*gomas.Error, int) {
	var err *gomas.Error = nil
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a01, A02, a11, a12, A22, a11inv cmat.FloatMatrix
	var w00, w01, w11 cmat.FloatMatrix
	var cwrk cmat.FloatMatrix
	var pT, pB, p0, p1, p2 Pivots

	err = nil
	nc := 0
	if ncol > n(A) {
		ncol = n(A)
	}

	// permanent working space for symmetric inverse of a11
	a11inv.SubMatrix(wrk, m(wrk)-2, 0, 2, 2)
	a11inv.Set(0, 1, -1.0)
	a11inv.Set(1, 0, -1.0)

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PBOTTOMRIGHT)
	partitionPivot2x1(
		&pT,
		&pB, *p, 0, util.PBOTTOM)

	for n(&ATL) > 0 && nc < ncol {

		util.Partition2x2(
			&w00, &w01,
			nil, &w11, wrk, nc, nc, util.PBOTTOMRIGHT)

		r, np := findAndBuildBKPivotUpper(&ATL, &ATR, &w00, &w01, nc)
		if np > ncol-nc {
			// next pivot does not fit into ncol columns,
			// return with number of factorized columns
			return err, nc
		}
		cwrk.SubMatrix(&w00, 0, n(&w00)-np, m(&ATL), np)
		if r != -1 {
			// pivoting needed; do swaping here
			k := m(&ATL) - np
			applyBKPivotSymUpper(&ATL, k, r)
			// swap right hand rows to get correct updates
			swapRows(&ATR, k, r)
			swapRows(&w01, k, r)
			if np == 2 && r != k {
				/* for 2x2 blocks we need diagonal pivots.
				 *          [r, r] | [ r,-1]
				 * a11 ==   ----------------  2-by-2 pivot, swapping [1,0] and [r,0]
				 *          [-1,r] | [-1,-1]
				 */
				t0 := w00.Get(k, -1)
				tr := w00.Get(r, -1)
				w00.Set(k, -1, tr)
				w00.Set(r, -1, t0)
				t0 = w00.Get(k, -2)
				tr = w00.Get(r, -2)
				w00.Set(k, -2, tr)
				w00.Set(r, -2, t0)
			}
		}
		// repartition according the pivot size
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			nil, &a11, &a12,
			nil, nil, &A22 /**/, A, np, util.PTOPLEFT)
		repartPivot2x1to3x1(&pT,
			&p0,
			&p1,
			&p2 /**/, *p, np, util.PTOP)
		// ------------------------------------------------------------

		wlc := n(&w00) - np
		cwrk.SubMatrix(&w00, 0, wlc, m(&a01), n(&a01))
		if np == 1 {
			//
			a11.Set(0, 0, w00.Get(m(&a01), wlc))
			// a21 = a21/a11
			blasd.Copy(&a01, &cwrk)
			blasd.InvScale(&a01, a11.Get(0, 0))
			// store pivot point relative to original matrix
			if r == -1 {
				p1[0] = m(&ATL)
			} else {
				p1[0] = r + 1
			}
		} else if np == 2 {
			/*          a | b                       d/b | -1
			 *  w00 == ------  == a11 --> a11.-1 == -------- * scale
			 *          . | d                        -1 | a/b
			 */
			a := w00.Get(m(&ATL)-2, -2)
			b := w00.Get(m(&ATL)-2, -1)
			d := w00.Get(m(&ATL)-1, -1)
			a11inv.Set(0, 0, d/b)
			a11inv.Set(1, 1, a/b)
			// denominator: (a/b)*(d/b)-1.0 == (a*d - b^2)/b^2
			scale := 1.0 / ((a/b)*(d/b) - 1.0)
			scale /= b

			// a01 = a01*a11.-1
			blasd.Mult(&a01, &cwrk, &a11inv, scale, 0.0, gomas.NONE, conf)
			a11.Set(0, 0, a)
			a11.Set(0, 1, b)
			a11.Set(1, 1, d)

			// store pivot point relative to original matrix
			p1[0] = -(r + 1)
			p1[1] = p1[0]
		}
		// ------------------------------------------------------------
		nc += np
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PTOPLEFT)
		contPivot3x1to2x1(
			&pT,
			&pB, p0, p1, *p, util.PTOP)

	}
	return err, nc
}
예제 #25
0
파일: rqmult.go 프로젝트: hrautila/gomas
/*
 * Multiply and replace C with Q*C or Q.T*C where Q is a real orthogonal matrix
 * defined as the product of k elementary reflectors.
 *
 *    Q = H(0)H(1)...H(K-1)
 *
 * as returned by RQFactor().
 *
 * Arguments:
 *  C     On entry, the M-by-N matrix C or if flag bit RIGHT is set then
 *        N-by-M matrix.  On exit C is overwritten by Q*C or Q.T*C.
 *        If bit RIGHT is set then C is  overwritten by C*Q or C*Q.T
 *
 *  A     RQ factorization as returned by RQFactor() where the upper
 *        trapezoidal part holds the elementary reflectors.
 *
 *  tau   The scalar factors of the elementary reflectors.
 *
 *  W     Workspace matrix,  required size is returned by RQMultWork().
 *
 *  flags Indicators. Valid indicators LEFT, RIGHT, TRANS
 *
 *  conf  Blocking configuration. Field LB defines block sized. If it is zero
 *        unblocked invocation is assumed.
 *
 * Compatible with lapack.DORMRQ
 *
 * Notes:
 *   m(A) is number of elementary reflectors
 *   n(A) is the order of the Q matrix
 *
 *   LEFT : m(C) >= n(Q) --> m(A) <= n(C) <= n(A)
 *   RIGHT: n(C) >= m(Q) --> m(A) <= m(C) <= n(A)
 */
func RQMult(C, A, tau, W *cmat.FloatMatrix, flags int, confs ...*gomas.Config) *gomas.Error {
	var err *gomas.Error = nil
	var wsmin int
	var tauval float64
	var Qh, tauh cmat.FloatMatrix
	conf := gomas.CurrentConf(confs...)

	// default to multiply from left if side not defined
	if flags&(gomas.LEFT|gomas.RIGHT) == 0 {
		flags = flags | gomas.LEFT
	}
	// m(A) is number of elementary reflectors, Q is n(A)-by-n(A) matrix
	ok := false
	lb := 0
	hr, hc := m(A), n(A)
	switch flags & gomas.RIGHT {
	case gomas.RIGHT:
		ok = n(C) <= n(A) && m(A) <= n(C)
		wsmin = wsMultRQRight(C, 0)
		hc = n(C)
		lb = estimateLB(C, W.Len(), wsMultRQRight)
	default:
		ok = m(C) <= n(A) && m(A) <= m(C)
		wsmin = wsMultRQLeft(C, 0)
		hc = m(C)
		lb = estimateLB(C, W.Len(), wsMultRQLeft)
	}
	if !ok {
		return gomas.NewError(gomas.ESIZE, "MultRQ")
	}
	if W == nil || W.Len() < wsmin {
		return gomas.NewError(gomas.EWORK, "MultRQ", wsmin)
	}
	lb = imin(lb, conf.LB)
	Qh.SubMatrix(A, 0, 0, hr, hc)
	tauh.SubMatrix(tau, 0, 0, m(A), 1)
	if hc == hr {
		// m-by-m multiplication, H(K) is unit vector
		// set last tauval to zero, householder functions expect this
		tauval = tau.Get(hc-1, 0)
		tau.Set(hc-1, 0, 0.0)
	}
	if lb == 0 || m(A) <= lb {
		if flags&gomas.RIGHT != 0 {
			unblockedMultRQRight(C, &Qh, &tauh, W, flags)
		} else {
			unblockedMultRQLeft(C, &Qh, &tauh, W, flags)
		}
	} else {
		//lb = conf.LB
		if flags&gomas.RIGHT != 0 {
			blockedMultRQRight(C, &Qh, &tauh, W, flags, lb, conf)
		} else {
			blockedMultRQLeft(C, &Qh, &tauh, W, flags, lb, conf)
		}
	}
	if hc == hr {
		// restore tau value
		tau.Set(hc-1, 0, tauval)
	}
	return err
}
예제 #26
0
파일: trired.go 프로젝트: hrautila/gomas
/*
 * This is adaptation of TRIRED_LAZY_UNB algorithm from (1).
 */
func unblkBuildTridiagUpper(A, tauq, Y, W *cmat.FloatMatrix) {
	var ATL, ABR cmat.FloatMatrix
	var A00, a01, A02, a11, a12, A22 cmat.FloatMatrix
	var YTL, YBR cmat.FloatMatrix
	var Y00, y01, Y02, y11, y12, Y22 cmat.FloatMatrix
	var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix
	var w12 cmat.FloatMatrix
	var v0 float64

	util.Partition2x2(
		&ATL, nil,
		nil, &ABR, A, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x2(
		&YTL, nil,
		nil, &YBR, Y, 0, 0, util.PBOTTOMRIGHT)
	util.Partition2x1(
		&tqT,
		&tqB, tauq, 0, util.PBOTTOM)

	k := 0
	for k < n(Y) {
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			nil, &a11, &a12,
			nil, nil, &A22, A, 1, util.PTOPLEFT)
		util.Repartition2x2to3x3(&YTL,
			&Y00, &y01, &Y02,
			nil, &y11, &y12,
			nil, nil, &Y22, Y, 1, util.PTOPLEFT)
		util.Repartition2x1to3x1(&tqT,
			&tq0,
			&tauq1,
			&tq2, tauq, 1, util.PTOP)

		// set temp vectors for this round
		w12.SubMatrix(Y, -1, 0, 1, n(&Y02))
		// ------------------------------------------------------

		if n(&Y02) > 0 {
			aa := blasd.Dot(&a12, &y12)
			aa += blasd.Dot(&y12, &a12)
			a11.Set(0, 0, a11.Get(0, 0)-aa)

			// a01 := a01 - A02*y12
			blasd.MVMult(&a01, &A02, &y12, -1.0, 1.0, gomas.NONE)
			// a01 := a01 - Y02*a12
			blasd.MVMult(&a01, &Y02, &a12, -1.0, 1.0, gomas.NONE)

			// restore superdiagonal value
			a12.Set(0, 0, v0)
		}
		// Compute householder to zero subdiagonal entries
		computeHouseholderRev(&a01, &tauq1)
		tauqv := tauq1.Get(0, 0)

		// set sub&iagonal to unit
		v0 = a01.Get(-1, 0)
		a01.Set(-1, 0, 1.0)

		// y01 := tauq*A00*a01
		blasd.MVMultSym(&y01, &A00, &a01, tauqv, 0.0, gomas.UPPER)
		// w12 := A02.T*a01
		blasd.MVMult(&w12, &A02, &a01, 1.0, 0.0, gomas.TRANS)
		// y01 := y01 - Y02*(A02.T*a01)
		blasd.MVMult(&y01, &Y02, &w12, -tauqv, 1.0, gomas.NONE)
		// w12 := Y02.T*a01
		blasd.MVMult(&w12, &Y02, &a01, 1.0, 0.0, gomas.TRANS)
		// y01 := y01 - A02*(Y02.T*a01)
		blasd.MVMult(&y01, &A02, &w12, -tauqv, 1.0, gomas.NONE)

		// beta := tauq*a01.T*y01
		beta := tauqv * blasd.Dot(&a01, &y01)
		// y01  := y01 - 0.5*beta*a01
		blasd.Axpy(&y01, &a01, -0.5*beta)

		// ------------------------------------------------------
		k += 1
		util.Continue3x3to2x2(
			&ATL, nil,
			nil, &ABR, &A00, &a11, &A22, A, util.PTOPLEFT)
		util.Continue3x3to2x2(
			&YTL, nil,
			nil, &YBR, &Y00, &y11, &Y22, A, util.PTOPLEFT)
		util.Continue3x1to2x1(
			&tqT,
			&tqB, &tq0, &tauq1, tauq, util.PTOP)
	}
	// restore superdiagonal value
	A.Set(m(&ATL)-1, n(&ATL), v0)
}
예제 #27
0
파일: ldlbku.go 프로젝트: hrautila/gomas
/*
 * Unblocked Bunch-Kauffman LDL factorization.
 *
 * Corresponds lapack.DSYTF2
 */
func unblkDecompBKUpper(A, wrk *cmat.FloatMatrix, p Pivots, conf *gomas.Config) (*gomas.Error, int) {
	var err *gomas.Error = nil
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a01, A02, a11, a12, A22, a11inv cmat.FloatMatrix
	var cwrk cmat.FloatMatrix
	var pT, pB, p0, p1, p2 Pivots

	err = nil
	nc := 0

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PBOTTOMRIGHT)
	partitionPivot2x1(
		&pT,
		&pB, p, 0, util.PBOTTOM)

	// permanent working space for symmetric inverse of a11
	a11inv.SubMatrix(wrk, 0, n(wrk)-2, 2, 2)
	a11inv.Set(1, 0, -1.0)
	a11inv.Set(0, 1, -1.0)

	for n(&ATL) > 0 {

		nr := m(&ATL) - 1
		r, np := findBKPivotUpper(&ATL)
		if r != -1 {
			cwrk.SubMatrix(&ATL, 0, n(&ATL)-np, m(&ATL), np)
			// pivoting needed; do swaping here
			applyBKPivotSymUpper(&ATL, m(&ATL)-np, r)
			if np == 2 {
				/*          [r, r] | [r, nr]
				 * a11 ==   ----------------  2-by-2 pivot, swapping [nr-1,nr] and [r,nr]
				 *          [nr,r] | [nr,nr]  (nr is the current diagonal entry)
				 */
				t := ATL.Get(nr-1, nr)
				ATL.Set(nr-1, nr, ATL.Get(r, nr))
				ATL.Set(r, nr, t)
			}
		}

		// repartition according the pivot size
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			nil, &a11, &a12,
			nil, nil, &A22 /**/, A, np, util.PTOPLEFT)
		repartPivot2x1to3x1(&pT,
			&p0,
			&p1,
			&p2 /**/, p, np, util.PTOP)
		// ------------------------------------------------------------

		if np == 1 {
			// A00 = A00 - a01*a01.T/a11
			blasd.MVUpdateTrm(&A00, &a01, &a01, -1.0/a11.Get(0, 0), gomas.UPPER)
			// a01 = a01/a11
			blasd.InvScale(&a01, a11.Get(0, 0))
			// store pivot point relative to original matrix
			if r == -1 {
				p1[0] = m(&ATL)
			} else {
				p1[0] = r + 1
			}
		} else if np == 2 {
			/* see comments on unblkDecompBKLower() */
			a := a11.Get(0, 0)
			b := a11.Get(0, 1)
			d := a11.Get(1, 1)
			a11inv.Set(0, 0, d/b)
			a11inv.Set(1, 1, a/b)
			// denominator: (a/b)*(d/b)-1.0 == (a*d - b^2)/b^2
			scale := 1.0 / ((a/b)*(d/b) - 1.0)
			scale /= b

			// cwrk = a21
			cwrk.SubMatrix(wrk, 2, 0, m(&a01), n(&a01))
			blasd.Copy(&cwrk, &a01)
			// a01 = a01*a11.-1
			blasd.Mult(&a01, &cwrk, &a11inv, scale, 0.0, gomas.NONE, conf)
			// A00 = A00 - a01*a11.-1*a01.T = A00 - a01*cwrk.T
			blasd.UpdateTrm(&A00, &a01, &cwrk, -1.0, 1.0, gomas.UPPER|gomas.TRANSB, conf)
			// store pivot point relative to original matrix
			p1[0] = -(r + 1)
			p1[1] = p1[0]
		}
		// ------------------------------------------------------------
		nc += np
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PTOPLEFT)
		contPivot3x1to2x1(
			&pT,
			&pB, p0, p1, p, util.PTOP)
	}
	return err, nc
}
예제 #28
0
파일: ldlbku.go 프로젝트: hrautila/gomas
/*
 * 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
}
예제 #29
0
파일: trired.go 프로젝트: hrautila/gomas
/*
 * This is adaptation of TRIRED_LAZY_UNB algorithm from (1).
 */
func unblkBuildTridiagLower(A, tauq, Y, W *cmat.FloatMatrix) {
	var ATL, ABR cmat.FloatMatrix
	var A00, a10, a11, A20, a21, A22 cmat.FloatMatrix
	var YTL, YBR cmat.FloatMatrix
	var Y00, y10, y11, Y20, y21, Y22 cmat.FloatMatrix
	var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix
	var w12 cmat.FloatMatrix
	var v0 float64

	util.Partition2x2(
		&ATL, nil,
		nil, &ABR, A, 0, 0, util.PTOPLEFT)
	util.Partition2x2(
		&YTL, nil,
		nil, &YBR, Y, 0, 0, util.PTOPLEFT)
	util.Partition2x1(
		&tqT,
		&tqB, tauq, 0, util.PTOP)

	k := 0
	for k < n(Y) {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10, &a11, nil,
			&A20, &a21, &A22, A, 1, util.PBOTTOMRIGHT)
		util.Repartition2x2to3x3(&YTL,
			&Y00, nil, nil,
			&y10, &y11, nil,
			&Y20, &y21, &Y22, Y, 1, util.PBOTTOMRIGHT)
		util.Repartition2x1to3x1(&tqT,
			&tq0,
			&tauq1,
			&tq2, tauq, 1, util.PBOTTOM)
		// set temp vectors for this round
		//w12.SetBuf(y10.Len(), 1, y10.Len(), W.Data())
		w12.SubMatrix(Y, 0, 0, 1, n(&Y00))
		// ------------------------------------------------------

		if n(&Y00) > 0 {
			aa := blasd.Dot(&a10, &y10)
			aa += blasd.Dot(&y10, &a10)
			a11.Set(0, 0, a11.Get(0, 0)-aa)

			// a21 := a21 - A20*y10
			blasd.MVMult(&a21, &A20, &y10, -1.0, 1.0, gomas.NONE)
			// a21 := a21 - Y20*a10
			blasd.MVMult(&a21, &Y20, &a10, -1.0, 1.0, gomas.NONE)

			// restore subdiagonal value
			a10.Set(0, -1, v0)
		}
		// Compute householder to zero subdiagonal entries
		computeHouseholderVec(&a21, &tauq1)
		tauqv := tauq1.Get(0, 0)

		// set subdiagonal to unit
		v0 = a21.Get(0, 0)
		a21.Set(0, 0, 1.0)

		// y21 := tauq*A22*a21
		blasd.MVMultSym(&y21, &A22, &a21, tauqv, 0.0, gomas.LOWER)
		// w12 := A20.T*a21
		blasd.MVMult(&w12, &A20, &a21, 1.0, 0.0, gomas.TRANS)
		// y21 := y21 - Y20*(A20.T*a21)
		blasd.MVMult(&y21, &Y20, &w12, -tauqv, 1.0, gomas.NONE)
		// w12 := Y20.T*a21
		blasd.MVMult(&w12, &Y20, &a21, 1.0, 0.0, gomas.TRANS)
		// y21 := y21 - A20*(Y20.T*a21)
		blasd.MVMult(&y21, &A20, &w12, -tauqv, 1.0, gomas.NONE)

		// beta := tauq*a21.T*y21
		beta := tauqv * blasd.Dot(&a21, &y21)
		// y21  := y21 - 0.5*beta*a21
		blasd.Axpy(&y21, &a21, -0.5*beta)

		// ------------------------------------------------------
		k += 1
		util.Continue3x3to2x2(
			&ATL, nil,
			nil, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
		util.Continue3x3to2x2(
			&YTL, nil,
			nil, &YBR, &Y00, &y11, &Y22, A, util.PBOTTOMRIGHT)
		util.Continue3x1to2x1(
			&tqT,
			&tqB, &tq0, &tauq1, tauq, util.PBOTTOM)
	}
	// restore subdiagonal value
	A.Set(m(&ATL), n(&ATL)-1, v0)
}
예제 #30
0
파일: ldlbku.go 프로젝트: hrautila/gomas
/*
 * Find diagonal pivot and build incrementaly updated block.
 *
 *    d x r2 x  x  x  c1 | x x     kp1 k | w w
 *      d r2 x  x  x  c1 | x x     kp1 k | w w
 *        r2 r2 r2 r2 c1 | x x     kp1 k | w w
 *           d  x  x  c1 | x x     kp1 k | w w
 *              d  x  c1 | x x     kp1 k | w w
 *                 d  c1 | x x     kp1 k | w w
 *                    c1 | x x     kp1 k | w w
 *   --------------------------   -------------
 *               (AL)     (AR)     (WL)   (WR)
 *
 * Matrix AL contains the unfactored part of the matrix and AR the already
 * factored columns. Matrix WR is updated values of factored part ie.
 * w(i) = l(i)d(i). Matrix WL will have updated values for next column.
 * Column WL(k) contains updated AL(c1) and WL(kp1) possible pivot row AL(r2).
 *
 * On exit, for 1x1 diagonal the rightmost column of WL (k) holds the updated
 * value of AL(c1). If pivoting this required the WL(k) holds the actual pivoted
 * column/row.
 *
 * For 2x2 diagonal blocks WL(k) holds the updated AL(c1) and WL(kp1) holds
 * actual values of pivot column/row AL(r2), without the diagonal pivots.
 */
func findAndBuildBKPivotUpper(AL, AR, WL, WR *cmat.FloatMatrix, k int) (int, int) {
	var r, q int
	var rcol, qrow, src, wk, wkp1, wrow cmat.FloatMatrix

	lc := n(AL) - 1
	wc := n(WL) - 1
	lr := m(AL) - 1

	// Copy AL[:,lc] to WL[:,wc] and update with WR[0:]
	src.SubMatrix(AL, 0, lc, m(AL), 1)
	wk.SubMatrix(WL, 0, wc, m(AL), 1)
	blasd.Copy(&wk, &src)
	if k > 0 {
		wrow.SubMatrix(WR, lr, 0, 1, n(WR))
		blasd.MVMult(&wk, AR, &wrow, -1.0, 1.0, gomas.NONE)
	}
	if m(AL) == 1 {
		return -1, 1
	}
	// amax is on-diagonal element of current column
	amax := math.Abs(WL.Get(lr, wc))

	// find max off-diagonal on first column.
	rcol.SubMatrix(WL, 0, wc, lr, 1)
	// r is row index and rmax is its absolute value
	r = blasd.IAmax(&rcol)
	rmax := math.Abs(rcol.Get(r, 0))
	if amax >= bkALPHA*rmax {
		// no pivoting, 1x1 diagonal
		return -1, 1
	}

	// Now we need to copy row r to WL[:,wc-1] and update it
	wkp1.SubMatrix(WL, 0, wc-1, m(AL), 1)
	if r > 0 {
		// above the diagonal part of AL
		qrow.SubMatrix(AL, 0, r, r, 1)
		blasd.Copy(&wkp1, &qrow)
	}
	var wkr cmat.FloatMatrix
	qrow.SubMatrix(AL, r, r, 1, m(AL)-r)
	wkr.SubMatrix(&wkp1, r, 0, m(AL)-r, 1)
	blasd.Copy(&wkr, &qrow)
	if k > 0 {
		// update wkp1
		wrow.SubMatrix(WR, r, 0, 1, n(WR))
		blasd.MVMult(&wkp1, AR, &wrow, -1.0, 1.0, gomas.NONE)
	}
	// set on-diagonal entry to zero to avoid hitting it.
	p1 := wkp1.Get(r, 0)
	wkp1.Set(r, 0, 0.0)

	// max off-diagonal on r'th column/row at index q
	q = blasd.IAmax(&wkp1)
	qmax := math.Abs(wkp1.Get(q, 0))
	wkp1.Set(r, 0, p1)

	if amax >= bkALPHA*rmax*(rmax/qmax) {
		// no pivoting, 1x1 diagonal
		return -1, 1
	}
	// if q == r then qmax is not off-diagonal, qmax == WR[r,1] and
	// we get 1x1 pivot as following is always true
	if math.Abs(WL.Get(r, wc-1)) >= bkALPHA*qmax {
		// 1x1 pivoting and interchange with k, r
		// pivot row in column WL[:,-2] to WL[:,-1]
		src.SubMatrix(WL, 0, wc-1, m(AL), 1)
		wkp1.SubMatrix(WL, 0, wc, m(AL), 1)
		blasd.Copy(&wkp1, &src)
		wkp1.Set(-1, 0, src.Get(r, 0))
		wkp1.Set(r, 0, src.Get(-1, 0))
		return r, 1
	} else {
		// 2x2 pivoting and interchange with k+1, r
		return r, 2
	}
	return -1, 1
}