示例#1
0
文件: ldlbku.go 项目: hrautila/gomas
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
}
示例#2
0
文件: ldlbkl.go 项目: hrautila/gomas
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
}
示例#3
0
文件: ldlbku.go 项目: hrautila/gomas
/*
 * Unblocked Bunch-Kauffman LDL factorization.
 *
 * Corresponds lapack.DSYTF2
 */
func unblkDecompBKUpper(A, wrk *cmat.FloatMatrix, p Pivots, conf *gomas.Config) (*gomas.Error, int) {
	var err *gomas.Error = nil
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a01, A02, a11, a12, A22, a11inv cmat.FloatMatrix
	var cwrk cmat.FloatMatrix
	var pT, pB, p0, p1, p2 Pivots

	err = nil
	nc := 0

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PBOTTOMRIGHT)
	partitionPivot2x1(
		&pT,
		&pB, p, 0, util.PBOTTOM)

	// permanent working space for symmetric inverse of a11
	a11inv.SubMatrix(wrk, 0, n(wrk)-2, 2, 2)
	a11inv.Set(1, 0, -1.0)
	a11inv.Set(0, 1, -1.0)

	for n(&ATL) > 0 {

		nr := m(&ATL) - 1
		r, np := findBKPivotUpper(&ATL)
		if r != -1 {
			cwrk.SubMatrix(&ATL, 0, n(&ATL)-np, m(&ATL), np)
			// pivoting needed; do swaping here
			applyBKPivotSymUpper(&ATL, m(&ATL)-np, r)
			if np == 2 {
				/*          [r, r] | [r, nr]
				 * a11 ==   ----------------  2-by-2 pivot, swapping [nr-1,nr] and [r,nr]
				 *          [nr,r] | [nr,nr]  (nr is the current diagonal entry)
				 */
				t := ATL.Get(nr-1, nr)
				ATL.Set(nr-1, nr, ATL.Get(r, nr))
				ATL.Set(r, nr, t)
			}
		}

		// repartition according the pivot size
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			nil, &a11, &a12,
			nil, nil, &A22 /**/, A, np, util.PTOPLEFT)
		repartPivot2x1to3x1(&pT,
			&p0,
			&p1,
			&p2 /**/, p, np, util.PTOP)
		// ------------------------------------------------------------

		if np == 1 {
			// A00 = A00 - a01*a01.T/a11
			blasd.MVUpdateTrm(&A00, &a01, &a01, -1.0/a11.Get(0, 0), gomas.UPPER)
			// a01 = a01/a11
			blasd.InvScale(&a01, a11.Get(0, 0))
			// store pivot point relative to original matrix
			if r == -1 {
				p1[0] = m(&ATL)
			} else {
				p1[0] = r + 1
			}
		} else if np == 2 {
			/* see comments on unblkDecompBKLower() */
			a := a11.Get(0, 0)
			b := a11.Get(0, 1)
			d := a11.Get(1, 1)
			a11inv.Set(0, 0, d/b)
			a11inv.Set(1, 1, a/b)
			// denominator: (a/b)*(d/b)-1.0 == (a*d - b^2)/b^2
			scale := 1.0 / ((a/b)*(d/b) - 1.0)
			scale /= b

			// cwrk = a21
			cwrk.SubMatrix(wrk, 2, 0, m(&a01), n(&a01))
			blasd.Copy(&cwrk, &a01)
			// a01 = a01*a11.-1
			blasd.Mult(&a01, &cwrk, &a11inv, scale, 0.0, gomas.NONE, conf)
			// A00 = A00 - a01*a11.-1*a01.T = A00 - a01*cwrk.T
			blasd.UpdateTrm(&A00, &a01, &cwrk, -1.0, 1.0, gomas.UPPER|gomas.TRANSB, conf)
			// store pivot point relative to original matrix
			p1[0] = -(r + 1)
			p1[1] = p1[0]
		}
		// ------------------------------------------------------------
		nc += np
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PTOPLEFT)
		contPivot3x1to2x1(
			&pT,
			&pB, p0, p1, p, util.PTOP)
	}
	return err, nc
}
示例#4
0
文件: ldlbkl.go 项目: hrautila/gomas
/*
 * Unblocked Bunch-Kauffman LDL factorization.
 *
 * Corresponds lapack.DSYTF2
 */
