Teuchos_TestingHelpers.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef TEUCHOS_TESTING_HELPERS_HPP
00030 #define TEUCHOS_TESTING_HELPERS_HPP
00031 
00032 
00038 #include "Teuchos_ScalarTraits.hpp"
00039 #include "Teuchos_TypeNameTraits.hpp"
00040 #include "Teuchos_FancyOStream.hpp"
00041 
00042 
00043 namespace Teuchos {
00044 
00045 
00050 inline void updateSuccess(const bool result, bool &success);
00051 
00052 
00057 inline const std::string passfail(const bool result);
00058 
00059 
00064 template <bool hasMachineParameters, class Scalar>
00065 class RelErrSmallNumber {
00066 public:
00067   static Scalar smallNumber()
00068     {
00069       return ScalarTraits<Scalar>::ThisShouldNotCompile();
00070     }
00071 };
00072 
00073 
00078 template <class Scalar>
00079 class RelErrSmallNumber<false,Scalar> {
00080 public:
00081   static Scalar smallNumber()
00082     {
00083       return Scalar(1e-8);
00084     }
00085 };
00086 
00087 
00092 template <class Scalar>
00093 class RelErrSmallNumber<true,Scalar> {
00094 public:
00095   static Scalar smallNumber()
00096     {
00097       return Teuchos::ScalarTraits<Scalar>::eps();
00098     }
00099 };
00100 
00101 
00106 template <class Scalar>
00107 Scalar defaultSmallNumber()
00108 {
00109   const bool hasMachineParameters = ScalarTraits<Scalar>::hasMachineParameters;
00110   return RelErrSmallNumber<hasMachineParameters,Scalar>::smallNumber();
00111 }
00112 
00113 
00120 template <class Scalar>
00121 typename ScalarTraits<Scalar>::magnitudeType
00122 relErr( const Scalar &s1, const Scalar &s2 );
00123 
00124 
00131 template<class Scalar>
00132 bool testRelErr(
00133   const std::string &v1_name,
00134   const Scalar &v1,
00135   const std::string &v2_name,
00136   const Scalar &v2,
00137   const std::string &maxRelErr_error_name,
00138   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00139   const std::string &maxRelErr_warning_name,
00140   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00141   const Ptr<std::ostream> &out
00142   );
00143 
00144 
00156 template<class Array1, class Array2>
00157 bool compareArrays(
00158   const Array1 &a1, const std::string &a1_name,
00159   const Array2 &a2, const std::string &a2_name,
00160   Teuchos::FancyOStream &out
00161   );
00162 
00163 
00176 template<class Array1, class Array2, class ScalarMag>
00177 bool compareFloatingArrays(
00178   const Array1 &a1, const std::string &a1_name,
00179   const Array2 &a2, const std::string &a2_name,
00180   const ScalarMag &tol,
00181   Teuchos::FancyOStream &out
00182   );
00183 
00184 
00185 } // namespace Teuchos
00186 
00187 
00194 #define TEUCHOS_ECHO( statement, out ) \
00195   (out) << #statement ";\n"; \
00196   statement;
00197 
00204 #define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \
00205   { \
00206     (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \
00207     const bool l_result = (v1) == (v2); \
00208     (out) << Teuchos::passfail(l_result) << "\n"; \
00209     if (!l_result) (success) = false; \
00210   }
00211 
00218 #define TEUCHOS_TEST_ASSERT( v1, out, success ) \
00219   TEUCHOS_TEST_EQUALITY_CONST( v1, true, out, success )
00220 
00221 
00228 #define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \
00229   { \
00230     (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \
00231     const bool l_result = (v1) == (v2); \
00232     if (!l_result) (success) = false; \
00233     (out) << Teuchos::passfail(l_result) << "\n"; \
00234   }
00235 
00236 
00243 #define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \
00244   { \
00245     (out) << #v1" = "<<Teuchos::toString(v1)<<" != "<<Teuchos::toString(v2)<<" : "; \
00246     const bool l_result = (v1) != (v2); \
00247     (out) << Teuchos::passfail(l_result) << "\n"; \
00248     if (!l_result) (success) = false; \
00249   }
00250 
00251 
00258 #define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \
00259   { \
00260     (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \
00261     const bool l_result = (v1) != (v2); \
00262     if (!l_result) (success) = false; \
00263     (out) << Teuchos::passfail(l_result) << "\n"; \
00264   }
00265 
00266 
00273 #define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \
00274   { \
00275     const bool l_result = Teuchos::testRelErr( \
00276       #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \
00277     if (!l_result) (success) = false; \
00278   }
00279 
00280 
00290 #define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \
00291   { \
00292     (out) << #iter1" == "#iter2" =  : "; \
00293     const bool l_result = (iter1) == (iter2); \
00294     if (!l_result) (success) = false; \
00295     (out) << Teuchos::passfail(l_result) << "\n"; \
00296   }
00297 
00298 
00305 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
00306   { \
00307     const bool l_result = ( (a)[i] == (val) ); \
00308     if (!l_result) (success) = false; \
00309     if (printPass || !(l_result)) { \
00310       out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \
00311           << " : " << Teuchos::passfail(l_result) << "\n"; \
00312     } \
00313   }
00314 
00315 
00322 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
00323   { \
00324     const bool l_result = ( (a)[i] != (val) ); \
00325     if (!l_result) (success) = false; \
00326     if (printPass || !(l_result)) { \
00327       out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \
00328           << " : " << Teuchos::passfail(l_result) << "\n"; \
00329     } \
00330   }
00331 
00332 
00340 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
00341   { \
00342     std::ostringstream a_i_str; \
00343     a_i_str <<#a<<"("<<i<<","<<j<<")"; \
00344     const bool l_result = Teuchos::testRelErr( \
00345       a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
00346       (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
00347     if (!l_result) (success) = false; \
00348   }
00349 
00350 
00357 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
00358   { \
00359     const bool l_result = ( (a)(i,j) == (val) ); \
00360     if (!l_result) (success) = false; \
00361     if (printPass || !(l_result)) { \
00362       out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
00363           << " : " << Teuchos::passfail(l_result) << "\n"; \
00364     } \
00365   }
00366 
00367 
00374 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
00375   { \
00376     out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
00377     const bool l_result = (v1) comp (v2); \
00378     if (!l_result) (success) = false; \
00379     (out) << Teuchos::passfail(l_result) << "\n"; \
00380   }
00381 
00382 
00389 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success  ) \
00390   try { \
00391     (out) << "Test that code {"#code";} throws " \
00392           <<Teuchos::TypeNameTraits<ExceptType>::name()<<": "; \
00393     code; \
00394     (success) = false; \
00395     (out) << "failed\n"; \
00396   } \
00397   catch (const ExceptType& except) { \
00398     out << "passed\n"; \
00399     out << "\nException message for expected exception:\n\n"; \
00400     { \
00401       Teuchos::OSTab l_tab(out); \
00402       out << except.what() << "\n\n"; \
00403     } \
00404   }
00405 
00406 
00413 #define TEUCHOS_TEST_NOTHROW( code, out, success  ) \
00414   try { \
00415     (out) << "Test that code {"#code";} does not throw : "; \
00416     code; \
00417     (out) << "passes\n"; \
00418   } \
00419   catch (...) { \
00420     (success) = false; \
00421     out << "failed\n"; \
00422   }
00423 
00424 
00425 //
00426 // Implementations
00427 //
00428 
00429 
00430 inline
00431 void Teuchos::updateSuccess(const bool result, bool &success)
00432 {
00433   if (!result) success = false;
00434 }
00435 
00436 
00437 inline
00438 const std::string
00439 Teuchos::passfail(const bool result)
00440 {
00441   if (!result)
00442     return "failed";
00443   return "passed";
00444 }
00445 
00446 
00447 template <class Scalar>
00448 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00449 Teuchos::relErr( const Scalar &s1, const Scalar &s2 )
00450 {
00451   typedef Teuchos::ScalarTraits<Scalar> ST;
00452   return
00453     ST::magnitude( s1 - s2 )
00454     / (
00455       ST::magnitude(
00456         RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00457         )
00458       + std::max( ST::magnitude(s1), ST::magnitude(s1) )
00459       );
00460 }
00461 
00462 
00463 template<class Scalar>
00464 bool Teuchos::testRelErr(
00465   const std::string &v1_name,
00466   const Scalar &v1,
00467   const std::string &v2_name,
00468   const Scalar &v2,
00469   const std::string &maxRelErr_error_name,
00470   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00471   const std::string &maxRelErr_warning_name,
00472   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00473   const Ptr<std::ostream> &out
00474   )
00475 {
00476   using std::endl;
00477   typedef ScalarTraits<Scalar> ST;
00478   typedef typename ST::magnitudeType ScalarMag;
00479   typedef ScalarTraits<ScalarMag> SMT;
00480   const ScalarMag rel_err = relErr( v1, v2 );
00481   const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
00482     && rel_err <= maxRelErr_error );
00483   if (!is_null(out)) {
00484     *out
00485       << endl
00486       << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n"
00487       << "       = rel_err(" << v1 << ", " << v2 << ") "
00488       << "= " << rel_err << endl
00489       << "         <= " << maxRelErr_error_name
00490       << " = " << maxRelErr_error << " : " << passfail(success) << endl;
00491     if( success && rel_err >= maxRelErr_warning ) {
00492       *out
00493         << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n"
00494         << "       = rel_err(" << v1 << ", " << v2 << ") "
00495         << "= " << rel_err << endl
00496         << "         >= " << maxRelErr_warning_name
00497         << " = " << maxRelErr_warning << "!\n";
00498     }
00499   }
00500   return success;
00501 }
00502 
00503 
00504 template<class Array1, class Array2>
00505 bool Teuchos::compareArrays(
00506   const Array1 &a1, const std::string &a1_name,
00507   const Array2 &a2, const std::string &a2_name,
00508   Teuchos::FancyOStream &out
00509   )
00510 {
00511   using Teuchos::as;
00512   bool success = true;
00513 
00514   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00515 
00516   const int n = a1.size();
00517 
00518   // Compare sizes
00519   if (as<int>(a2.size()) != n) {
00520     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00521         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00522     return false;
00523   }
00524   
00525   // Compare elements
00526   for( int i = 0; i < n; ++i ) {
00527     const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
00528     if (!result) {
00529       out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
00530           << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
00531       success = false;
00532     }
00533   }
00534   if (success) {
00535     out << "passed\n";
00536   }
00537 
00538   return success;
00539 
00540 }
00541 
00542 
00543 template<class Array1, class Array2, class ScalarMag>
00544 bool Teuchos::compareFloatingArrays(
00545   const Array1 &a1, const std::string &a1_name,
00546   const Array2 &a2, const std::string &a2_name,
00547   const ScalarMag &tol,
00548   Teuchos::FancyOStream &out
00549   )
00550 {
00551   using Teuchos::as;
00552   bool success = true;
00553 
00554   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00555 
00556   const int n = a1.size();
00557 
00558   // Compare sizes
00559   if (as<int>(a2.size()) != n) {
00560     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00561         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00562     return false;
00563   }
00564   
00565   // Compare elements
00566   for( int i = 0; i < n; ++i ) {
00567     const ScalarMag err = relErr( a1[i], a2[i] );
00568     if ( err > tol ) {
00569       out
00570         <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
00571         <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
00572         <<err<<" <= tol = "<<tol<<": failed!\n";
00573       success = false;
00574     }
00575   }
00576   if (success) {
00577     out << "passed\n";
00578   }
00579 
00580   return success;
00581 
00582 }
00583 
00584 
00585 #endif  // TEUCHOS_TESTING_HELPERS_HPP

Generated on Wed May 12 21:24:41 2010 for Teuchos - Trilinos Tools Package by  doxygen 1.4.7