예제 #1
0
파일: diag.go 프로젝트: hrautila/gomas
/*
 * Compute
 *   B = B*diag(D).-1      flags & RIGHT == true
 *   B = diag(D).-1*B      flags & LEFT  == true
 *
 * If flags is LEFT (RIGHT) then element-wise divides columns (rows) of B with vector D.
 *
 * Arguments:
 *   B     M-by-N matrix if flags&RIGHT == true or N-by-M matrix if flags&LEFT == true
 *
 *   D     N element column or row vector or N-by-N matrix
 *
 *   flags Indicator bits, LEFT or RIGHT
 */
func SolveDiag(B, D *cmat.FloatMatrix, flags int, confs ...*gomas.Config) *gomas.Error {
	var c, d0 cmat.FloatMatrix
	var d *cmat.FloatMatrix

	conf := gomas.CurrentConf(confs...)
	d = D
	if !D.IsVector() {
		d0.Diag(D)
		d = &d0
	}
	dn := d0.Len()
	br, bc := B.Size()
	switch flags & (gomas.LEFT | gomas.RIGHT) {
	case gomas.LEFT:
		if br != dn {
			return gomas.NewError(gomas.ESIZE, "SolveDiag")
		}
		// scale rows;
		for k := 0; k < dn; k++ {
			c.Row(B, k)
			blasd.InvScale(&c, d.GetAt(k), conf)
		}
	case gomas.RIGHT:
		if bc != dn {
			return gomas.NewError(gomas.ESIZE, "SolveDiag")
		}
		// scale columns
		for k := 0; k < dn; k++ {
			c.Column(B, k)
			blasd.InvScale(&c, d.GetAt(k), conf)
		}
	}
	return nil
}
예제 #2
0
파일: lu.go 프로젝트: hrautila/gomas
// unblocked LU decomposition w/o pivots, FLAME LU nopivots variant 5
func unblockedLUnoPiv(A *cmat.FloatMatrix, conf *gomas.Config) *gomas.Error {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a01, A02, a10, a11, a12, A20, a21, A22 cmat.FloatMatrix
	var err *gomas.Error = nil

	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)

	for m(&ATL) < m(A) {
		util.Repartition2x2to3x3(&ATL,
			&A00, &a01, &A02,
			&a10, &a11, &a12,
			&A20, &a21, &A22, A, 1, util.PBOTTOMRIGHT)

		// a21 = a21/a11
		blasd.InvScale(&a21, a11.Get(0, 0))
		// A22 = A22 - a21*a12
		blasd.MVUpdate(&A22, &a21, &a12, -1.0)

		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)
	}
	return err
}
예제 #3
0
파일: trdsec.go 프로젝트: hrautila/gomas
// Compute eigenvector corresponding precomputed deltas
func trdsecEigenVecDelta(qi, delta, z *cmat.FloatMatrix) {
	var dk, zk float64

	for k := 0; k < delta.Len(); k++ {
		zk = z.GetAt(k)
		dk = delta.GetAt(k)
		qi.SetAt(k, zk/dk)
	}
	s := blasd.Nrm2(qi)
	blasd.InvScale(qi, s)
}
예제 #4
0
파일: scal_test.go 프로젝트: hrautila/gomas
func TestDVecScal(t *testing.T) {

	const N = 911

	X := cmat.NewMatrix(N, 1)
	Y := cmat.NewMatrix(N, 1)

	zeromean := cmat.NewFloatUniformSource(2.0, 0.5)

	X.SetFrom(zeromean)
	Y.Copy(X)

	// B = A*B
	blasd.Scale(X, 2.0)
	blasd.InvScale(X, 2.0)
	ok := X.AllClose(Y)
	t.Logf("X = InvScale(Scale(X, 2.0), 2.0) : %v\n", ok)

}
예제 #5
0
파일: trdsec.go 프로젝트: hrautila/gomas
func trdsecEigenBuildInplace(Q, z *cmat.FloatMatrix) {
	var QTL, QBR, Q00, q11, q12, q21, Q22, qi cmat.FloatMatrix
	var zk0, zk1, dk0, dk1 float64

	util.Partition2x2(
		&QTL, nil,
		nil, &QBR /**/, Q, 0, 0, util.PTOPLEFT)

	for m(&QBR) > 0 {
		util.Repartition2x2to3x3(&QTL,
			&Q00, nil, nil,
			nil, &q11, &q12,
			nil, &q21, &Q22 /**/, Q, 1, util.PBOTTOMRIGHT)
		//---------------------------------------------------------------
		k := m(&Q00)
		zk0 = z.GetAt(k)
		dk0 = q11.Get(0, 0)
		q11.Set(0, 0, zk0/dk0)

		for i := 0; i < q12.Len(); i++ {
			zk1 = z.GetAt(k + i + 1)
			dk0 = q12.GetAt(i)
			dk1 = q21.GetAt(i)
			q12.SetAt(i, zk0/dk1)
			q21.SetAt(i, zk1/dk0)
		}
		//---------------------------------------------------------------
		util.Continue3x3to2x2(
			&QTL, nil,
			nil, &QBR /**/, &Q00, &q11, &Q22 /**/, Q, util.PBOTTOMRIGHT)
	}
	// scale column eigenvectors
	for k := 0; k < z.Len(); k++ {
		qi.Column(Q, k)
		t := blasd.Nrm2(&qi)
		blasd.InvScale(&qi, t)
	}
}
예제 #6
0
파일: sec_test.go 프로젝트: hrautila/gomas
func test1(N int, beta float64, t *testing.T) {
	var sI cmat.FloatMatrix

	if N&0x1 != 0 {
		N = N + 1
	}
	D := cmat.NewMatrix(N, 1)
	Z := cmat.NewMatrix(N, 1)
	Y := cmat.NewMatrix(N, 1)
	V := cmat.NewMatrix(N, 1)
	Q := cmat.NewMatrix(N, N)
	I := cmat.NewMatrix(N, N)

	D.SetAt(0, 1.0)
	Z.SetAt(0, 2.0)
	for i := 1; i < N-1; i++ {
		if i < N/2 {
			D.SetAt(i, 2.0-float64(N/2-i)*beta)
		} else {
			D.SetAt(i, 2.0+float64(i+1-N/2)*beta)
		}
		Z.SetAt(i, beta)
	}
	D.SetAt(N-1, 10.0/3.0)
	Z.SetAt(N-1, 2.0)
	w := blasd.Nrm2(Z)
	blasd.InvScale(Z, w)
	rho := 1.0 / (w * w)

	lapackd.TRDSecularSolveAll(Y, V, Q, D, Z, rho)
	lapackd.TRDSecularEigen(Q, V, nil)
	blasd.Mult(I, Q, Q, 1.0, 0.0, gomas.TRANSA)
	sI.Diag(I)
	sI.Add(-1.0)
	nrm := lapackd.NormP(I, lapackd.NORM_ONE)
	t.Logf("N=%d, beta=%e ||I - Q.T*Q||_1: %e\n", N, beta, nrm)
}
예제 #7
0
파일: chol.go 프로젝트: hrautila/gomas
func unblockedLowerCHOL(A *cmat.FloatMatrix, flags int, nr int) (err *gomas.Error) {
	var ATL, ATR, ABL, ABR cmat.FloatMatrix
	var A00, a10, a11, A20, a21, A22 cmat.FloatMatrix

	err = nil
	util.Partition2x2(
		&ATL, &ATR,
		&ABL, &ABR, A, 0, 0, util.PTOPLEFT)

	for m(&ATL) < m(A) {
		util.Repartition2x2to3x3(&ATL,
			&A00, nil, nil,
			&a10, &a11, nil,
			&A20, &a21, &A22, A, 1, util.PBOTTOMRIGHT)

		// a11 = sqrt(a11)
		aval := a11.Get(0, 0)
		if aval < 0.0 {
			if err == nil {
				err = gomas.NewError(gomas.ENEGATIVE, "DecomposeCHOL", m(&ATL)+nr)
			}
		} else {
			a11.Set(0, 0, math.Sqrt(aval))
		}

		// a21 = a21/a11
		blasd.InvScale(&a21, a11.Get(0, 0))
		// A22 = A22 - a21*a21' (SYR)
		blasd.MVUpdateSym(&A22, &a21, -1.0, gomas.LOWER)

		util.Continue3x3to2x2(
			&ATL, &ATR,
			&ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT)

	}
	return
}
예제 #8
0
파일: house.go 프로젝트: hrautila/gomas
/* From LAPACK/dlarfg.f
 *
 * Generates a real elementary reflector H of order n, such
 * that
 *
 *       H * ( alpha ) = ( beta ),   H**T * H = I.
 *           (   x   )   (   0  )
 *
 * where alpha and beta are scalars, and x is an (n-1)-element real
 * vector. H is represented in the form
 *
 *       H = I - tau * ( 1 ) * ( 1 v**T ) ,
 *                     ( v )
 *
 * where tau is a real scalar and v is a real (n-1)-element
 * vector.
 *
 * If the elements of x are all zero, then tau = 0 and H is taken to be
 * the unit cmat.
 *
 * Otherwise  1 <= tau <= 2.
 */
