Beispiel #1
0
func findBKPivotUpper(A *cmat.FloatMatrix) (int, int) {
	var r, q int
	var rcol, qrow cmat.FloatMatrix
	if m(A) == 1 {
		return 0, 1
	}
	lastcol := m(A) - 1
	amax := math.Abs(A.Get(lastcol, lastcol))
	// column above [A.Rows()-1, A.Rows()-1]
	rcol.SubMatrix(A, 0, lastcol, lastcol, 1)

	r = blasd.IAmax(&rcol)
	// max off-diagonal on first column at index r
	rmax := math.Abs(A.Get(r, lastcol))

	if amax >= bkALPHA*rmax {
		// no pivoting, 1x1 diagonal
		return -1, 1
	}
	// max off-diagonal on r'th row at index q
	//  a) rest of the r'th row above diagonal
	qmax := 0.0
	if r > 0 {
		qrow.SubMatrix(A, 0, r, r, 1)
		q = blasd.IAmax(&qrow)
		qmax = math.Abs(A.Get(q, r /*+1*/))
	}
	//  b) elements right of diagonal
	qrow.SubMatrix(A, r, r+1, 1, lastcol-r)
	q = blasd.IAmax(&qrow)
	qmax2 := math.Abs(qrow.Get(0, q))
	if qmax2 > qmax {
		qmax = qmax2
	}

	if amax >= bkALPHA*rmax*(rmax/qmax) {
		// no pivoting, 1x1 diagonal
		return -1, 1
	}
	if math.Abs(A.Get(r, r)) >= bkALPHA*qmax {
		// 1x1 pivoting and interchange with k, r
		return r, 1
	} else {
		// 2x2 pivoting and interchange with k+1, r
		return r, 2
	}
	return 0, 1
}
Beispiel #2
0
/*
 * α = (1 + sqrt(17))/8
 * λ = |a(r,1)| = max{|a(2,1)|, . . . , |a(m,1)|}
 * if λ > 0
 *     if |a(1,1)| ≥ αλ
 *         use a11 as 1-by-1 pivot
 *     else
 *         σ = |a(p,r)| = max{|a(1,r)|,..., |a(r−1,r)|, |a(r+1,r)|,..., |a(m,r)|}
 *         if |a(1,1) |σ ≥ αλ^2
 *             use a(1,1) as 1-by-1 pivot
 *         else if |a(r,r)| ≥ ασ
 *             use a(r,r) as 1-by-1 pivot
 *         else
 *                  a11 | ar1
 *             use  --------  as 2-by-2 pivot
 *                  ar1 | arr
 *         end
 *     end
 * end
 *
 *    -----------------------
 *    | 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 findBKPivotLower(A *cmat.FloatMatrix) (int, int) {
	var r, q int
	var rcol, qrow cmat.FloatMatrix
	if m(A) == 1 {
		return 0, 1
	}
	amax := math.Abs(A.Get(0, 0))
	// column below diagonal at [0, 0]
	rcol.SubMatrix(A, 1, 0, m(A)-1, 1)
	r = blasd.IAmax(&rcol) + 1
	// max off-diagonal on first column at index r
	rmax := math.Abs(A.Get(r, 0))
	if amax >= bkALPHA*rmax {
		// no pivoting, 1x1 diagonal
		return 0, 1
	}
	// max off-diagonal on r'th row at index q
	qrow.SubMatrix(A, r, 0, 1, r /*+1*/)
	q = blasd.IAmax(&qrow)
	qmax := math.Abs(A.Get(r, q /*+1*/))
	if r < m(A)-1 {
		// rest of the r'th row after diagonal
		qrow.SubMatrix(A, r+1, r, m(A)-r-1, 1)
		q = blasd.IAmax(&qrow)
		qmax2 := math.Abs(qrow.Get(q, 0))
		if qmax2 > qmax {
			qmax = qmax2
		}
	}

	if amax >= bkALPHA*rmax*(rmax/qmax) {
		// no pivoting, 1x1 diagonal
		return 0, 1
	}
	if math.Abs(A.Get(r, r)) >= bkALPHA*qmax {
		// 1x1 pivoting and interchange with k, r
		return r, 1
	} else {
		// 2x2 pivoting and interchange with k+1, r
		return r, 2
	}
	return 0, 1
}
Beispiel #3
0
/*
 * Find diagonal pivot and build incrementaly updated block.
 *
 *    d x r2 x  x  x  c1 | x x     kp1 k | w w
 *      d r2 x  x  x  c1 | x x     kp1 k | w w
 *        r2 r2 r2 r2 c1 | x x     kp1 k | w w
 *           d  x  x  c1 | x x     kp1 k | w w
 *              d  x  c1 | x x     kp1 k | w w
 *                 d  c1 | x x     kp1 k | w w
 *                    c1 | x x     kp1 k | w w
 *   --------------------------   -------------
 *               (AL)     (AR)     (WL)   (WR)
 *
 * Matrix AL contains the unfactored part of the matrix and AR the already
 * factored columns. Matrix WR is updated values of factored part ie.
 * w(i) = l(i)d(i). Matrix WL will have updated values for next column.
 * Column WL(k) contains updated AL(c1) and WL(kp1) possible pivot row AL(r2).
 *
 * On exit, for 1x1 diagonal the rightmost column of WL (k) holds the updated
 * value of AL(c1). If pivoting this required the WL(k) holds the actual pivoted
 * column/row.
 *
 * For 2x2 diagonal blocks WL(k) holds the updated AL(c1) and WL(kp1) holds
 * actual values of pivot column/row AL(r2), without the diagonal pivots.
 */
