func syrkTest(t *testing.T, C, A *matrix.FloatMatrix, flags Flags, vlen, nb int) bool { //var B0 *matrix.FloatMatrix P := A.Cols() S := 0 E := C.Rows() C0 := C.Copy() trans := linalg.OptNoTrans if flags&TRANSA != 0 { trans = linalg.OptTrans P = A.Rows() } uplo := linalg.OptUpper if flags&LOWER != 0 { uplo = linalg.OptLower } blas.SyrkFloat(A, C0, 1.0, 1.0, uplo, trans) if A.Rows() < 8 { //t.Logf("..A\n%v\n", A) t.Logf(" BLAS C0:\n%v\n", C0) } Ar := A.FloatArray() Cr := C.FloatArray() DSymmRankBlk(Cr, Ar, 1.0, 1.0, flags, C.LeadingIndex(), A.LeadingIndex(), P, S, E, vlen, nb) result := C0.AllClose(C) t.Logf(" C0 == C: %v\n", result) if A.Rows() < 8 { t.Logf(" DMRank C:\n%v\n", C) } return result }
func trmvTest(t *testing.T, A *matrix.FloatMatrix, flags Flags, nb int) bool { N := A.Cols() //S := 0 //E := A.Cols() X0 := matrix.FloatWithValue(A.Rows(), 1, 2.0) X1 := X0.Copy() trans := linalg.OptNoTrans if flags&TRANS != 0 { trans = linalg.OptTrans } diag := linalg.OptNonUnit if flags&UNIT != 0 { diag = linalg.OptUnit } uplo := linalg.OptUpper if flags&LOWER != 0 { uplo = linalg.OptLower } blas.TrmvFloat(A, X0, uplo, diag, trans) Ar := A.FloatArray() Xr := X1.FloatArray() if nb == 0 { DTrimvUnblkMV(Xr, Ar, flags, 1, A.LeadingIndex(), N) } result := X0.AllClose(X1) t.Logf(" X0 == X1: %v\n", result) if !result && A.Rows() < 8 { t.Logf(" BLAS TRMV X0:\n%v\n", X0) t.Logf(" DTrmv X1:\n%v\n", X1) } return result }
// Solve multiple right sides. If flags&UNIT then A diagonal is assumed to // to unit and is not referenced. (blas.TRSM) // alpha*B = A.-1*B if flags&LEFT // alpha*B = A.-T*B if flags&(LEFT|TRANS) // alpha*B = B*A.-1 if flags&RIGHT // alpha*B = B*A.-T if flags&(RIGHT|TRANS) // // Matrix A is N*N triangular matrix defined with flags bits as follow // LOWER non-unit lower triangular // LOWER|UNIT unit lower triangular // UPPER non-unit upper triangular // UPPER|UNIT unit upper triangular // // Matrix B is N*P if flags&LEFT or P*N if flags&RIGHT. // func SolveTrm(B, A *matrix.FloatMatrix, alpha float64, flags Flags) error { ok := true empty := false br, bc := B.Size() ar, ac := A.Size() switch flags & (LEFT | RIGHT) { case LEFT: empty = br == 0 ok = br == ac && ac == ar case RIGHT: empty = bc == 0 ok = bc == ar && ac == ar } if empty { return nil } if !ok { return onError("A, B size mismatch") } Ar := A.FloatArray() ldA := A.LeadingIndex() Br := B.FloatArray() ldB := B.LeadingIndex() E := bc if flags&RIGHT != 0 { E = br } // if more workers available can divide to tasks by B columns if flags&LEFT or by // B rows if flags&RIGHT. calgo.DSolveBlk(Br, Ar, alpha, calgo.Flags(flags), ldB, ldA, ac, 0, E, nB) return nil }
func solveMVTest(t *testing.T, A, X0 *matrix.FloatMatrix, flags Flags, bN, bNB int) { X1 := X0.Copy() uplo := linalg.OptUpper diag := linalg.OptNonUnit if flags&LOWER != 0 { uplo = linalg.OptLower } if flags&UNIT != 0 { diag = linalg.OptUnit } blas.TrsvFloat(A, X0, uplo, diag) Ar := A.FloatArray() Xr := X1.FloatArray() if bN == bNB { DSolveUnblkMV(Xr, Ar, flags, 1, A.LeadingIndex(), bN) } else { DSolveBlkMV(Xr, Ar, flags, 1, A.LeadingIndex(), bN, bNB) } ok := X1.AllClose(X0) t.Logf("X1 == X0: %v\n", ok) if !ok && bN < 8 { t.Logf("A=\n%v\n", A) t.Logf("X0=\n%v\n", X0) t.Logf("blas: X0\n%v\n", X0) t.Logf("X1:\n%v\n", X1) } }
// A = alpha*A + beta*B // A = alpha*A + beta*B.T if flags&TRANSB func ScalePlus(A, B *matrix.FloatMatrix, alpha, beta float64, flags Flags) error { Ar := A.FloatArray() ldA := A.LeadingIndex() Br := B.FloatArray() ldB := B.LeadingIndex() S := 0 L := A.Cols() R := 0 E := A.Rows() calgo.DScalePlus(Ar, Br, alpha, beta, calgo.Flags(flags), ldA, ldB, S, L, R, E) return nil }
func trmmTest(t *testing.T, A *matrix.FloatMatrix, flags Flags, nb int) bool { var B0 *matrix.FloatMatrix N := A.Cols() S := 0 E := A.Cols() side := linalg.OptLeft if flags&RIGHT != 0 { B0 = matrix.FloatWithValue(2, A.Rows(), 2.0) side = linalg.OptRight E = B0.Rows() } else { B0 = matrix.FloatWithValue(A.Rows(), 2, 2.0) E = B0.Cols() } B1 := B0.Copy() trans := linalg.OptNoTrans if flags&TRANSA != 0 { trans = linalg.OptTransA } diag := linalg.OptNonUnit if flags&UNIT != 0 { diag = linalg.OptUnit } uplo := linalg.OptUpper if flags&LOWER != 0 { uplo = linalg.OptLower } blas.TrmmFloat(A, B0, 1.0, uplo, diag, trans, side) if A.Rows() < 8 { //t.Logf("..A\n%v\n", A) t.Logf(" BLAS B0:\n%v\n", B0) } Ar := A.FloatArray() Br := B1.FloatArray() if nb != 0 { DTrmmBlk(Br, Ar, 1.0, flags, B1.LeadingIndex(), A.LeadingIndex(), N, S, E, nb) } else { DTrmmUnblk(Br, Ar, 1.0, flags, B1.LeadingIndex(), A.LeadingIndex(), N, S, E, 0) } result := B0.AllClose(B1) t.Logf(" B0 == B1: %v\n", result) if A.Rows() < 8 { t.Logf(" DTrmm B1:\n%v\n", B1) } return result }
/* * Compute * C = C*diag(D) flags & RIGHT == true * C = diag(D)*C flags & LEFT == true * * Arguments * C 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 MultDiag(C, D *matrix.FloatMatrix, flags Flags) { var c, d0 matrix.FloatMatrix if D.Cols() == 1 { // diagonal is column vector switch flags & (LEFT | RIGHT) { case LEFT: // scale rows; for each column element-wise multiply with D-vector for k := 0; k < C.Cols(); k++ { C.SubMatrix(&c, 0, k, C.Rows(), 1) c.Mul(D) } case RIGHT: // scale columns for k := 0; k < C.Cols(); k++ { C.SubMatrix(&c, 0, k, C.Rows(), 1) // scale the column c.Scale(D.GetAt(k, 0)) } } } else { // diagonal is row vector var d *matrix.FloatMatrix if D.Rows() == 1 { d = D } else { D.SubMatrix(&d0, 0, 0, 1, D.Cols(), D.LeadingIndex()+1) d = &d0 } switch flags & (LEFT | RIGHT) { case LEFT: for k := 0; k < C.Rows(); k++ { C.SubMatrix(&c, k, 0, 1, C.Cols()) // scale the row c.Scale(d.GetAt(0, k)) } case RIGHT: // scale columns for k := 0; k < C.Cols(); k++ { C.SubMatrix(&c, 0, k, C.Rows(), 1) // scale the column c.Scale(d.GetAt(0, k)) } } } }
// A = A + alpha*X*Y.T; A is N*N symmetric, X is row or column vector of length N. func MVSymmUpdateUpper(A, X *matrix.FloatMatrix, alpha float64) error { if X.Rows() != 1 && X.Cols() != 1 { return errors.New("X not a vector.") } Ar := A.FloatArray() ldA := A.LeadingIndex() Xr := X.FloatArray() incX := 1 if X.Rows() == 1 { // row vector incX = X.LeadingIndex() } // NOTE: This could diveded to parallel tasks per column. calgo.DSymmRankMV(Ar, Xr, alpha, calgo.UPPER, ldA, incX, 0, A.Cols(), 0) return nil }
// Rank update for symmetric lower or upper matrix (blas.SYRK) // C = beta*C + alpha*A*A.T + alpha*A.T*A func RankUpdateSym(C, A *matrix.FloatMatrix, alpha, beta float64, flags Flags) error { if C.Rows() != C.Cols() { return onError("C not a square matrix") } Ar := A.FloatArray() ldA := A.LeadingIndex() Cr := C.FloatArray() ldC := C.LeadingIndex() S := 0 E := C.Rows() P := A.Cols() if flags&TRANSA != 0 { P = A.Rows() } // if more workers available C can be divided to blocks [S:E, S:E] along diagonal // and updated in separate tasks. calgo.DSymmRankBlk(Cr, Ar, alpha, beta, calgo.Flags(flags), ldC, ldA, P, S, E, vpLen, nB) return nil }
// Y = alpha*A.T*X + beta*Y func MVMultTransA(Y, A, X *matrix.FloatMatrix, alpha, beta float64) error { if Y.Rows() != 1 && Y.Cols() != 1 { return errors.New("Y not a vector.") } if X.Rows() != 1 && X.Cols() != 1 { return errors.New("X not a vector.") } Ar := A.FloatArray() ldA := A.LeadingIndex() Yr := Y.FloatArray() incY := 1 lenY := Y.Rows() if Y.Rows() == 1 { // row vector incY = Y.LeadingIndex() lenY = Y.Cols() } Xr := X.FloatArray() incX := 1 lenX := X.Rows() if X.Rows() == 1 { // row vector incX = X.LeadingIndex() lenX = X.Cols() } calgo.DMultMV(Yr, Ar, Xr, alpha, beta, calgo.TRANSA, incY, ldA, incX, 0, lenX, 0, lenY, vpLen, mB) return nil }
// Calculate C = alpha*A*B + beta*C, C is M*N, A is M*M and B is M*N func MMSymmUpper(C, A, B *matrix.FloatMatrix, alpha, beta float64) error { if A.Rows() != A.Cols() { return errors.New("A matrix not square matrix.") } psize := int64(C.NumElements() * A.Cols()) Ar := A.FloatArray() ldA := A.LeadingIndex() Br := B.FloatArray() ldB := B.LeadingIndex() Cr := C.FloatArray() ldC := C.LeadingIndex() if nWorker <= 1 || psize <= limitOne { calgo.DMultSymm(Cr, Ar, Br, alpha, beta, calgo.LEFT|calgo.UPPER, ldC, ldA, ldB, A.Cols(), 0, C.Cols(), 0, C.Rows(), vpLen, nB, mB) return nil } // here we have more than one worker available worker := func(cstart, cend, rstart, rend int, ready chan int) { calgo.DMultSymm(Cr, Ar, Br, alpha, beta, calgo.LEFT|calgo.UPPER, ldC, ldA, ldB, A.Cols(), cstart, cend, rstart, rend, vpLen, nB, mB) ready <- 1 } colworks, rowworks := divideWork(C.Rows(), C.Cols(), nWorker) scheduleWork(colworks, rowworks, C.Cols(), C.Rows(), worker) return nil }
// Calculate C = alpha*A*B.T + beta*C, C is M*N, A is M*P and B is N*P func MMMultTransB(C, A, B *matrix.FloatMatrix, alpha, beta float64) error { psize := int64(C.NumElements() * A.Cols()) Ar := A.FloatArray() ldA := A.LeadingIndex() Br := B.FloatArray() ldB := B.LeadingIndex() Cr := C.FloatArray() ldC := C.LeadingIndex() if nWorker <= 1 || psize <= limitOne { calgo.DMult(Cr, Ar, Br, alpha, beta, calgo.TRANSB, ldC, ldA, ldB, B.Rows(), 0, C.Cols(), 0, C.Rows(), vpLen, nB, mB) return nil } // here we have more than one worker available worker := func(cstart, cend, rstart, rend int, ready chan int) { calgo.DMult(Cr, Ar, Br, alpha, beta, calgo.TRANSB, ldC, ldA, ldB, B.Rows(), cstart, cend, rstart, rend, vpLen, nB, mB) ready <- 1 } colworks, rowworks := divideWork(C.Rows(), C.Cols(), nWorker) scheduleWork(colworks, rowworks, C.Cols(), C.Rows(), worker) //scheduleWork(colworks, rowworks, worker) return nil }
func Mult0(C, A, B *matrix.FloatMatrix, alpha, beta float64, flags Flags) error { if A.Cols() != B.Rows() { return errors.New("A.cols != B.rows: size mismatch") } psize := int64(C.NumElements()) * int64(A.Cols()) Ar := A.FloatArray() ldA := A.LeadingIndex() Br := B.FloatArray() ldB := B.LeadingIndex() Cr := C.FloatArray() ldC := C.LeadingIndex() if nWorker <= 1 || psize <= limitOne { calgo.DMult0(Cr, Ar, Br, alpha, beta, calgo.Flags(flags), ldC, ldA, ldB, B.Rows(), 0, C.Cols(), 0, C.Rows(), vpLen, nB, mB) return nil } // here we have more than one worker available worker := func(cstart, cend, rstart, rend int, ready chan int) { calgo.DMult0(Cr, Ar, Br, alpha, beta, calgo.Flags(flags), ldC, ldA, ldB, B.Rows(), cstart, cend, rstart, rend, vpLen, nB, mB) ready <- 1 } colworks, rowworks := divideWork(C.Rows(), C.Cols(), nWorker) scheduleWork(colworks, rowworks, C.Cols(), C.Rows(), worker) return nil }
func MVSymm2UpdateUpper(A, X, Y *matrix.FloatMatrix, alpha float64) error { if Y.Rows() != 1 && Y.Cols() != 1 { return errors.New("Y not a vector.") } if X.Rows() != 1 && X.Cols() != 1 { return errors.New("X not a vector.") } Ar := A.FloatArray() ldA := A.LeadingIndex() Yr := Y.FloatArray() incY := 1 if Y.Rows() == 1 { // row vector incY = Y.LeadingIndex() } Xr := X.FloatArray() incX := 1 if X.Rows() == 1 { // row vector incX = X.LeadingIndex() } // NOTE: This could diveded to parallel tasks like matrix-matrix multiplication calgo.DSymmRank2MV(Ar, Xr, Yr, alpha, calgo.UPPER, ldA, incY, incX, 0, A.Cols(), 0) return nil }
func update(t *testing.T, Y1, Y2, C1, C2, T, W *matrix.FloatMatrix) { if W.Rows() != C1.Cols() { panic("W.Rows != C1.Cols") } // W = C1.T ScalePlus(W, C1, 0.0, 1.0, TRANSB) //fmt.Printf("W = C1.T:\n%v\n", W) // W = C1.T*Y1 //MultTrm(W, Y1, 1.0, LOWER|UNIT|RIGHT) Wr := W.FloatArray() Y1r := Y1.FloatArray() ldW := W.LeadingIndex() ldY := Y1.LeadingIndex() calgo.DTrmmUnblk(Wr, Y1r, 1.0, calgo.Flags(LOWER|UNIT|RIGHT), ldW, ldY, Y1.Cols(), 0, W.Rows(), 0) t.Logf("W = C1.T*Y1:\n%v\n", W) // W = W + C2.T*Y2 Mult(W, C2, Y2, 1.0, 1.0, TRANSA) t.Logf("W = W + C2.T*Y2:\n%v\n", W) // --- here: W == C.T*Y --- // W = W*T MultTrm(W, T, 1.0, UPPER|RIGHT) t.Logf("W = C.T*Y*T:\n%v\n", W) // --- here: W == C.T*Y*T --- // C2 = C2 - Y2*W.T Mult(C2, Y2, W, -1.0, 1.0, TRANSB) t.Logf("C2 = C2 - Y2*W.T:\n%v\n", C2) // W = Y1*W.T ==> W.T = W*Y1.T MultTrm(W, Y1, 1.0, LOWER|UNIT|TRANSA|RIGHT) t.Logf("W.T = W*Y1.T:\n%v\n", W) // C1 = C1 - W.T ScalePlus(C1, W, 1.0, -1.0, TRANSB) //fmt.Printf("C1 = C1 - W.T:\n%v\n", C1) // --- here: C = (I - Y*T*Y.T).T * C --- }
// Generic matrix-matrix multpily. (blas.GEMM). Calculates // C = beta*C + alpha*A*B (default) // C = beta*C + alpha*A.T*B flags&TRANSA // C = beta*C + alpha*A*B.T flags&TRANSB // C = beta*C + alpha*A.T*B.T flags&(TRANSA|TRANSB) // // C is M*N, A is M*P or P*M if flags&TRANSA. B is P*N or N*P if flags&TRANSB. // func Mult(C, A, B *matrix.FloatMatrix, alpha, beta float64, flags Flags) error { var ok, empty bool // error checking must take in account flag values! ar, ac := A.Size() br, bc := B.Size() cr, cc := C.Size() switch flags & (TRANSA | TRANSB) { case TRANSA | TRANSB: empty = ac == 0 || br == 0 ok = cr == ac && cc == br && ar == bc case TRANSA: empty = ac == 0 || bc == 0 ok = cr == ac && cc == bc && ar == br case TRANSB: empty = ar == 0 || br == 0 ok = cr == ar && cc == br && ac == bc default: empty = ar == 0 || bc == 0 ok = cr == ar && cc == bc && ac == br } if empty { return nil } if !ok { return errors.New("Mult: size mismatch") } psize := int64(C.NumElements()) * int64(A.Cols()) Ar := A.FloatArray() ldA := A.LeadingIndex() Br := B.FloatArray() ldB := B.LeadingIndex() Cr := C.FloatArray() ldC := C.LeadingIndex() // matrix A, B common dimension P := A.Cols() if flags&TRANSA != 0 { P = A.Rows() } if nWorker <= 1 || psize <= limitOne { calgo.DMult(Cr, Ar, Br, alpha, beta, calgo.Flags(flags), ldC, ldA, ldB, P, 0, C.Cols(), 0, C.Rows(), vpLen, nB, mB) return nil } // here we have more than one worker available worker := func(cstart, cend, rstart, rend int, ready chan int) { calgo.DMult(Cr, Ar, Br, alpha, beta, calgo.Flags(flags), ldC, ldA, ldB, P, cstart, cend, rstart, rend, vpLen, nB, mB) ready <- 1 } colworks, rowworks := divideWork(C.Rows(), C.Cols(), nWorker) scheduleWork(colworks, rowworks, C.Cols(), C.Rows(), worker) return nil }
// Symmetric matrix multiply. (blas.SYMM) // C = beta*C + alpha*A*B (default) // C = beta*C + alpha*A.T*B flags&TRANSA // C = beta*C + alpha*A*B.T flags&TRANSB // C = beta*C + alpha*A.T*B.T flags&(TRANSA|TRANSB) // // C is N*P, A is N*N symmetric matrix. B is N*P or P*N if flags&TRANSB. // func MultSym(C, A, B *matrix.FloatMatrix, alpha, beta float64, flags Flags) error { var ok, empty bool ar, ac := A.Size() br, bc := B.Size() cr, cc := C.Size() switch flags & (TRANSA | TRANSB) { case TRANSA | TRANSB: empty = ac == 0 || br == 0 ok = ar == ac && cr == ac && cc == br && ar == bc case TRANSA: empty = ac == 0 || bc == 0 ok = ar == ac && cr == ac && cc == bc && ar == br case TRANSB: empty = ar == 0 || br == 0 ok = ar == ac && cr == ar && cc == br && ac == bc default: empty = ar == 0 || bc == 0 ok = ar == ac && cr == ar && cc == bc && ac == br } if empty { return nil } if !ok { return errors.New("MultSym: size mismatch") } /* if A.Rows() != A.Cols() { return errors.New("A matrix not square matrix."); } if A.Cols() != B.Rows() { return errors.New("A.cols != B.rows: size mismatch") } */ psize := int64(C.NumElements()) * int64(A.Cols()) Ar := A.FloatArray() ldA := A.LeadingIndex() Br := B.FloatArray() ldB := B.LeadingIndex() Cr := C.FloatArray() ldC := C.LeadingIndex() if nWorker <= 1 || psize <= limitOne { calgo.DMultSymm(Cr, Ar, Br, alpha, beta, calgo.Flags(flags), ldC, ldA, ldB, A.Cols(), 0, C.Cols(), 0, C.Rows(), vpLen, nB, mB) return nil } // here we have more than one worker available worker := func(cstart, cend, rstart, rend int, ready chan int) { calgo.DMultSymm(Cr, Ar, Br, alpha, beta, calgo.Flags(flags), ldC, ldA, ldB, A.Cols(), cstart, cend, rstart, rend, vpLen, nB, mB) ready <- 1 } colworks, rowworks := divideWork(C.Rows(), C.Cols(), nWorker) scheduleWork(colworks, rowworks, C.Cols(), C.Rows(), worker) return nil }
func TestMultMVTransASmall(t *testing.T) { data6 := [][]float64{ []float64{-1.59e+00, 6.56e-02, 2.14e-01, 6.79e-01, 2.93e-01, 5.24e-01}, []float64{4.28e-01, 1.57e-01, 3.81e-01, 2.19e-01, 2.97e-01, 2.83e-02}, []float64{3.02e-01, 9.70e-02, 3.18e-01, 2.03e-01, 7.53e-01, 1.58e-01}, []float64{1.99e-01, 3.01e-01, 4.69e-01, 3.61e-01, 2.07e-01, 6.07e-01}, []float64{1.93e-01, 5.15e-01, 2.83e-01, 5.71e-01, 8.65e-01, 9.75e-01}, []float64{3.13e-01, 8.14e-01, 2.93e-01, 8.62e-01, 6.97e-01, 7.95e-02}} data5 := [][]float64{ []float64{1.57e-01, 3.81e-01, 2.19e-01, 2.97e-01, 2.83e-02}, []float64{9.70e-02, 3.18e-01, 2.03e-01, 7.53e-01, 1.58e-01}, []float64{3.01e-01, 4.69e-01, 3.61e-01, 2.07e-01, 6.07e-01}, []float64{5.15e-01, 2.83e-01, 5.71e-01, 8.65e-01, 9.75e-01}, []float64{8.14e-01, 2.93e-01, 8.62e-01, 6.97e-01, 7.95e-02}} data2 := []float64{4.28e-01, 3.02e-01, 1.99e-01, 1.93e-01, 3.13e-01} bM := 5 bN := 4 nb := 2 //A := matrix.FloatNormal(bN, bM) //X := matrix.FloatWithValue(bN, 1, 1.0) A := matrix.FloatMatrixFromTable(data5, matrix.RowOrder) X := matrix.FloatNew(5, 1, data2) bM = A.Rows() bN = A.Cols() Ym := matrix.FloatZeros(3, bM) Y1 := matrix.FloatZeros(bM, 1) Y0 := matrix.FloatZeros(bM, 1) Ar := A.FloatArray() Xr := X.FloatArray() Y1r := Y1.FloatArray() blas.GemvFloat(A, X, Y0, 1.0, 1.0, linalg.OptTrans) DMultMV(Y1r, Ar, Xr, 1.0, 1.0, TRANSA, 1, A.LeadingIndex(), 1, 0, bN, 0, bM, nb, nb) ok := Y0.AllClose(Y1) t.Logf("Y0 == Y1: %v\n", ok) if ok || !ok { t.Logf("blas: Y=A.T*X\n%v\n", Y0) t.Logf("Y1: Y1 = A*X\n%v\n", Y1) } // zero Y0, Y1 Y0.Scale(0.0) Y1.Scale(0.0) // test with matrix view; A is view var A0 matrix.FloatMatrix A6 := matrix.FloatMatrixFromTable(data6, matrix.RowOrder) A0.SubMatrixOf(A6, 1, 1) blas.GemvFloat(&A0, X, Y0, 1.0, 1.0, linalg.OptTrans) Ar = A0.FloatArray() DMultMV(Y1r, Ar, Xr, 1.0, 1.0, TRANSA, 1, A0.LeadingIndex(), 1, 0, bN, 0, bM, nb, nb) ok = Y0.AllClose(Y1) t.Logf("lda>rows: Y0 == Y1: %v\n", ok) if ok || !ok { t.Logf("blas: Y=A.T*X\n%v\n", Y0) t.Logf("Y1: Y1 = A*X\n%v\n", Y1) } // Y is view too. Y1.SubMatrixOf(Ym, 0, 0, 1, bM) Y1r = Y1.FloatArray() DMultMV(Y1r, Ar, Xr, 1.0, 1.0, TRANSA, Y1.LeadingIndex(), A0.LeadingIndex(), 1, 0, bN, 0, bM, nb, nb) ok = Y0.AllClose(Y1.Transpose()) t.Logf("Y0 == Y1 row: %v\n", ok) t.Logf("row Y1: %v\n", Y1) }
func trsmSolve(t *testing.T, A *matrix.FloatMatrix, flags Flags, rand bool, nrhs, nb int) bool { var B0 *matrix.FloatMatrix side := linalg.OptLeft trans := linalg.OptNoTrans N := A.Cols() S := 0 E := A.Rows() _ = S _ = E if flags&RIGHT != 0 { if rand { B0 = matrix.FloatNormal(nrhs, A.Rows()) } else { B0 = matrix.FloatWithValue(nrhs, A.Rows(), 2.0) } side = linalg.OptRight E = B0.Rows() } else { if rand { B0 = matrix.FloatNormal(A.Rows(), nrhs) } else { B0 = matrix.FloatWithValue(A.Rows(), nrhs, 2.0) } E = B0.Cols() } B1 := B0.Copy() diag := linalg.OptNonUnit if flags&UNIT != 0 { diag = linalg.OptUnit } uplo := linalg.OptUpper if flags&LOWER != 0 { uplo = linalg.OptLower } if flags&TRANSA != 0 { trans = linalg.OptTransA } blas.TrsmFloat(A, B0, 1.0, uplo, diag, side, trans) Ar := A.FloatArray() Br := B1.FloatArray() if nb == 0 || nb == N { DSolveUnblk(Br, Ar, 1.0, flags, B1.LeadingIndex(), A.LeadingIndex(), N, S, E) } else { DSolveBlk(Br, Ar, 1.0, flags, B1.LeadingIndex(), A.LeadingIndex(), N, S, E, nb) } result := B1.AllClose(B0) t.Logf("B1 == B0: %v\n", result) if !result { if nrhs < 10 { t.Logf("blas: B0\n%v\n", B0) t.Logf("B1:\n%v\n", B1) } else { b0 := B0.FloatArray() b1 := B1.FloatArray() for k := 0; k < len(b0); k++ { if !isClose(b0[k], b1[k]) { t.Logf("first divergences at %d ... col %d, row %d\n", k, k/B0.Rows(), k%B0.Rows()) break } } } } return result }