func computeHouseholder(a11, x, tau *cmat.FloatMatrix) {

	// norm_x2 = ||x||_2
	norm_x2 := blasd.Nrm2(x)
	if norm_x2 == 0.0 {
		tau.Set(0, 0, 0.0)
		return
	}

	alpha := a11.Get(0, 0)
	sign := 1.0
	if math.Signbit(alpha) {
		sign = -1.0
	}
	// beta = -(alpha / |alpha|) * ||alpha x||
	//      = -sign(alpha) * sqrt(alpha**2, norm_x2**2)
	beta := -sign * sqrtX2Y2(alpha, norm_x2)

	// x = x /(a11 - beta)
	blasd.InvScale(x, alpha-beta)

	tau.Set(0, 0, (beta-alpha)/beta)
	a11.Set(0, 0, beta)
}
예제 #9
0
파일: ldlbku.go 프로젝트: hrautila/gomas
/*
 * 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
}
예제 #10
0
파일: ldlbku.go 프로젝트: hrautila/gomas
func unblkBoundedBKUpper(A, wrk *cmat.FloatMatrix, p *Pivots, ncol int, 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 w00, w01, w11 cmat.FloatMatrix
	var cwrk cmat.FloatMatrix
	var pT, pB, p0, p1, p2 Pivots

	err = nil
	nc := 0
	if ncol > n(A) {
		ncol = n(A)
	}

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

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

	for n(&ATL) > 0 && nc < ncol {

		util.Partition2x2(
			&w00, &w01,
			nil, &w11, wrk, nc, nc, util.PBOTTOMRIGHT)

		r, np := findAndBuildBKPivotUpper(&ATL, &ATR, &w00, &w01, nc)
		if np > ncol-nc {
			// next pivot does not fit into ncol columns,
			// return with number of factorized columns
			return err, nc
		}
		cwrk.SubMatrix(&w00, 0, n(&w00)-np, m(&ATL), np)
		if r != -1 {
			// pivoting needed; do swaping here
			k := m(&ATL) - np
			applyBKPivotSymUpper(&ATL, k, r)
			// swap right hand rows to get correct updates
			swapRows(&ATR, k, r)
			swapRows(&w01, k, r)
			if np == 2 && r != k {
				/* for 2x2 blocks we need diagonal pivots.
				 *          [r, r] | [ r,-1]
				 * a11 ==   ----------------  2-by-2 pivot, swapping [1,0] and [r,0]
				 *          [-1,r] | [-1,-1]
				 */
				t0 := w00.Get(k, -1)
				tr := w00.Get(r, -1)
				w00.Set(k, -1, tr)
				w00.Set(r, -1, t0)
				t0 = w00.Get(k, -2)
				tr = w00.Get(r, -2)
				w00.Set(k, -2, tr)
				w00.Set(r, -2, t0)
			}
		}
		// 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)
		// ------------------------------------------------------------

		wlc := n(&w00) - np
		cwrk.SubMatrix(&w00, 0, wlc, m(&a01), n(&a01))
		if np == 1 {
			//
			a11.Set(0, 0, w00.Get(m(&a01), wlc))
			// a21 = a21/a11
			blasd.Copy(&a01, &cwrk)
			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 {
			/*          a | b                       d/b | -1
			 *  w00 == ------  == a11 --> a11.-1 == -------- * scale
			 *          . | d                        -1 | a/b
			 */
			a := w00.Get(m(&ATL)-2, -2)
			b := w00.Get(m(&ATL)-2, -1)
			d := w00.Get(m(&ATL)-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

			// a01 = a01*a11.-1
			blasd.Mult(&a01, &cwrk, &a11inv, scale, 0.0, gomas.NONE, conf)
			a11.Set(0, 0, a)
			a11.Set(0, 1, b)
			a11.Set(1, 1, d)

			// 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
}
예제 #11
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
}
예제 #12
0
파일: ldlbkl.go 프로젝트: hrautila/gomas
/*
 * Unblocked, bounded Bunch-Kauffman LDL factorization for at most ncol columns.
 * At most ncol columns are factorized and trailing matrix updates are restricted
 * to ncol columns. Also original columns are accumulated to working matrix, which
 * is used by calling blocked algorithm to update the trailing matrix with BLAS3
 * update.
 *
 * Corresponds lapack.DLASYF
 */
func unblkBoundedBKLower(A, wrk *cmat.FloatMatrix, p *Pivots, ncol int, 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 w00, w10, w11 cmat.FloatMatrix
	var cwrk cmat.FloatMatrix
	var pT, pB, p0, p1, p2 Pivots

	err = nil
	nc := 0
	if ncol > n(A) {
		ncol = n(A)
	}

	// 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)

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

	for n(&ABR) > 0 && nc < ncol {

		util.Partition2x2(
			&w00, nil,
			&w10, &w11, wrk, nc, nc, util.PTOPLEFT)

		r, np := findAndBuildBKPivotLower(&ABL, &ABR, &w10, &w11, nc)
		if np > ncol-nc {
			// next pivot does not fit into ncol columns, restore last column,
			// return with number of factorized columns
			return err, nc
		}
		if r != 0 && r != np-1 {
			// pivoting needed; do swaping here
			applyBKPivotSymLower(&ABR, np-1, r)
			// swap left hand rows to get correct updates
			swapRows(&ABL, np-1, r)
			swapRows(&w10, 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]
				 */
				t0 := w11.Get(1, 0)
				tr := w11.Get(r, 0)
				w11.Set(1, 0, tr)
				w11.Set(r, 0, t0)
				// interchange diagonal entries on w11[:,1]
				t0 = w11.Get(1, 1)
				tr = w11.Get(r, 1)
				w11.Set(1, 1, tr)
				w11.Set(r, 1, t0)
			}
		}
		// 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 {
			//
			cwrk.SubMatrix(&w11, np, 0, m(&a21), np)
			a11.Set(0, 0, w11.Get(0, 0))
			// a21 = a21/a11
			blasd.Copy(&a21, &cwrk)
			blasd.InvScale(&a21, a11.Get(0, 0))
			// store pivot point relative to original matrix
			p1[0] = r + m(&ATL) + 1
		} else if np == 2 {
			/*
			 * See comments for this block in unblkDecompBKLower().
			 */
			a := w11.Get(0, 0)
			b := w11.Get(1, 0)
			d := w11.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.SubMatrix(&w11, np, 0, m(&a21), np)
			// a21 = a21*a11.-1
			blasd.Mult(&a21, &cwrk, &a11inv, scale, 0.0, gomas.NONE, conf)
			a11.Set(0, 0, a)
			a11.Set(1, 0, b)
			a11.Set(1, 1, d)

			// 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
}
예제 #13
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
}
예제 #14
0
파일: lu.go 프로젝트: hrautila/gomas
// 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
}