/* * Blocked QR decomposition with compact WY transform. * * Compatible with lapack.DGEQRF. */ func blockedQL(A, Tvec, Twork, W *cmat.FloatMatrix, lb int, conf *gomas.Config) { var ATL, ATR, ABL, ABR, AL cmat.FloatMatrix var A00, A01, A10, A11, A22 cmat.FloatMatrix var TT, TB cmat.FloatMatrix var t0, tau, t2 cmat.FloatMatrix var Wrk, w1 cmat.FloatMatrix util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, 0, 0, util.PBOTTOMRIGHT) util.Partition2x1( &TT, &TB, Tvec, 0, util.PBOTTOM) nb := lb for m(&ATL)-nb > 0 && n(&ATL)-nb > 0 { util.Repartition2x2to3x3(&ATL, &A00, &A01, nil, &A10, &A11, nil, nil, nil, &A22, A, nb, util.PTOPLEFT) util.Repartition2x1to3x1(&TT, &t0, &tau, &t2, Tvec, nb, util.PTOP) // current block size cb, rb := A11.Size() if rb < cb { cb = rb } // -------------------------------------------------------- // decompose righ side AL == /A01\ // \A11/ w1.SubMatrix(W, 0, 0, cb, 1) util.Merge2x1(&AL, &A01, &A11) unblockedQL(&AL, &tau, &w1) // build block reflector unblkQLBlockReflector(Twork, &AL, &tau) // update A'tail i.e. A10 and A00 with (I - Y*T*Y.T).T * A'tail // compute: C - Y*(C.T*Y*T).T ar, ac := A10.Size() Wrk.SubMatrix(W, 0, 0, ac, ar) updateQLLeft(&A10, &A00, &A11, &A01, Twork, &Wrk, true, conf) // -------------------------------------------------------- util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &A11, &A22, A, util.PTOPLEFT) util.Continue3x1to2x1( &TT, &TB, &t0, &tau, Tvec, util.PTOP) } // last block with unblocked if m(&ATL) > 0 && n(&ATL) > 0 { w1.SubMatrix(W, 0, 0, n(&ATL), 1) unblockedQL(&ATL, &t0, &w1) } }
/* * 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 }
/* * Blocked version for computing C = C*Q and C = C*Q.T from elementary reflectors * and scalar coefficients. * * Elementary reflectors and scalar coefficients are used to build block reflector T. * Matrix C is updated by applying block reflector T using compact WY algorithm. */ func blockedMultQRight(C, A, tau, W *cmat.FloatMatrix, flags, nb int, conf *gomas.Config) { var ATL, ATR, ABL, ABR, AL cmat.FloatMatrix var A00, A10, A11, A20, A21, A22 cmat.FloatMatrix var CL, CR, C0, C1, C2 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau1, t2 cmat.FloatMatrix var W0, Wrk, Tw, Twork cmat.FloatMatrix var Aref *cmat.FloatMatrix var pAdir, pAstart, pDir, pStart, pCstart, pCdir util.Direction var bsz, cb, mb int // partitioning start and direction if flags&gomas.TRANS != 0 { // from bottom-right to top-left to produce transpose sequence (C*Q.T) pAstart = util.PBOTTOMRIGHT pAdir = util.PTOPLEFT pStart = util.PBOTTOM pDir = util.PTOP pCstart = util.PRIGHT pCdir = util.PLEFT mb = imax(0, m(A)-n(A)) cb = n(C) - n(A) Aref = &ATL } else { // from top-left to bottom-right to produce normal sequence (C*Q) pAstart = util.PTOPLEFT pAdir = util.PBOTTOMRIGHT pStart = util.PTOP pDir = util.PBOTTOM pCstart = util.PLEFT pCdir = util.PRIGHT mb = 0 cb = 0 Aref = &ABR } // intermediate reflector at start of workspace Twork.SetBuf(nb, nb, nb, W.Data()) W0.SetBuf(m(C), nb, m(C), W.Data()[Twork.Len():]) util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, mb, 0, pAstart) util.Partition1x2( &CL, &CR, C, cb, pCstart) util.Partition2x1( &tT, &tB, tau, 0, pStart) transpose := flags&gomas.TRANS != 0 for m(Aref) > 0 && n(Aref) > 0 { util.Repartition2x2to3x3(&ATL, &A00, nil, nil, &A10, &A11, nil, &A20, &A21, &A22, A, nb, pAdir) util.Repartition2x1to3x1(&tT, &t0, &tau1, &t2, tau, nb, pDir) bsz = n(&A11) // C1 block size must match A11 util.Repartition1x2to1x3(&CL, &C0, &C1, &C2, C, bsz, pCdir) // -------------------------------------------------------- // clear & build block reflector from current block util.Merge2x1(&AL, &A11, &A21) Tw.SubMatrix(&Twork, 0, 0, bsz, bsz) blasd.Scale(&Tw, 0.0) unblkQRBlockReflector(&Tw, &AL, &tau1) // compute: C*Q.T == C - C*(Y*T*Y.T).T = C - C*Y*T.T*Y.T // C*Q == C - C*Y*T*Y.T Wrk.SubMatrix(&W0, 0, 0, m(&C1), bsz) updateWithQTRight(&C1, &C2, &A11, &A21, &Tw, &Wrk, transpose, conf) // -------------------------------------------------------- util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &A11, &A22, A, pAdir) util.Continue1x3to1x2( &CL, &CR, &C0, &C1, C, pCdir) util.Continue3x1to2x1( &tT, &tB, &t0, &tau1, tau, pDir) } }
/* * Blocked version for computing C = Q*C and C = Q.T*C from elementary reflectors * and scalar coefficients. * * Elementary reflectors and scalar coefficients are used to build block reflector T. * Matrix C is updated by applying block reflector T using compact WY algorithm. */ func blockedMultQLeft(C, A, tau, W *cmat.FloatMatrix, flags, nb int, conf *gomas.Config) { var ATL, ATR, ABL, ABR, AL cmat.FloatMatrix var A00, A10, A11, A20, A21, A22 cmat.FloatMatrix var CT, CB, C0, C1, C2 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau1, t2 cmat.FloatMatrix var Wrk, W0, Tw, Twork cmat.FloatMatrix var Aref *cmat.FloatMatrix var pAdir, pAstart, pDir, pStart util.Direction var bsz, mb int // partitioning start and direction if flags&gomas.TRANS != 0 || nb == n(A) { // from top-left to bottom-right to produce transposed sequence (Q.T*C) pAstart = util.PTOPLEFT pAdir = util.PBOTTOMRIGHT pStart = util.PTOP pDir = util.PBOTTOM mb = 0 Aref = &ABR } else { // from bottom-right to top-left to produce normal sequence (Q*C) pAstart = util.PBOTTOMRIGHT pAdir = util.PTOPLEFT pStart = util.PBOTTOM pDir = util.PTOP mb = imax(0, m(A)-n(A)) Aref = &ATL } util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, mb, 0, pAstart) util.Partition2x1( &CT, &CB, C, mb, pStart) util.Partition2x1( &tT, &tB, tau, 0, pStart) transpose := flags&gomas.TRANS != 0 // intermediate reflector at start of workspace Twork.SetBuf(nb, nb, nb, W.Data()) W0.SetBuf(n(C), nb, n(C), W.Data()[Twork.Len():]) for m(Aref) > 0 && n(Aref) > 0 { util.Repartition2x2to3x3(&ATL, &A00, nil, nil, &A10, &A11, nil, &A20, &A21, &A22, A, nb, pAdir) util.Repartition2x1to3x1(&tT, &t0, &tau1, &t2, tau, nb, pDir) bsz = n(&A11) util.Repartition2x1to3x1(&CT, &C0, &C1, &C2, C, bsz, pDir) // -------------------------------------------------------- // clear & build block reflector from current block util.Merge2x1(&AL, &A11, &A21) Tw.SubMatrix(&Twork, 0, 0, bsz, bsz) blasd.Scale(&Tw, 0.0) unblkQRBlockReflector(&Tw, &AL, &tau1) // compute: Q*T.C == C - Y*(C.T*Y*T).T transpose == true // Q*C == C - C*Y*T*Y.T transpose == false Wrk.SubMatrix(&W0, 0, 0, n(&C1), bsz) updateWithQTLeft(&C1, &C2, &A11, &A21, &Tw, &Wrk, transpose, conf) // -------------------------------------------------------- util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &A11, &A22, A, pAdir) util.Continue3x1to2x1( &CT, &CB, &C0, &C1, C, pDir) util.Continue3x1to2x1( &tT, &tB, &t0, &tau1, tau, pDir) } }
func blkMultLeftQL(C, A, tau, W *cmat.FloatMatrix, flags, lb int, conf *gomas.Config) { var ATL /*ATR, ABL,*/, ABR, AL cmat.FloatMatrix var A00, A01, A11, A22 cmat.FloatMatrix var CT, CB, C0, C1, C2 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau1, t2 cmat.FloatMatrix var T0, T, W0, Wrk cmat.FloatMatrix var Aref *cmat.FloatMatrix var pAdir, pAstart, pDir, pStart util.Direction var mb, tb, nb int // partitioning start and direction if flags&gomas.TRANS != 0 { // A from bottom-right to top-left to produce transposed sequence (Q.T*C) pAstart = util.PBOTTOMRIGHT pAdir = util.PTOPLEFT pStart = util.PBOTTOM pDir = util.PTOP mb = 0 tb = 0 nb = 0 Aref = &ATL } else { // from top-left to bottom-right to produce normal sequence (Q*C) pAstart = util.PTOPLEFT pAdir = util.PBOTTOMRIGHT pStart = util.PTOP pDir = util.PBOTTOM mb = imax(0, m(A)-n(A)) nb = imax(0, n(A)-m(A)) tb = imax(0, tau.Len()-n(A)) Aref = &ABR } util.Partition2x2( &ATL, nil, nil, &ABR, A, mb, nb, pAstart) util.Partition2x1( &CT, &CB, C, mb, pStart) util.Partition2x1( &tT, &tB, tau, tb, pStart) transpose := flags&gomas.TRANS != 0 // divide workspace for block reflector and temporart space T0.SetBuf(lb, lb, lb, W.Data()) W0.SetBuf(n(C), lb, n(C), W.Data()[T0.Len():]) for n(Aref) > 0 { util.Repartition2x2to3x3(&ATL, &A00, &A01, nil, nil, &A11, nil, nil, nil, &A22, A, lb, pAdir) util.Repartition2x1to3x1(&tT, &t0, &tau1, &t2, tau, lb, pDir) bsz := n(&A11) util.Repartition2x1to3x1(&CT, &C0, &C1, &C2, C, bsz, pDir) // -------------------------------------------------------- // build block reflector for current block util.Merge2x1(&AL, &A01, &A11) T.SubMatrix(&T0, 0, 0, bsz, bsz) blasd.Scale(&T, 0.0) unblkQLBlockReflector(&T, &AL, &tau1) // update with (I - Y*T*Y.T) or (I - Y*T*Y.T).T Wrk.SubMatrix(&W0, 0, 0, n(&C1), bsz) updateQLLeft(&C1, &C0, &A11, &A01, &T, &Wrk, transpose, conf) // -------------------------------------------------------- util.Continue3x3to2x2( &ATL, nil, nil, &ABR, &A00, &A11, &A22, A, pAdir) util.Continue3x1to2x1( &CT, &CB, &C0, &C1, C, pDir) util.Continue3x1to2x1( &tT, &tB, &t0, &tau1, tau, pDir) } }
func blkMultRightQL(C, A, tau, W *cmat.FloatMatrix, flags, lb int, conf *gomas.Config) { var ATL, ABR, AL cmat.FloatMatrix var A00, A01, A11, A22 cmat.FloatMatrix var CL, CR, C0, C1, C2 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau1, t2 cmat.FloatMatrix var T0, T, W0, Wrk cmat.FloatMatrix var Aref *cmat.FloatMatrix var pAdir, pAstart, pDir, pStart, pCdir, pCstart util.Direction var mb, tb, nb, cb int // partitioning start and direction if flags&gomas.TRANS != 0 { // from top-left to bottom-right to produce transpose sequence (C*Q.T) pAstart = util.PTOPLEFT pAdir = util.PBOTTOMRIGHT pStart = util.PTOP pDir = util.PBOTTOM pCstart = util.PLEFT pCdir = util.PRIGHT mb = imax(0, m(A)-n(A)) nb = imax(0, n(A)-m(A)) cb = imax(0, n(C)-n(A)) tb = imax(0, tau.Len()-n(A)) Aref = &ABR } else { // A from bottom-right to top-left to produce normal sequence (C*Q) pAstart = util.PBOTTOMRIGHT pAdir = util.PTOPLEFT pStart = util.PBOTTOM pDir = util.PTOP pCstart = util.PRIGHT pCdir = util.PLEFT mb = 0 tb = 0 nb = 0 cb = 0 Aref = &ATL } util.Partition2x2( &ATL, nil, nil, &ABR /**/, A, mb, nb, pAstart) util.Partition1x2( &CL, &CR /**/, C, cb, pCstart) util.Partition2x1( &tT, &tB /**/, tau, tb, pStart) transpose := flags&gomas.TRANS != 0 // divide workspace for block reflector and temporary work matrix T0.SetBuf(lb, lb, lb, W.Data()) W0.SetBuf(m(C), lb, m(C), W.Data()[T0.Len():]) for n(Aref) > 0 { util.Repartition2x2to3x3(&ATL, &A00, &A01, nil, nil, &A11, nil, nil, nil, &A22 /**/, A, lb, pAdir) bsz := n(&A11) util.Repartition1x2to1x3(&CL, &C0, &C1, &C2 /**/, C, bsz, pCdir) util.Repartition2x1to3x1(&tT, &t0, &tau1, &t2 /**/, tau, bsz, pDir) // -------------------------------------------------------- util.Merge2x1(&AL, &A01, &A11) T.SubMatrix(&T0, 0, 0, bsz, bsz) blasd.Scale(&T, 0.0) unblkQLBlockReflector(&T, &AL, &tau1) Wrk.SubMatrix(&W0, 0, 0, m(C), bsz) updateQLRight(&C1, &C0, &A11, &A01, &T, &Wrk, transpose, conf) // -------------------------------------------------------- util.Continue3x3to2x2( &ATL, nil, nil, &ABR /**/, &A00, &A11, &A22, A, pAdir) util.Continue1x3to1x2( &CL, &CR /**/, &C0, &C1, C, pCdir) util.Continue3x1to2x1( &tT, &tB /**/, &t0, &tau1, tau, pDir) } }
/* * 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 }
/* * Blocked 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. * * If the number K of elementary reflectors is not multiple of the blocking * factor lb, then unblocked code is used first to generate the lower right corner * of the matrix Q. * * Compatible with lapack.DORGQR subroutine. */ func blkBuildQRQ(A, Tvec, Twork, W *cmat.FloatMatrix, K, lb int, conf *gomas.Config) { var ATL, ATR, ABL, ABR, AL cmat.FloatMatrix var A00, A01, A11, A12, A21, A22 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau, t2, Wrk, D, T cmat.FloatMatrix nk := n(A) - K mk := m(A) - K uk := K % lb util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, mk+uk, nk+uk, util.PBOTTOMRIGHT) util.Partition2x1( &tT, &tB, Tvec, nk+uk, util.PBOTTOM) // zero the right side if nk+uk > 0 { blasd.Scale(&ATR, 0.0) if uk > 0 { // number of reflectors is not multiple of blocking factor // do the first part with unblocked code. unblkBuildQRQ(&ABR, &tB, W, m(&ABR)-uk, n(&ABR)-uk, true) } else { // blocking factor is multiple of K blasd.Scale(&ABR, 0.0) D.Diag(&ABR) blasd.Add(&D, 1.0) } } for m(&ATL) > 0 && n(&ATL) > 0 { util.Repartition2x2to3x3(&ATL, &A00, &A01, nil, nil, &A11, &A12, nil, &A21, &A22, A, lb, util.PTOPLEFT) util.Repartition2x1to3x1(&tT, &t0, &tau, &t2, Tvec, lb, util.PTOP) // ------------------------------------------------------ util.Merge2x1(&AL, &A11, &A21) // build block reflector T.SubMatrix(Twork, 0, 0, n(&A11), n(&A11)) unblkQRBlockReflector(&T, &AL, &tau) // update right side i.e. A12 and A22 with (I - Y*T*Y.T) ar, ac := A12.Size() Wrk.SubMatrix(W, 0, 0, ac, ar) updateWithQTLeft(&A12, &A22, &A11, &A21, &T, &Wrk, false, conf) // update current block unblkBuildQRQ(&AL, &tau, W, m(&A21), 0, false) // zero top rows blasd.Scale(&A01, 0.0) // ------------------------------------------------------ util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &A11, &A22, A, util.PTOPLEFT) util.Continue3x1to2x1( &tT, &tB, &t0, &tau, Tvec, util.PTOP) } }