func findAndBuildBKPivotUpper(AL, AR, WL, WR *cmat.FloatMatrix, k int) (int, int) {
	var r, q int
	var rcol, qrow, src, wk, wkp1, wrow cmat.FloatMatrix

	lc := n(AL) - 1
	wc := n(WL) - 1
	lr := m(AL) - 1

	// Copy AL[:,lc] to WL[:,wc] and update with WR[0:]
	src.SubMatrix(AL, 0, lc, m(AL), 1)
	wk.SubMatrix(WL, 0, wc, m(AL), 1)
	blasd.Copy(&wk, &src)
	if k > 0 {
		wrow.SubMatrix(WR, lr, 0, 1, n(WR))
		blasd.MVMult(&wk, AR, &wrow, -1.0, 1.0, gomas.NONE)
	}
	if m(AL) == 1 {
		return -1, 1
	}
	// amax is on-diagonal element of current column
	amax := math.Abs(WL.Get(lr, wc))

	// find max off-diagonal on first column.
	rcol.SubMatrix(WL, 0, wc, lr, 1)
	// r is row index and rmax is its absolute value
	r = blasd.IAmax(&rcol)
	rmax := math.Abs(rcol.Get(r, 0))
	if amax >= bkALPHA*rmax {
		// no pivoting, 1x1 diagonal
		return -1, 1
	}

	// Now we need to copy row r to WL[:,wc-1] and update it
	wkp1.SubMatrix(WL, 0, wc-1, m(AL), 1)
	if r > 0 {
		// above the diagonal part of AL
		qrow.SubMatrix(AL, 0, r, r, 1)
		blasd.Copy(&wkp1, &qrow)
	}
	var wkr cmat.FloatMatrix
	qrow.SubMatrix(AL, r, r, 1, m(AL)-r)
	wkr.SubMatrix(&wkp1, r, 0, m(AL)-r, 1)
	blasd.Copy(&wkr, &qrow)
	if k > 0 {
		// update wkp1
		wrow.SubMatrix(WR, r, 0, 1, n(WR))
		blasd.MVMult(&wkp1, AR, &wrow, -1.0, 1.0, gomas.NONE)
	}
	// set on-diagonal entry to zero to avoid hitting it.
	p1 := wkp1.Get(r, 0)
	wkp1.Set(r, 0, 0.0)

	// max off-diagonal on r'th column/row at index q
	q = blasd.IAmax(&wkp1)
	qmax := math.Abs(wkp1.Get(q, 0))
	wkp1.Set(r, 0, p1)

	if amax >= bkALPHA*rmax*(rmax/qmax) {
		// no pivoting, 1x1 diagonal
		return -1, 1
	}
	// if q == r then qmax is not off-diagonal, qmax == WR[r,1] and
	// we get 1x1 pivot as following is always true
	if math.Abs(WL.Get(r, wc-1)) >= bkALPHA*qmax {
		// 1x1 pivoting and interchange with k, r
		// pivot row in column WL[:,-2] to WL[:,-1]
		src.SubMatrix(WL, 0, wc-1, m(AL), 1)
		wkp1.SubMatrix(WL, 0, wc, m(AL), 1)
		blasd.Copy(&wkp1, &src)
		wkp1.Set(-1, 0, src.Get(r, 0))
		wkp1.Set(r, 0, src.Get(-1, 0))
		return r, 1
	} else {
		// 2x2 pivoting and interchange with k+1, r
		return r, 2
	}
	return -1, 1
}
Beispiel #4
0
/*
 * Find diagonal pivot and build incrementaly updated block.
 *
 *  (AL)  (AR)                   (WL)  (WR)
 *  --------------------------   ----------    k'th row in W
 *  x x | c1                     w w | k kp1
 *  x x | c1 d                   w w | k kp1
 *  x x | c1 x  d                w w | k kp1
 *  x x | c1 x  x  d             w w | k kp1
 *  x x | c1 r2 r2 r2 r2         w w | k kp1
 *  x x | c1 x  x  x  r2 d       w w | k kp1
 *  x x | c1 x  x  x  r2 x d     w w | k kp1
 *
 * Matrix AR contains the unfactored part of the matrix and AL the already
 * factored columns. Matrix WL is updated values of factored part ie.
 * w(i) = l(i)d(i). Matrix WR will have updated values for next column.
 * Column WR(k) contains updated AR(c1) and WR(kp1) possible pivot row AR(r2).
 */
