/** \file ex_trisolve.cpp \brief main routines. -*- c++ -*- */ /*************************************************************************** - begin : 2006-11-03 - copyright : (C) 2006 by Gunter Winkler - email : guwi17@gmx.de ***************************************************************************/ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // misc. boost includes #include #include "trisolve.h" // boost ublas includes #include #include #include #include #include #include // system includes #include #include #ifndef NDEBUG const size_t default_size = 10; #else const size_t default_size = 100; #endif template void setup_L(M& A, bool unit=false) { using namespace boost::numeric::ublas; if (unit) A = triangular_adaptor,unit_lower>( scalar_matrix(A.size1(), A.size2(), -0.2) ); else A = triangular_adaptor,strict_lower>( scalar_matrix(A.size1(), A.size2(), -0.2) ); } template void setup_U(M& A, bool unit=false) { using namespace boost::numeric::ublas; if (unit) A = triangular_adaptor,unit_upper>( scalar_matrix(A.size1(), A.size2(), 0.2) ); else A = triangular_adaptor,strict_upper>( scalar_matrix(A.size1(), A.size2(), 0.2) ); } template void setup_x(boost::numeric::ublas::vector_expression& x) { for (size_t i=0; i void setup_x(boost::numeric::ublas::matrix_expression& x) { double t = 1.0 / sqrt(x().size1()); for (size_t i=0; i(x().size2(), t ); } } // this is no real norm -> its only useful for this test template double norm_2(const boost::numeric::ublas::matrix_expression& A) { double result=0.0; for (size_t k=0; k double norm_inf_2(const boost::numeric::ublas::matrix_expression& A) { double result=0.0; for (size_t k=0; k double norm_inf_2(const boost::numeric::ublas::vector_expression& A) { return norm_inf(A()); } template bool do_test(const boost::numeric::ublas::matrix_expression& A, VECTOR& x, const VECTOR& rhs) { using namespace boost::numeric::ublas; double eps = std::numeric_limits::epsilon(); x=rhs; boost::timer t; t.restart(); inplace_solve(A(), x, typename TRI::triangular_type()); double time = t.elapsed(); VECTOR resid = (rhs - prod(A(),x)); if ( TRI::one(1,1) ) resid -= x; double error = norm_2(resid)/norm_2(rhs); #ifndef NDEBUG std::cerr << "||b-Ax|| = " << norm_2(resid) << ", " << norm_inf(resid) << std::endl; std::cerr << "||b|| = " << norm_2(rhs) << ", " << norm_inf(rhs) << std::endl; std::cerr << "||x|| = " << norm_2(x) << ", " << norm_inf(x) << std::endl; #endif double limit = (A().size1()*eps); if (error <= limit) { std::cout << " (" << time << " sec)" << " relative error " << error << std::endl; return true; } else { std::cout << " (" << time << " sec)" << " relative error " << error << " greater than threshold " << limit << std::endl; #ifndef NDEBUG std::cerr << " rhs = " << rhs << "\n"; std::cerr << " x = " << x << "\n"; std::cerr << " res = " << resid << "\n"; #endif return false; } } template < class MATRIX > void run_solver_tests(size_t size, size_t nrhs=5) { using namespace boost::numeric::ublas; typedef MATRIX LMAT; typedef MATRIX UMAT; LMAT L(size,size); UMAT U(size,size); L.clear(); U.clear(); vector b(size); vector x(size); vector x2(size); matrix X(size,nrhs); matrix B(size,nrhs); setup_L(L,false); setup_U(U,false); setup_x(x); std::cout << "vec unit lower: "; b = x + prod(L, x); std::cerr << do_test(L,x,b); setup_x(x); std::cout << "vec unit upper: "; b = x + prod(U, x); std::cerr << do_test(U,x,b); setup_x(X); std::cout << "mat unit lower: "; B = X + prod(L, X); std::cerr << do_test(L,X,B); setup_x(X); std::cout << "mat unit upper: "; B = X + prod(U, X); std::cerr << do_test(U,X,B); L.clear(); U.clear(); setup_L(L,true); setup_U(U,true); setup_x(x); std::cout << "vec lower: "; b = prod(L,x); std::cerr << do_test(L,x,b); setup_x(x); std::cout << "vec upper: "; b = prod(U,x); std::cerr << do_test(U,x,b); setup_x(X); std::cout << "mat lower: "; B = prod(L, X); std::cerr << do_test(L,X,B); setup_x(X); std::cout << "mat upper: "; B = prod(U, X); std::cerr << do_test(U,X,B); } int main(int argc, char *argv[]) { typedef size_t size_type; size_type size = default_size; if (argc > 1) size = ::atoi (argv [1]); std::cout << "size " << size << std::endl; using namespace boost::numeric::ublas; std::cout << "dense column major\n"; run_solver_tests< matrix >(size); std::cout << "dense row major\n"; run_solver_tests< matrix >(size); std::cout << "compressed column_major major\n"; run_solver_tests< compressed_matrix >(size); std::cout << "compressed row major\n"; run_solver_tests< compressed_matrix >(size); std::cout << "mapped column_major major\n"; run_solver_tests< mapped_matrix >(size); std::cout << "mapped row major\n"; run_solver_tests< mapped_matrix >(size); return EXIT_SUCCESS; }