Пример #1
0
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)
			}
		}
	}
}
Пример #2
0
/*
 * 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
	}
}
Пример #3
0
/*
 * 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
}
Пример #4
0
/*
 * 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
}
Пример #5
0
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)
}
Пример #6
0
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)
}
Пример #7
0
/*
 * 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
	}
}
Пример #8
0
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
}
Пример #9
0
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
}