/* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2010 Thales group */ /* Authors: Johann Dréo */ #include #include #include #include #include #include #include #include "cholesky.h" void setformat( std::ostream& out ) { out << std::right; out << std::setfill(' '); out << std::setw( 5 + std::numeric_limits::digits10); out << std::setprecision(std::numeric_limits::digits10); out << std::setiosflags(std::ios_base::showpoint); } template std::string format(const MT& mat ) { std::ostringstream out; setformat(out); for( unsigned int i=0; i T round( T val, T prec = 1.0 ) { return (val > 0.0) ? floor(val * prec + 0.5) / prec : ceil(val * prec - 0.5) / prec ; } template bool equal( const MT& M1, const MT& M2, double prec /* = 1/std::numeric_limits::digits10 ???*/ ) { if( M1.size1() != M2.size1() || M1.size2() != M2.size2() ) { return false; } for( unsigned int i=0; i; algos["LLTa"] = new cholesky::LLTabs; algos["LLTz"] = new cholesky::LLTzero; algos["LDLT"] = new cholesky::LDLT; // init data structures on the same keys than given algorithms std::map fails; // triangular errors sum std::map > errors; for( typename AlgoMap::iterator ialgo = algos.begin(); ialgo != algos.end(); ++ialgo ) { fails[ialgo->first] = 0; errors[ialgo->first] = std::vector(); } for( unsigned int n=0; n S(M,N); for( unsigned int i=0; i(rand())/RAND_MAX; } } // a variance-covariance matrix of size N*N CovarMat V = ublas::prod( ublas::trans(S), S ); assert( V.size1() == N && V.size2() == N ); #ifndef NDEBUG if( R == 1 ) { std::cout << std::endl << "Covariance matrix:" << std::endl; std::cout << format(V) << std::endl; } #endif for( typename AlgoMap::iterator ialgo = algos.begin(); ialgo != algos.end(); ++ialgo ) { // The LLT algorithm can fail on a sqrt(x<0) and throw an error // we thus count the failures FactorMat L; try { L = (*ialgo->second)(V); CovarMat Vn = ublas::prod( L, ublas::trans(L) ); errors[ialgo->first].push_back( trigsum(error(V,Vn)) ); } catch( cholesky::NotDefinitePositive & error ) { fails[ialgo->first]++; #ifndef NDEBUG std::cout << "FAILED:\t" << error.what() << std::endl; #endif } } // for ialgo in algos } // for n in R for( typename AlgoMap::iterator ialgo = algos.begin(); ialgo != algos.end(); ++ialgo ) { std::string a = ialgo->first; std::cout << "\t" << a << ": (" << fails[a] << "/" << R << ")\t"; if( errors[a].size() == 0 ) { std::cout << "NAN"; } else { assert( errors[a].size() == R - fails[a] ); std::cout << sum(errors[a])/R; } std::cout << std::endl; } // for a in algos } int main(int argc, char** argv) { unsigned int seed = time(0); unsigned int M = 10; // sample size unsigned int N = 12; // variables number unsigned int F = 10; // range factor unsigned int R = 1; // nb of repetitions if( argc >= 2 ) { M = std::atoi(argv[1]); } if( argc >= 3 ) { N = std::atoi(argv[2]); } if( argc >= 4 ) { F = std::atoi(argv[3]); } if( argc >= 5 ) { R = std::atoi(argv[4]); } std::clog << "Usage: test [sample size] [variables number] [random range] [repetitions]" << std::endl; std::clog << "\tsample size = " << M << std::endl; std::clog << "\tmatrix size = " << N << std::endl; std::clog << "\trandom range = " << F << std::endl; std::clog << "\trepetitions = " << R << std::endl; std::clog << "Legend:" << std::endl; std::clog << "\tAlgo: (failures/runs)\tAverage error" << std::endl; std::cout << std::endl << "FLOAT" << std::endl; test(M,N,F,R,seed); std::cout << std::endl << "DOUBLE" << std::endl; test(M,N,F,R,seed); std::cout << std::endl << "LONG DOUBLE" << std::endl; test(M,N,F,R,seed); }