func sortEigenVec(D, U, V, C *cmat.FloatMatrix, updown int) { var sD, m0, m1 cmat.FloatMatrix N := D.Len() for k := 0; k < N-1; k++ { sD.SubVector(D, k, N-k) pk := vecMinMax(&sD, -updown) if pk != 0 { t0 := D.GetAt(k) D.SetAt(k, D.GetAt(pk+k)) D.SetAt(k+pk, t0) if U != nil { m0.Column(U, k) m1.Column(U, k+pk) blasd.Swap(&m1, &m0) } if V != nil { m0.Row(V, k) m1.Row(V, k+pk) blasd.Swap(&m1, &m0) } if C != nil { m0.Column(C, k) m1.Column(C, k+pk) blasd.Swap(&m1, &m0) } } } }
/* * 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 } }
/* * 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 swapCols(A *cmat.FloatMatrix, src, dst int) { var c0, c1 cmat.FloatMatrix ar, _ := A.Size() if src == dst || ar == 0 { return } c0.SubMatrix(A, 0, src, ar, 1) c1.SubMatrix(A, 0, dst, ar, 1) blasd.Swap(&c0, &c1) }
func swapRows(A *cmat.FloatMatrix, src, dst int) { var r0, r1 cmat.FloatMatrix ar, ac := A.Size() if src == dst || ar == 0 { return } r0.SubMatrix(A, src, 0, 1, ac) r1.SubMatrix(A, dst, 0, 1, ac) blasd.Swap(&r0, &r1) }
/* * 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 blkDecompBKUpper(A, W *cmat.FloatMatrix, p *Pivots, conf *gomas.Config) (err *gomas.Error) { var ATL, ATR, ABL, ABR cmat.FloatMatrix var A00, A01, A02, A11, A12, A22 cmat.FloatMatrix var wrk cmat.FloatMatrix var pT, pB, p0, p1, p2 Pivots var nblk int = 0 err = nil util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, 0, 0, util.PBOTTOMRIGHT) partitionPivot2x1( &pT, &pB, *p, 0, util.PBOTTOM) nb := conf.LB for n(&ATL) >= nb { err, nblk = unblkBoundedBKUpper(&ATL, W, &pT, nb, conf) // repartition nblk size util.Repartition2x2to3x3(&ATL, &A00, &A01, &A02, nil, &A11, &A12, nil, nil, &A22, A, nblk, util.PTOPLEFT) repartPivot2x1to3x1(&pT, &p0, &p1, &p2 /**/, *p, nblk, util.PTOP) // -------------------------------------------------------- // here [A01;A11] has been decomposed by unblkBoundedBKUpper() // Now we need update A00 // wrk is original A01 wrk.SubMatrix(W, 0, n(W)-nblk, m(&A01), nblk) // A00 = A00 - L01*D1*L01.T = A22 - A01*W.T blasd.UpdateTrm(&A00, &A01, &wrk, -1.0, 1.0, gomas.UPPER|gomas.TRANSB) // partially undo row pivots right of diagonal for k := 0; k < nblk; k++ { var s, d cmat.FloatMatrix r := p1[k] colno := n(&A00) + k np := 1 if r < 0 { r = -r np = 2 } rlen := n(&ATL) - colno - np if r == colno+1 && p1[k] > 0 { // no pivot continue } s.SubMatrix(&ATL, colno, colno+np, 1, rlen) d.SubMatrix(&ATL, r-1, colno+np, 1, rlen) blasd.Swap(&d, &s) if p1[k] < 0 { k++ // skip other entry in 2x2 pivots } } // --------------------------------------------------------- util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &A11, &A22, A, util.PTOPLEFT) contPivot3x1to2x1( &pT, &pB, p0, p1, *p, util.PTOP) } // do the last part with unblocked code if n(&ATL) > 0 { unblkDecompBKUpper(&ATL, W, pT, conf) } return }
func blkDecompBKLower(A, W *cmat.FloatMatrix, p *Pivots, conf *gomas.Config) (err *gomas.Error) { var ATL, ATR, ABL, ABR cmat.FloatMatrix var A00, A10, A11, A20, A21, A22 cmat.FloatMatrix var wrk cmat.FloatMatrix var pT, pB, p0, p1, p2 Pivots var nblk int = 0 err = nil util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, 0, 0, util.PTOPLEFT) partitionPivot2x1( &pT, &pB, *p, 0, util.PTOP) nb := conf.LB for n(&ABR) >= nb { err, nblk = unblkBoundedBKLower(&ABR, W, &pB, nb, conf) // repartition nblk size util.Repartition2x2to3x3(&ATL, &A00, nil, nil, &A10, &A11, nil, &A20, &A21, &A22, A, nblk, util.PBOTTOMRIGHT) repartPivot2x1to3x1(&pT, &p0, &p1, &p2 /**/, *p, nblk, util.PBOTTOM) // -------------------------------------------------------- // here [A11;A21] has been decomposed by unblkBoundedBKLower() // Now we need update A22 // wrk is original A21 wrk.SubMatrix(W, nblk, 0, m(&A21), nblk) // A22 = A22 - L21*D1*L21.T = A22 - L21*W.T blasd.UpdateTrm(&A22, &A21, &wrk, -1.0, 1.0, gomas.LOWER|gomas.TRANSB) // partially undo row pivots left of diagonal for k := nblk; k > 0; k-- { var s, d cmat.FloatMatrix r := p1[k-1] rlen := k - 1 if r < 0 { r = -r rlen-- } if r == k && p1[k-1] > 0 { // no pivot continue } s.SubMatrix(&ABR, k-1, 0, 1, rlen) d.SubMatrix(&ABR, r-1, 0, 1, rlen) blasd.Swap(&d, &s) if p1[k-1] < 0 { k-- // skip other entry in 2x2 pivots } } // shift pivot values for k, n := range p1 { if n > 0 { p1[k] += m(&ATL) } else { p1[k] -= m(&ATL) } } // zero work for debuging //blasd.Scale(W, 0.0) // --------------------------------------------------------- util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &A11, &A22, A, util.PBOTTOMRIGHT) contPivot3x1to2x1( &pT, &pB, p0, p1, *p, util.PBOTTOM) } // do the last part with unblocked code if n(&ABR) > 0 { unblkDecompBKLower(&ABR, W, pB, conf) // shift pivot values for k, n := range pB { if n > 0 { pB[k] += m(&ATL) } else { pB[k] -= m(&ATL) } } } return }