/* * 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) } }
/* * 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) } }
/* * 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) }
/* * 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) }
/* * Compute unblocked bidiagonal reduction for A when M >= N * * Diagonal and first super/sub diagonal are overwritten with the * upper/lower bidiagonal matrix B. * * This computing (1-tauq*v*v.T)*A*(1-taup*u.u.T) from left to right. */ func unblkReduceBidiagLeft(A, tauq, taup, W *cmat.FloatMatrix) { var ATL, ABR cmat.FloatMatrix var A00, a11, a12t, a21, A22 cmat.FloatMatrix var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix var tpT, tpB, tp0, taup1, tp2 cmat.FloatMatrix var y21, z21 cmat.FloatMatrix var v0 float64 util.Partition2x2( &ATL, nil, nil, &ABR, A, 0, 0, util.PTOPLEFT) util.Partition2x1( &tqT, &tqB, tauq, 0, util.PTOP) util.Partition2x1( &tpT, &tpB, taup, 0, util.PTOP) for m(&ABR) > 0 && n(&ABR) > 0 { util.Repartition2x2to3x3(&ATL, &A00, nil, nil, nil, &a11, &a12t, nil, &a21, &A22, A, 1, util.PBOTTOMRIGHT) util.Repartition2x1to3x1(&tqT, &tq0, &tauq1, &tq2, tauq, 1, util.PBOTTOM) util.Repartition2x1to3x1(&tpT, &tp0, &taup1, &tp2, taup, 1, util.PBOTTOM) // set temp vectors for this round y21.SetBuf(n(&a12t), 1, n(&a12t), W.Data()) z21.SetBuf(m(&a21), 1, m(&a21), W.Data()[y21.Len():]) // ------------------------------------------------------ // Compute householder to zero subdiagonal entries computeHouseholder(&a11, &a21, &tauq1) // y21 := a12 + A22.T*a21 blasd.Axpby(&y21, &a12t, 1.0, 0.0) blasd.MVMult(&y21, &A22, &a21, 1.0, 1.0, gomas.TRANSA) // a12t := a12t - tauq*y21 tauqv := tauq1.Get(0, 0) blasd.Axpy(&a12t, &y21, -tauqv) // Compute householder to zero elements above 1st superdiagonal computeHouseholderVec(&a12t, &taup1) v0 = a12t.Get(0, 0) a12t.Set(0, 0, 1.0) taupv := taup1.Get(0, 0) // [v == a12t, u == a21] beta := blasd.Dot(&y21, &a12t) // z21 := tauq*beta*u blasd.Axpby(&z21, &a21, tauqv*beta, 0.0) // z21 := A22*v - z21 blasd.MVMult(&z21, &A22, &a12t, 1.0, -1.0, gomas.NONE) // A22 := A22 - tauq*u*y21 blasd.MVUpdate(&A22, &a21, &y21, -tauqv) // A22 := A22 - taup*z21*v blasd.MVUpdate(&A22, &z21, &a12t, -taupv) a12t.Set(0, 0, v0) // ------------------------------------------------------ util.Continue3x3to2x2( &ATL, nil, nil, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT) util.Continue3x1to2x1( &tqT, &tqB, &tq0, &tauq1, tauq, util.PBOTTOM) util.Continue3x1to2x1( &tpT, &tpB, &tp0, &taup1, taup, util.PBOTTOM) } }
/* * This is adaptation of BIRED_LAZY_UNB algorithm from (1). * * Z matrix accumulates updates of row transformations i.e. first * Householder that zeros off diagonal entries on row. Vector z21 * is updates for current round, Z20 are already accumulated updates. * Vector z21 updates a12 before next transformation. * * Y matrix accumulates updates on column tranformations ie Householder * that zeros elements below sub-diagonal. Vector y21 is updates for current * round, Y20 are already accumulated updates. Vector y21 updates * a21 befor next transformation. * * Z, Y matrices upper trigonal part is not needed, temporary vector * w00 that has maximum length of n(Y) is placed on the last column of * Z matrix on each iteration. */ func unblkBuildBidiagRight(A, tauq, taup, Y, Z *cmat.FloatMatrix) { var ATL, ABL, ABR cmat.FloatMatrix var A00, a01, A02, a10, a11, a12t, A20, a21, A22 cmat.FloatMatrix var YTL, YBR, ZTL, ZBR cmat.FloatMatrix var Y00, y10, Y20, y11, y21, Y22 cmat.FloatMatrix var Z00, z10, Z20, z11, z21, Z22 cmat.FloatMatrix var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix var tpT, tpB, tp0, taup1, tp2 cmat.FloatMatrix var w00 cmat.FloatMatrix var v0 float64 // Y is workspace for building updates for first Householder. // And Z is space for build updates for second Householder // Y is n(A)-2,nb and Z is m(A)-1,nb util.Partition2x2( &ATL, nil, &ABL, &ABR, A, 0, 0, util.PTOPLEFT) util.Partition2x2( &YTL, nil, nil, &YBR, Y, 0, 0, util.PTOPLEFT) util.Partition2x2( &ZTL, nil, nil, &ZBR, Z, 0, 0, util.PTOPLEFT) util.Partition2x1( &tqT, &tqB, tauq, 0, util.PTOP) util.Partition2x1( &tpT, &tpB, taup, 0, util.PTOP) k := 0 for k < n(Y) { util.Repartition2x2to3x3(&ATL, &A00, &a01, &A02, &a10, &a11, &a12t, &A20, &a21, &A22, A, 1, util.PBOTTOMRIGHT) util.Repartition2x2to3x3(&YTL, &Y00, nil, nil, &y10, &y11, nil, &Y20, &y21, &Y22, Y, 1, util.PBOTTOMRIGHT) util.Repartition2x2to3x3(&ZTL, &Z00, nil, nil, &z10, &z11, nil, &Z20, &z21, &Z22, Z, 1, util.PBOTTOMRIGHT) util.Repartition2x1to3x1(&tqT, &tq0, &tauq1, &tq2, tauq, 1, util.PBOTTOM) util.Repartition2x1to3x1(&tpT, &tp0, &taup1, &tp2, taup, 1, util.PBOTTOM) // set temp vectors for this round, w00.SubMatrix(Z, 0, n(Z)-1, m(&A02), 1) // ------------------------------------------------------ // u10 == a10, U20 == A20, u21 == a21, // v10 == a01, V20 == A02, v21 == a12t if n(&Y20) > 0 { // a11 := a11 - u10t*z10 - y10*v10 aa := blasd.Dot(&a10, &z10) aa += blasd.Dot(&y10, &a01) a11.Set(0, 0, a11.Get(0, 0)-aa) // a12t := a12t - V20*z10 - Z20*u10 blasd.MVMult(&a12t, &A02, &y10, -1.0, 1.0, gomas.TRANS) blasd.MVMult(&a12t, &Z20, &a10, -1.0, 1.0, gomas.NONE) // a21 := a21 - Y20*v10 - U20*z10 blasd.MVMult(&a21, &Y20, &a01, -1.0, 1.0, gomas.NONE) blasd.MVMult(&a21, &A20, &z10, -1.0, 1.0, gomas.NONE) // here restore bidiagonal entry a10.Set(0, -1, v0) } // Compute householder to zero superdiagonal entries computeHouseholder(&a11, &a12t, &taup1) taupv := taup1.Get(0, 0) // y21 := a21 + A22*v21 - Y20*U20.T*v21 - V20*Z20.T*v21 blasd.Axpby(&y21, &a21, 1.0, 0.0) blasd.MVMult(&y21, &A22, &a12t, 1.0, 1.0, gomas.NONE) // w00 := U20.T*v21 [= A02*a12t] blasd.MVMult(&w00, &A02, &a12t, 1.0, 0.0, gomas.NONE) // y21 := y21 - U20*w00 [U20 == A20] blasd.MVMult(&y21, &Y20, &w00, -1.0, 1.0, gomas.NONE) // w00 := Z20.T*v21 blasd.MVMult(&w00, &Z20, &a12t, 1.0, 0.0, gomas.TRANS) // y21 := y21 - V20*w00 [V20 == A02.T] blasd.MVMult(&y21, &A20, &w00, -1.0, 1.0, gomas.NONE) // a21 := a21 - taup*y21 blasd.Scale(&y21, taupv) blasd.Axpy(&a21, &y21, -1.0) // Compute householder to zero elements below 1st subdiagonal computeHouseholderVec(&a21, &tauq1) v0 = a21.Get(0, 0) a21.Set(0, 0, 1.0) tauqv := tauq1.Get(0, 0) // z21 := tauq*(A22*y - V20*Y20.T*u - Z20*U20.T*u - beta*v) // [v == a12t, u == a21] beta := blasd.Dot(&y21, &a21) // z21 := beta*v blasd.Axpby(&z21, &a12t, beta, 0.0) // w00 = Y20.T*u blasd.MVMult(&w00, &Y20, &a21, 1.0, 0.0, gomas.TRANS) // z21 = z21 + V20*w00 == A02.T*w00 blasd.MVMult(&z21, &A02, &w00, 1.0, 1.0, gomas.TRANS) // w00 := U20.T*u (U20.T == A20.T) blasd.MVMult(&w00, &A20, &a21, 1.0, 0.0, gomas.TRANS) // z21 := z21 + Z20*w00 blasd.MVMult(&z21, &Z20, &w00, 1.0, 1.0, gomas.NONE) // z21 := -tauq*z21 + tauq*A22*v blasd.MVMult(&z21, &A22, &a21, tauqv, -tauqv, gomas.TRANS) // ------------------------------------------------------ k += 1 util.Continue3x3to2x2( &ATL, nil, &ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT) util.Continue3x3to2x2( &YTL, nil, nil, &YBR, &Y00, &y11, &Y22, Y, util.PBOTTOMRIGHT) util.Continue3x3to2x2( &ZTL, nil, nil, &ZBR, &Z00, &z11, &Z22, Z, util.PBOTTOMRIGHT) util.Continue3x1to2x1( &tqT, &tqB, &tq0, &tauq1, tauq, util.PBOTTOM) util.Continue3x1to2x1( &tpT, &tpB, &tp0, &taup1, taup, util.PBOTTOM) } // restore ABL.Set(0, -1, v0) }
// unblocked LU decomposition with pivots: FLAME LU variant 3; Left-looking func unblockedLUpiv(A *cmat.FloatMatrix, p *Pivots, offset int, conf *gomas.Config) *gomas.Error { var err *gomas.Error = nil var ATL, ATR, ABL, ABR cmat.FloatMatrix var A00, a01, A02, a10, a11, a12, A20, a21, A22 cmat.FloatMatrix var AL, AR, A0, a1, A2, aB1, AB0 cmat.FloatMatrix var pT, pB, p0, p1, p2 Pivots err = nil util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, 0, 0, util.PTOPLEFT) util.Partition1x2( &AL, &AR, A, 0, util.PLEFT) partitionPivot2x1( &pT, &pB, *p, 0, util.PTOP) for m(&ATL) < m(A) && n(&ATL) < n(A) { util.Repartition2x2to3x3(&ATL, &A00, &a01, &A02, &a10, &a11, &a12, &A20, &a21, &A22 /**/, A, 1, util.PBOTTOMRIGHT) util.Repartition1x2to1x3(&AL, &A0, &a1, &A2 /**/, A, 1, util.PRIGHT) repartPivot2x1to3x1(&pT, &p0, &p1, &p2 /**/, *p, 1, util.PBOTTOM) // apply previously computed pivots on current column applyPivots(&a1, p0) // a01 = trilu(A00) \ a01 (TRSV) blasd.MVSolveTrm(&a01, &A00, 1.0, gomas.LOWER|gomas.UNIT) // a11 = a11 - a10 *a01 aval := a11.Get(0, 0) - blasd.Dot(&a10, &a01) a11.Set(0, 0, aval) // a21 = a21 -A20*a01 blasd.MVMult(&a21, &A20, &a01, -1.0, 1.0, gomas.NONE) // pivot index on current column [a11, a21].T aB1.Column(&ABR, 0) p1[0] = pivotIndex(&aB1) // pivots to current column applyPivots(&aB1, p1) // a21 = a21 / a11 if aval == 0.0 { if err == nil { ij := m(&ATL) + p1[0] - 1 err = gomas.NewError(gomas.ESINGULAR, "DecomposeLU", ij) } } else { blasd.InvScale(&a21, a11.Get(0, 0)) } // apply pivots to previous columns AB0.SubMatrix(&ABL, 0, 0) applyPivots(&AB0, p1) // scale last pivots to origin matrix row numbers p1[0] += m(&ATL) util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT) util.Continue1x3to1x2( &AL, &AR, &A0, &a1, A, util.PRIGHT) contPivot3x1to2x1( &pT, &pB, p0, p1, *p, util.PBOTTOM) } if n(&ATL) < n(A) { applyPivots(&ATR, *p) blasd.SolveTrm(&ATR, &ATL, 1.0, gomas.LEFT|gomas.UNIT|gomas.LOWER, conf) } return err }