bool testGaussTransform (const Ring &F, size_t m, size_t n) { commentator.start ("Testing GaussJordan::echelonize", __FUNCTION__); std::ostream &report = commentator.report (Commentator::LEVEL_NORMAL, INTERNAL_DESCRIPTION); std::ostream &error = commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR); bool pass = true; DenseMatrix<typename Ring::Element> R (m, n); RandomDenseStream<Ring, typename DenseMatrix<typename Ring::Element>::Row> A_stream (F, n, m); DenseMatrix<typename Ring::Element> A (A_stream), A_copy (m, n); typename GaussJordan<Ring>::Permutation P; Context<Ring> ctx (F); Elimination<Ring> elim (ctx); GaussJordan<Ring> GJ (ctx); size_t rank; typename Ring::Element det; BLAS3::copy (ctx, A, R); BLAS3::copy (ctx, A, A_copy); GJ.echelonize (R, P, rank, det); report << "A = " << std::endl; BLAS3::write (ctx, report, A); report << "P = "; BLAS1::write_permutation (report, P.begin (), P.end ()) << std::endl; report << "R, L = " << std::endl; BLAS3::write (ctx, report, R); BLAS3::permute_rows (ctx, P.begin (), P.end (), A); report << "PA = " << std::endl; BLAS3::write (ctx, report, A); typename DenseMatrix<typename Ring::Element>::SubmatrixType Rp (R, 0, 0, R.rowdim (), R.rowdim ()); BLAS3::trmm (ctx, F.one (), Rp, A, LowerTriangular, true); report << "LPA = " << std::endl; BLAS3::write (ctx, report, A); report << "Computed rank = " << rank << std::endl; report << "Computed det = "; F.write (report, det); report << std::endl; // Trick to eliminate part below diagonal so that equality-check works elim.move_L (R, R); if (!BLAS3::equal (ctx, A, R)) { error << "ERROR: LPA != R" << std::endl; pass = false; } elim.echelonize (A_copy, P, rank, det, false); report << "Result of Elimination::echelonize: " << std::endl; BLAS3::write (ctx, report, A_copy); if (!BLAS3::equal (ctx, A_copy, R)) { error << "ERROR: Results from Elimination and GaussJordan not equal" << std::endl; pass = false; } commentator.stop (MSG_STATUS (pass)); return pass; }
bool testEchelonize (const Ring &F, const char *text, Matrix &A) { std::ostringstream str; str << "Testing Elimination::echelonize for " << text << " matrices" << std::ends; commentator.start (str.str ().c_str (), __FUNCTION__); std::ostream &report = commentator.report (Commentator::LEVEL_NORMAL, INTERNAL_DESCRIPTION); std::ostream &error = commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR); bool pass = true; Context<Ring> ctx (F); Elimination<Ring> elim (ctx); typename Matrix::ContainerType PA (A.rowdim (), A.coldim ()), LPA (A.rowdim (), A.coldim ()); BLAS3::copy (ctx, A, PA); typename Elimination<Ring>::Permutation P; size_t rank; typename Ring::Element det; report << "A = " << std::endl; BLAS3::write (ctx, report, A, FORMAT_PRETTY); elim.echelonize (A, P, rank, det, true); report << "L, R = " << std::endl; BLAS3::write (ctx, report, A, FORMAT_PRETTY); report << "P = "; BLAS1::write_permutation (report, P.begin (), P.end ()) << std::endl; BLAS3::permute_rows (ctx, P.begin (), P.end (), PA); report << "PA = " << std::endl; BLAS3::write (ctx, report, PA, FORMAT_PRETTY); typename Matrix::ContainerType L (A.rowdim (), A.rowdim ()); typename Matrix::ContainerType::RowIterator i_L; StandardBasisStream<Ring, typename Matrix::ContainerType::Row> s (ctx.F, A.rowdim ()); for (i_L = L.rowBegin (); i_L != L.rowEnd (); ++i_L) s >> *i_L; elim.move_L (L, A); BLAS3::scal (ctx, F.zero (), LPA); BLAS3::gemm (ctx, F.one (), L, PA, F.zero (), LPA); report << "LPA = " << std::endl; BLAS3::write (ctx, report, LPA); report << "Computed rank = " << rank << std::endl; report << "Computed det = "; F.write (report, det); report << std::endl; if (!BLAS3::equal (ctx, LPA, A)) { error << "LPA != R, not okay" << std::endl; pass = false; } commentator.stop (MSG_STATUS (pass)); return pass; }
bool testGaussJordanTransform (const Ring &F, size_t m, size_t n) { commentator.start ("Testing GaussJordan::echelonize_reduced", __FUNCTION__); std::ostream &report = commentator.report (Commentator::LEVEL_NORMAL, INTERNAL_DESCRIPTION); std::ostream &error = commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR); bool pass = true; DenseMatrix<typename Ring::Element> R (m, n); RandomDenseStream<Ring, typename DenseMatrix<typename Ring::Element>::Row> A_stream (F, n, m); DenseMatrix<typename Ring::Element> A (A_stream), L (m, m), LPA (m, n); typename GaussJordan<Ring>::Permutation P; Context<Ring> ctx (F); GaussJordan<Ring> GJ (ctx); size_t rank; typename Ring::Element det; BLAS3::copy (ctx, A, R); GJ.echelonize_reduced (R, L, P, rank, det); report << "A = " << std::endl; BLAS3::write (ctx, report, A); report << "P = "; BLAS1::write_permutation (report, P.begin (), P.end ()) << std::endl; report << "R = " << std::endl; BLAS3::write (ctx, report, R); report << "L = " << std::endl; BLAS3::write (ctx, report, L); BLAS3::permute_rows (ctx, P.begin (), P.end (), A); report << "PA = " << std::endl; BLAS3::write (ctx, report, A); BLAS3::scal (ctx, F.zero (), LPA); BLAS3::gemm (ctx, F.one (), L, A, F.zero (), LPA); report << "LPA = " << std::endl; BLAS3::write (ctx, report, LPA); report << "Computed rank = " << rank << std::endl; report << "Computed det = "; F.write (report, det); report << std::endl; // Trick to eliminate part below diagonal so that equality-check works Elimination<Ring> elim (ctx); elim.move_L (R, R); if (!BLAS3::equal (ctx, LPA, R)) { error << "ERROR: LPA != R" << std::endl; pass = false; } commentator.stop (MSG_STATUS (pass)); return pass; }
bool testPLUQ (const Ring &F, const char *text, Matrix &A) { std::ostringstream str; str << "Testing Elimination::pluq for " << text << " matrices" << std::ends; commentator.start (str.str ().c_str (), __FUNCTION__); std::ostream &report = commentator.report (Commentator::LEVEL_NORMAL, INTERNAL_DESCRIPTION); std::ostream &error = commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR); bool pass = true; Context<Ring> ctx (F); Elimination<Ring> elim (ctx); typename Matrix::ContainerType Acopy (A.rowdim (), A.coldim ()), L (A.rowdim (), A.rowdim ()); BLAS3::copy (ctx, A, Acopy); typename Elimination<Ring>::Permutation P, Q; size_t rank; typename Ring::Element det; report << "A = " << std::endl; BLAS3::write (ctx, report, A, FORMAT_PRETTY); elim.pluq (A, P, Q, rank, det); report << "L, U = " << std::endl; BLAS3::write (ctx, report, A, FORMAT_PRETTY); report << "P = "; BLAS1::write_permutation (report, P.begin (), P.end ()) << std::endl; report << "Q = "; BLAS1::write_permutation (report, Q.begin (), Q.end ()) << std::endl; BLAS3::scal (ctx, ctx.F.zero (), L); elim.move_L (L, A); report << "L = " << std::endl; BLAS3::write (ctx, report, L, FORMAT_PRETTY); report << "U = " << std::endl; BLAS3::write (ctx, report, A, FORMAT_PRETTY); BLAS3::trmm (ctx, F.one (), L, A, LowerTriangular, true); report << "LU = " << std::endl; BLAS3::write (ctx, report, A, FORMAT_PRETTY); BLAS3::permute_rows (ctx, P.begin (), P.end (), A); report << "PLU = " << std::endl; BLAS3::write (ctx, report, A); BLAS3::permute_cols (ctx, Q.begin (), Q.end (), A); report << "PLUQ = " << std::endl; BLAS3::write (ctx, report, A); report << "Computed rank = " << rank << std::endl; report << "Computed det = "; F.write (report, det); report << std::endl; if (!BLAS3::equal (ctx, A, Acopy)) { error << "PLUQ != A, not okay" << std::endl; BLAS3::axpy (ctx, ctx.F.minusOne (), A, Acopy); error << "Difference is:" << std::endl; BLAS3::write (ctx, error, Acopy); pass = false; } commentator.stop (MSG_STATUS (pass)); return pass; }