func findAndBuildBKPivotLower(AL, AR, WL, WR *cmat.FloatMatrix, k int) (int, int) {
	var r, q int
	var rcol, qrow, src, wk, wkp1, wrow cmat.FloatMatrix

	// Copy AR column 0 to WR column 0 and update with WL[0:]
	src.SubMatrix(AR, 0, 0, m(AR), 1)
	wk.SubMatrix(WR, 0, 0, m(AR), 1)
	wk.Copy(&src)
	if k > 0 {
		wrow.SubMatrix(WL, 0, 0, 1, n(WL))
		blasd.MVMult(&wk, AL, &wrow, -1.0, 1.0, gomas.NONE)
	}
	if m(AR) == 1 {
		return 0, 1
	}
	amax := math.Abs(WR.Get(0, 0))

	// find max off-diagonal on first column.
	rcol.SubMatrix(WR, 1, 0, m(AR)-1, 1)

	// r is row index and rmax is its absolute value
	r = blasd.IAmax(&rcol) + 1
	rmax := math.Abs(rcol.Get(r-1, 0))
	if amax >= bkALPHA*rmax {
		// no pivoting, 1x1 diagonal
		return 0, 1
	}
	// Now we need to copy row r to WR[:,1] and update it
	wkp1.SubMatrix(WR, 0, 1, m(AR), 1)
	qrow.SubMatrix(AR, r, 0, 1, r+1)
	blasd.Copy(&wkp1, &qrow)
	if r < m(AR)-1 {
		var wkr cmat.FloatMatrix
		qrow.SubMatrix(AR, r, r, m(AR)-r, 1)
		wkr.SubMatrix(&wkp1, r, 0, m(&wkp1)-r, 1)
		blasd.Copy(&wkr, &qrow)
	}
	if k > 0 {
		// update wkp1
		wrow.SubMatrix(WL, r, 0, 1, n(WL))
		blasd.MVMult(&wkp1, AL, &wrow, -1.0, 1.0, gomas.NONE)
	}

	// set on-diagonal entry to zero to avoid finding it
	p1 := wkp1.Get(r, 0)
	wkp1.Set(r, 0, 0.0)
	// max off-diagonal on r'th column/row at index q
	q = blasd.IAmax(&wkp1)
	qmax := math.Abs(wkp1.Get(q, 0))
	// restore on-diagonal entry
	wkp1.Set(r, 0, p1)

	if amax >= bkALPHA*rmax*(rmax/qmax) {
		// no pivoting, 1x1 diagonal
		return 0, 1
	}
	// if q == r then qmax is not off-diagonal, qmax == WR[r,1] and
	// we get 1x1 pivot as following is always true
	if math.Abs(WR.Get(r, 1)) >= bkALPHA*qmax {
		// 1x1 pivoting and interchange with k, r
		// pivot row in column WR[:,1] to W[:,0]
		src.SubMatrix(WR, 0, 1, m(AR), 1)
		wkp1.SubMatrix(WR, 0, 0, m(AR), 1)
		blasd.Copy(&wkp1, &src)
		wkp1.Set(0, 0, src.Get(r, 0))
		wkp1.Set(r, 0, src.Get(0, 0))
		return r, 1
	} else {
		// 2x2 pivoting and interchange with k+1, r
		return r, 2
	}
	return 0, 1
}
Beispiel #5
0
// Find largest absolute value on column
func pivotIndex(A *cmat.FloatMatrix) int {
	return blasd.IAmax(A) + 1
}