func unblkDecompBKLower(A, wrk *cmat.FloatMatrix, p Pivots, conf *gomas.Config) (*gomas.Error, int) {
	var err *gomas.Error = nil
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a10t, a11, A20, a21, A22, a11inv cmat.FloatMatrix
	var cwrk cmat.FloatMatrix
	var pT, pB, p0, p1, p2 Pivots

	err = nil
	nc := 0

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)
	partitionPivot2x1(
		&pT,
		&pB, p, 0, util.PTOP)

	// permanent working space for symmetric inverse of a11
	a11inv.SubMatrix(wrk, 0, n(wrk)-2, 2, 2)
	a11inv.Set(1, 0, -1.0)
	a11inv.Set(0, 1, -1.0)

	for n(&ABR) > 0 {

		r, np := findBKPivotLower(&ABR)
		if r != 0 && r != np-1 {
			// pivoting needed; do swaping here
			applyBKPivotSymLower(&ABR, np-1, r)
			if np == 2 {
				/*          [0,0] | [r,0]
				 * a11 ==   -------------  2-by-2 pivot, swapping [1,0] and [r,0]
				 *          [r,0] | [r,r]
				 */
				t := ABR.Get(1, 0)
				ABR.Set(1, 0, ABR.Get(r, 0))
				ABR.Set(r, 0, t)
			}
		}

		// repartition according the pivot size
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10t, &a11, nil,
			&A20, &a21, &A22 /**/, A, np, util.PBOTTOMRIGHT)
		repartPivot2x1to3x1(&pT,
			&p0,
			&p1,
			&p2 /**/, p, np, util.PBOTTOM)
		// ------------------------------------------------------------
		if np == 1 {
			// A22 = A22 - a21*a21.T/a11
			blasd.MVUpdateTrm(&A22, &a21, &a21, -1.0/a11.Get(0, 0), gomas.LOWER)
			// a21 = a21/a11
			blasd.InvScale(&a21, a11.Get(0, 0))
			// store pivot point relative to original matrix
			p1[0] = r + m(&ATL) + 1
		} else if np == 2 {
			/* from Bunch-Kaufmann 1977:
			 *  (E2 C.T) = ( I2      0      )( E  0      )( I[n-2] E.-1*C.T )
			 *  (C  B  )   ( C*E.-1  I[n-2] )( 0  A[n-2] )( 0      I2       )
			 *
			 *  A[n-2] = B - C*E.-1*C.T
			 *
			 *  E.-1 is inverse of a symmetric matrix, cannot use
			 *  triangular solve. We calculate inverse of 2x2 matrix.
			 *  Following is inspired by lapack.SYTF2
			 *
			 *      a | b      1        d | -b         b         d/b | -1
			 *  inv ----- =  ------  * ------  =  ----------- * --------
			 *      b | d    (ad-b^2)  -b |  a    (a*d - b^2)     -1 | a/b
			 *
			 */
			a := a11.Get(0, 0)
			b := a11.Get(1, 0)
			d := a11.Get(1, 1)
			a11inv.Set(0, 0, d/b)
			a11inv.Set(1, 1, a/b)
			// denominator: (a/b)*(d/b)-1.0 == (a*d - b^2)/b^2
			scale := 1.0 / ((a/b)*(d/b) - 1.0)
			scale /= b
			// cwrk = a21
			cwrk.SubMatrix(wrk, 2, 0, m(&a21), n(&a21))
			blasd.Copy(&cwrk, &a21)
			// a21 = a21*a11.-1
			blasd.Mult(&a21, &cwrk, &a11inv, scale, 0.0, gomas.NONE, conf)
			// A22 = A22 - a21*a11.-1*a21.T = A22 - a21*cwrk.T
			blasd.UpdateTrm(&A22, &a21, &cwrk, -1.0, 1.0, gomas.LOWER|gomas.TRANSB, conf)
			// store pivot point relative to original matrix
			p1[0] = -(r + m(&ATL) + 1)
			p1[1] = p1[0]
		}
		// ------------------------------------------------------------
		nc += np
		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
		contPivot3x1to2x1(
			&pT,
			&pB, p0, p1, p, util.PBOTTOM)
	}
	return err, nc
}