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 }
/* * α = (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 }
/* * 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 }
/* * 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 }
// Find largest absolute value on column func pivotIndex(A *cmat.FloatMatrix) int { return blasd.IAmax(A) + 1 }