/* * 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 }
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) }
// 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 }
/* * 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) } }
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) } }
/* * 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) } }
/* * 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) } }
/* * 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) } }
/* * 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) } }
/* * Unblocked QR decomposition with block reflector T. */ func unblockedQRT(A, T, W *cmat.FloatMatrix) *gomas.Error { var err *gomas.Error = nil var ATL, ATR, ABL, ABR cmat.FloatMatrix var A00, a10, a11, a12, A20, a21, A22 cmat.FloatMatrix var TTL, TTR, TBL, TBR cmat.FloatMatrix var T00, t01, T02, t11, t12, T22, w12 cmat.FloatMatrix util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, 0, 0, util.PTOPLEFT) util.Partition2x2( &TTL, &TTR, &TBL, &TBR, T, 0, 0, util.PTOPLEFT) for m(&ABR) > 0 && n(&ABR) > 0 { util.Repartition2x2to3x3(&ATL, &A00, nil, nil, &a10, &a11, &a12, &A20, &a21, &A22, A, 1, util.PBOTTOMRIGHT) util.Repartition2x2to3x3(&TTL, &T00, &t01, &T02, nil, &t11, &t12, nil, nil, &T22, T, 1, util.PBOTTOMRIGHT) // ------------------------------------------------------ computeHouseholder(&a11, &a21, &t11) // H*[a12 A22].T w12.SubMatrix(W, 0, 0, a12.Len(), 1) applyHouseholder2x1(&t11, &a21, &a12, &A22, &w12, gomas.LEFT) // update T tauval := t11.Get(0, 0) if tauval != 0.0 { // t01 := -tauval*(a10.T + &A20.T*a21) //a10.CopyTo(&t01) blasd.Axpby(&t01, &a10, 1.0, 0.0) blasd.MVMult(&t01, &A20, &a21, -tauval, -tauval, gomas.TRANSA) // 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) } return err }
func Amax(X *cmat.FloatMatrix, confs ...*gomas.Config) float64 { switch X.Len() { case 0: return 0.0 case 1: return X.Get(0, 0) } ix := IAmax(X, confs...) if ix == -1 { return 0.0 } return X.Get(ix, 0) }
func TestPartition1H(t *testing.T) { var AL, AR, A0, a1, A2 cmat.FloatMatrix A := cmat.NewMatrix(1, 6) Partition1x2(&AL, &AR, A, 0, PLEFT) t.Logf("n(AL)=%d, n(AR)=%d\n", n(&AL), n(&AR)) for n(&AL) < n(A) { addConst(&AR, 1.0) t.Logf("n(AR)=%d; %v\n", n(&AR), &AR) Repartition1x2to1x3(&AL, &A0, &a1, &A2, A, 1, PRIGHT) t.Logf("n(A0)=%d, n(A2)=%d, a1=%.1f\n", n(&A0), n(&A2), a1.Get(0, 0)) Continue1x3to1x2(&AL, &AR, &A0, &a1, A, PRIGHT) } t.Logf("A:%v\n", A) }
/* * 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) } }
/* * 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) } }
func findBKPivotUpper(A *cmat.FloatMatrix) (int, int) { var r, q int var rcol, qrow cmat.FloatMatrix if m(A) == 1 { return 0, 1 } lastcol := m(A) - 1 amax := math.Abs(A.Get(lastcol, lastcol)) // column above [A.Rows()-1, A.Rows()-1] rcol.SubMatrix(A, 0, lastcol, lastcol, 1) r = blasd.IAmax(&rcol) // max off-diagonal on first column at index r rmax := math.Abs(A.Get(r, lastcol)) if amax >= bkALPHA*rmax { // no pivoting, 1x1 diagonal return -1, 1 } // max off-diagonal on r'th row at index q // a) rest of the r'th row above diagonal qmax := 0.0 if r > 0 { qrow.SubMatrix(A, 0, r, r, 1) q = blasd.IAmax(&qrow) qmax = math.Abs(A.Get(q, r /*+1*/)) } // b) elements right of diagonal qrow.SubMatrix(A, r, r+1, 1, lastcol-r) q = blasd.IAmax(&qrow) qmax2 := math.Abs(qrow.Get(0, q)) if qmax2 > qmax { qmax = qmax2 } if amax >= bkALPHA*rmax*(rmax/qmax) { // no pivoting, 1x1 diagonal return -1, 1 } if math.Abs(A.Get(r, r)) >= bkALPHA*qmax { // 1x1 pivoting and interchange with k, r return r, 1 } else { // 2x2 pivoting and interchange with k+1, r return r, 2 } return 0, 1 }
/* * 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 }
/* * 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 }
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) }
/* * α = (1 + sqrt(17))/8 * λ = |a(r,1)| = max{|a(2,1)|, . . . , |a(m,1)|} * if λ > 0 * if |a(1,1)| ≥ αλ * use a11 as 1-by-1 pivot * else * σ = |a(p,r)| = max{|a(1,r)|,..., |a(r−1,r)|, |a(r+1,r)|,..., |a(m,r)|} * if |a(1,1) |σ ≥ αλ^2 * use a(1,1) as 1-by-1 pivot * else if |a(r,r)| ≥ ασ * use a(r,r) as 1-by-1 pivot * else * a11 | ar1 * use -------- as 2-by-2 pivot * ar1 | arr * end * end * end * * ----------------------- * | 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 findBKPivotLower(A *cmat.FloatMatrix) (int, int) { var r, q int var rcol, qrow cmat.FloatMatrix if m(A) == 1 { return 0, 1 } amax := math.Abs(A.Get(0, 0)) // column below diagonal at [0, 0] rcol.SubMatrix(A, 1, 0, m(A)-1, 1) r = blasd.IAmax(&rcol) + 1 // max off-diagonal on first column at index r rmax := math.Abs(A.Get(r, 0)) if amax >= bkALPHA*rmax { // no pivoting, 1x1 diagonal return 0, 1 } // max off-diagonal on r'th row at index q qrow.SubMatrix(A, r, 0, 1, r /*+1*/) q = blasd.IAmax(&qrow) qmax := math.Abs(A.Get(r, q /*+1*/)) if r < m(A)-1 { // rest of the r'th row after diagonal qrow.SubMatrix(A, r+1, r, m(A)-r-1, 1) q = blasd.IAmax(&qrow) qmax2 := math.Abs(qrow.Get(q, 0)) if qmax2 > qmax { qmax = qmax2 } } if amax >= bkALPHA*rmax*(rmax/qmax) { // no pivoting, 1x1 diagonal return 0, 1 } if math.Abs(A.Get(r, r)) >= bkALPHA*qmax { // 1x1 pivoting and interchange with k, r return r, 1 } else { // 2x2 pivoting and interchange with k+1, r return r, 2 } return 0, 1 }
/* * 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) } }
/* * 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) } }
/* * 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 } }
func MVMultTrm(X, A *cmat.FloatMatrix, alpha float64, bits int, confs ...*gomas.Config) *gomas.Error { ar, ac := A.Size() xr, xc := X.Size() if ar*ac == 0 { return nil } if xr != 1 && xc != 1 { return gomas.NewError(gomas.ENEED_VECTOR, "MVMultTrm") } nx := X.Len() if ac != nx || ar != ac { return gomas.NewError(gomas.ESIZE, "MVMultTrm") } if ar == 1 { vscal(X, alpha*A.Get(0, 0), nx) } else { trmv(X, A, alpha, bits, nx) } return nil }
/* * 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 } }
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) } }
/* * 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 }
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 }
/* 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) }
/* 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) }
/* * 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) } }