/* * Applies a real elementary reflector H to a real m by n matrix A, * from either the left or the right. 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 vector. * * If tau = 0, then H is taken to be the unit cmat. * * A is /a1\ a1 := a1 - w1 * \A2/ A2 := A2 - v*w1 * w1 := tau*(a1 + A2.T*v) if side == LEFT * := tau*(a1 + A2*v) if side == RIGHT * * Intermediate work space w1 required as parameter, no allocation. */ func applyHouseholder2x1(tau, v, a1, A2, w1 *cmat.FloatMatrix, flags int) *gomas.Error { var err *gomas.Error = nil tval := tau.Get(0, 0) if tval == 0.0 { return err } // shape oblivious vector copy. blasd.Axpby(w1, a1, 1.0, 0.0) if flags&gomas.LEFT != 0 { // w1 = a1 + A2.T*v err = blasd.MVMult(w1, A2, v, 1.0, 1.0, gomas.TRANSA) } else { // w1 = a1 + A2*v err = blasd.MVMult(w1, A2, v, 1.0, 1.0, gomas.NONE) } // w1 = tau*w1 blasd.Scale(w1, tval) // a1 = a1 - w1 blasd.Axpy(a1, w1, -1.0) // A2 = A2 - v*w1 if flags&gomas.LEFT != 0 { err = blasd.MVUpdate(A2, v, w1, -1.0) } else { err = blasd.MVUpdate(A2, w1, v, -1.0) } return err }
func TestDSyr1(t *testing.T) { const N = 911 A := cmat.NewMatrix(N, N) X := cmat.NewMatrix(N, 1) B := cmat.NewMatrix(N, N) //ones := cmat.NewFloatConstSource(1.0) zeromean := cmat.NewFloatUniformSource(0.5, 2.0) A.SetFrom(zeromean, cmat.LOWER) X.SetFrom(zeromean) B.Copy(A) // B = A*B blasd.MVUpdate(B, X, X, 1.0) cmat.TriL(B, cmat.NONE) blasd.MVUpdateSym(A, X, 1.0, gomas.LOWER) ok := B.AllClose(A) t.Logf("MVUpdateSym(A, X, L) == TriL(MVUpdate(A, X, X)) : %v\n", ok) A.SetFrom(zeromean, cmat.UPPER) cmat.TriU(A, cmat.NONE) B.Copy(A) blasd.MVUpdate(B, X, X, 1.0) cmat.TriU(B, cmat.NONE) blasd.MVUpdateSym(A, X, 1.0, gomas.UPPER) ok = B.AllClose(A) t.Logf("MVUpdateSym(A, X, U) == TriU(MVUpdate(A, X, X)) : %v\n", ok) }
func TestDSyrOther(t *testing.T) { const N = 911 var vec, As, Bs cmat.FloatMatrix P := N / 3 A := cmat.NewMatrix(P, P) X := cmat.NewMatrix(P, 1) B := cmat.NewMatrix(P, P) //ones := cmat.NewFloatConstSource(1.0) zeromean := cmat.NewFloatUniformSource(0.5, 2.0) A.SetFrom(zeromean, cmat.UPPER) X.SetFrom(zeromean) B.Copy(A) // update submatrices for i := 1; i < P; i++ { vec.SubMatrix(A, i-1, i, 1, P-i) As.SubMatrix(A, i, i) Bs.SubMatrix(B, i, i) // update with normal and symmetric blasd.MVUpdate(&Bs, &vec, &vec, 1.0) blasd.MVUpdateSym(&As, &vec, 1.0, gomas.UPPER) } // make normal update triangular and compare cmat.TriU(B, cmat.NONE) ok := B.AllClose(A) t.Logf("submatrix updates on upper triangular : %v\n", ok) A.SetFrom(zeromean, cmat.LOWER) cmat.TriL(A, cmat.NONE) B.Copy(A) // update submatrices for i := 1; i < P; i++ { vec.SubMatrix(A, i-1, i, 1, P-i) As.SubMatrix(A, i, i) Bs.SubMatrix(B, i, i) // update with normal and symmetric blasd.MVUpdate(&Bs, &vec, &vec, 1.0) blasd.MVUpdateSym(&As, &vec, 1.0, gomas.LOWER) } // make normal update triangular and compare cmat.TriL(B, cmat.NONE) ok = B.AllClose(A) t.Logf("submatrix updates on lower triangular : %v\n", ok) }
// 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 }
func TestDSyr2(t *testing.T) { const N = 911 A := cmat.NewMatrix(N, N) X := cmat.NewMatrix(N, 1) Y := cmat.NewMatrix(N, 1) B := cmat.NewMatrix(N, N) ones := cmat.NewFloatConstSource(1.0) twos := cmat.NewFloatConstSource(2.0) zeromean := cmat.NewFloatUniformSource(0.5, 2.0) A.SetFrom(zeromean, cmat.LOWER) X.SetFrom(ones) Y.SetFrom(twos) B.Copy(A) // B = A*B blasd.MVUpdate(B, X, Y, 1.0) blasd.MVUpdate(B, Y, X, 1.0) cmat.TriL(B, cmat.NONE) blasd.MVUpdate2Sym(A, X, Y, 1.0, gomas.LOWER) ok := B.AllClose(A) if N < 10 { t.Logf("A:\n%v\n", A) t.Logf("B:\n%v\n", B) } t.Logf("MVUpdate2Sym(A, X, Y, L) == TriL(MVUpdate(A, X, Y);MVUpdate(A, Y, X)) : %v\n", ok) A.SetFrom(zeromean, cmat.UPPER) cmat.TriU(A, cmat.NONE) B.Copy(A) blasd.MVUpdate(B, X, Y, 1.0) blasd.MVUpdate(B, Y, X, 1.0) cmat.TriU(B, cmat.NONE) blasd.MVUpdate2Sym(A, X, Y, 1.0, gomas.UPPER) ok = B.AllClose(A) if N < 10 { t.Logf("A:\n%v\n", A) t.Logf("B:\n%v\n", B) } t.Logf("MVUpdate2Sym(A, X, Y, U) == TriU(MVUpdate(A, X, Y);MVUpdate(A, Y, X)) : %v\n", ok) }
/* * Apply elementary Householder reflector v to matrix A2. * * H = I - tau*v*v.t; * * RIGHT: A = A*H = A - tau*A*v*v.T = A - tau*w1*v.T * LEFT: A = H*A = A - tau*v*v.T*A = A - tau*v*A.T*v = A - tau*v*w1 */ func applyHouseholder1x1(tau, v, A2, w1 *cmat.FloatMatrix, flags int) *gomas.Error { var err *gomas.Error = nil tval := tau.Get(0, 0) if tval == 0.0 { return nil } if flags&gomas.LEFT != 0 { // w1 = A2.T*v err = blasd.MVMult(w1, A2, v, 1.0, 0.0, gomas.TRANSA) if err == nil { // A2 = A2 - tau*v*w1; m(A2) == len(v) && n(A2) == len(w1) err = blasd.MVUpdate(A2, v, w1, -tval) } } else { // w1 = A2*v err = blasd.MVMult(w1, A2, v, 1.0, 0.0, gomas.NONE) if err == nil { // A2 = A2 - tau*w1*v; m(A2) == len(w1) && n(A2) == len(v) err = blasd.MVUpdate(A2, w1, v, -tval) } } return err }
/* From LAPACK/dlarf.f * * Applies a real elementary reflector H to a real m by n matrix A, * from either the left or the right. 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 vector. * * If tau = 0, then H is taken to be the unit cmat. * * A is /a1\ a1 := a1 - w1 * \A2/ A2 := A2 - v*w1 * w1 := tau*(a1 + A2.T*v) if side == LEFT * := tau*(a1 + A2*v) if side == RIGHT * * Allocates/frees intermediate work space matrix w1. */ func applyHouseholder(tau, v, a1, A2 *cmat.FloatMatrix, flags int) { tval := tau.Get(0, 0) if tval == 0.0 { return } w1 := cmat.NewCopy(a1) if flags&gomas.LEFT != 0 { // w1 = a1 + A2.T*v blasd.MVMult(w1, A2, v, 1.0, 1.0, gomas.TRANSA) } else { // w1 = a1 + A2*v blasd.MVMult(w1, A2, v, 1.0, 1.0, gomas.NONE) } // w1 = tau*w1 blasd.Scale(w1, tval) // a1 = a1 - w1 blasd.Axpy(a1, w1, -1.0) // A2 = A2 - v*w1 blasd.MVUpdate(A2, v, w1, -1.0) }
/* * Computes upper Hessenberg reduction of N-by-N matrix A using unblocked * algorithm as described in (1). * * Hessengerg reduction: A = Q.T*B*Q, Q unitary, B upper Hessenberg * Q = H(0)*H(1)*...*H(k) where H(k) is k'th Householder reflector. * * Compatible with lapack.DGEHD2. */ func unblkHessGQvdG(A, Tvec, W *cmat.FloatMatrix, row int) { var ATL, ATR, ABL, ABR cmat.FloatMatrix var A00, a11, a21, A22 cmat.FloatMatrix var AL, AR, A0, a1, A2 cmat.FloatMatrix var tT, tB cmat.FloatMatrix var t0, tau1, t2, w12, v1 cmat.FloatMatrix util.Partition2x2( &ATL, &ATR, &ABL, &ABR, A, row, 0, util.PTOPLEFT) util.Partition1x2( &AL, &AR, A, 0, util.PLEFT) util.Partition2x1( &tT, &tB, Tvec, 0, util.PTOP) v1.SubMatrix(W, 0, 0, m(A), 1) for m(&ABR) > 1 && n(&ABR) > 0 { util.Repartition2x2to3x3(&ATL, &A00, nil, nil, nil, &a11, nil, nil, &a21, &A22, A, 1, util.PBOTTOMRIGHT) util.Repartition1x2to1x3(&AL, &A0, &a1, &A2, A, 1, util.PRIGHT) util.Repartition2x1to3x1(&tT, &t0, &tau1, &t2, Tvec, 1, util.PBOTTOM) // ------------------------------------------------------ // a21 = [beta; H(k)].T computeHouseholderVec(&a21, &tau1) tauval := tau1.Get(0, 0) beta := a21.Get(0, 0) a21.Set(0, 0, 1.0) // v1 := A2*a21 blasd.MVMult(&v1, &A2, &a21, 1.0, 0.0, gomas.NONE) // A2 := A2 - tau*v1*a21 (A2 := A2*H(k)) blasd.MVUpdate(&A2, &v1, &a21, -tauval) w12.SubMatrix(W, 0, 0, n(&A22), 1) // w12 := a21.T*A22 = A22.T*a21 blasd.MVMult(&w12, &A22, &a21, 1.0, 0.0, gomas.TRANS) // A22 := A22 - tau*a21*w12 (A22 := H(k)*A22) blasd.MVUpdate(&A22, &a21, &w12, -tauval) a21.Set(0, 0, beta) // ------------------------------------------------------ util.Continue3x3to2x2( &ATL, &ATR, &ABL, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT) util.Continue1x3to1x2( &AL, &AR, &A0, &a1, A, util.PRIGHT) util.Continue3x1to2x1( &tT, &tB, &t0, &tau1, Tvec, util.PBOTTOM) } }
/* * 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 }
/* * Compute unblocked bidiagonal reduction for A when M >= N * * Diagonal and first super/sub diagonal are overwritten with the * upper/lower bidiagonal matrix B. * * This computing (1-tauq*v*v.T)*A*(1-taup*u.u.T) from left to right. */ func unblkReduceBidiagLeft(A, tauq, taup, W *cmat.FloatMatrix) { var ATL, ABR cmat.FloatMatrix var A00, a11, a12t, a21, A22 cmat.FloatMatrix var tqT, tqB, tq0, tauq1, tq2 cmat.FloatMatrix var tpT, tpB, tp0, taup1, tp2 cmat.FloatMatrix var y21, z21 cmat.FloatMatrix var v0 float64 util.Partition2x2( &ATL, nil, nil, &ABR, A, 0, 0, util.PTOPLEFT) util.Partition2x1( &tqT, &tqB, tauq, 0, util.PTOP) util.Partition2x1( &tpT, &tpB, taup, 0, util.PTOP) for m(&ABR) > 0 && n(&ABR) > 0 { util.Repartition2x2to3x3(&ATL, &A00, nil, nil, nil, &a11, &a12t, nil, &a21, &A22, A, 1, util.PBOTTOMRIGHT) util.Repartition2x1to3x1(&tqT, &tq0, &tauq1, &tq2, tauq, 1, util.PBOTTOM) util.Repartition2x1to3x1(&tpT, &tp0, &taup1, &tp2, taup, 1, util.PBOTTOM) // set temp vectors for this round y21.SetBuf(n(&a12t), 1, n(&a12t), W.Data()) z21.SetBuf(m(&a21), 1, m(&a21), W.Data()[y21.Len():]) // ------------------------------------------------------ // Compute householder to zero subdiagonal entries computeHouseholder(&a11, &a21, &tauq1) // y21 := a12 + A22.T*a21 blasd.Axpby(&y21, &a12t, 1.0, 0.0) blasd.MVMult(&y21, &A22, &a21, 1.0, 1.0, gomas.TRANSA) // a12t := a12t - tauq*y21 tauqv := tauq1.Get(0, 0) blasd.Axpy(&a12t, &y21, -tauqv) // Compute householder to zero elements above 1st superdiagonal computeHouseholderVec(&a12t, &taup1) v0 = a12t.Get(0, 0) a12t.Set(0, 0, 1.0) taupv := taup1.Get(0, 0) // [v == a12t, u == a21] beta := blasd.Dot(&y21, &a12t) // z21 := tauq*beta*u blasd.Axpby(&z21, &a21, tauqv*beta, 0.0) // z21 := A22*v - z21 blasd.MVMult(&z21, &A22, &a12t, 1.0, -1.0, gomas.NONE) // A22 := A22 - tauq*u*y21 blasd.MVUpdate(&A22, &a21, &y21, -tauqv) // A22 := A22 - taup*z21*v blasd.MVUpdate(&A22, &z21, &a12t, -taupv) a12t.Set(0, 0, v0) // ------------------------------------------------------ util.Continue3x3to2x2( &ATL, nil, nil, &ABR, &A00, &a11, &A22, A, util.PBOTTOMRIGHT) util.Continue3x1to2x1( &tqT, &tqB, &tq0, &tauq1, tauq, util.PBOTTOM) util.Continue3x1to2x1( &tpT, &tpB, &tp0, &taup1, taup, util.PBOTTOM) } }