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 const std::string passfail(const bool result);
00051 
00052 
00057 template <bool hasMachineParameters, class Scalar>
00058 class RelErrSmallNumber {
00059 public:
00060   static Scalar smallNumber()
00061     {
00062       return ScalarTraits<Scalar>::ThisShouldNotCompile();
00063     }
00064 };
00065 
00066 
00071 template <class Scalar>
00072 class RelErrSmallNumber<false,Scalar> {
00073 public:
00074   static Scalar smallNumber()
00075     {
00076       return Scalar(1e-8);
00077     }
00078 };
00079 
00080 
00085 template <class Scalar>
00086 class RelErrSmallNumber<true,Scalar> {
00087 public:
00088   static Scalar smallNumber()
00089     {
00090       return Teuchos::ScalarTraits<Scalar>::eps();
00091     }
00092 };
00093 
00094 
00099 template <class Scalar>
00100 Scalar defaultSmallNumber()
00101 {
00102   const bool hasMachineParameters = ScalarTraits<Scalar>::hasMachineParameters;
00103   return RelErrSmallNumber<hasMachineParameters,Scalar>::smallNumber();
00104 }
00105 
00106 
00113 template <class Scalar>
00114 typename ScalarTraits<Scalar>::magnitudeType
00115 relErr( const Scalar &s1, const Scalar &s2 );
00116 
00117 
00124 template<class Scalar>
00125 bool testRelErr(
00126   const std::string &v1_name,
00127   const Scalar &v1,
00128   const std::string &v2_name,
00129   const Scalar &v2,
00130   const std::string &maxRelErr_error_name,
00131   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00132   const std::string &maxRelErr_warning_name,
00133   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00134   const Ptr<std::ostream> &out
00135   );
00136 
00137 
00149 template<class Array1, class Array2>
00150 bool compareArrays(
00151   const Array1 &a1, const std::string &a1_name,
00152   const Array2 &a2, const std::string &a2_name,
00153   Teuchos::FancyOStream &out
00154   );
00155 
00156 
00169 template<class Array1, class Array2, class ScalarMag>
00170 bool compareFloatingArrays(
00171   const Array1 &a1, const std::string &a1_name,
00172   const Array2 &a2, const std::string &a2_name,
00173   const ScalarMag &tol,
00174   Teuchos::FancyOStream &out
00175   );
00176 
00177 
00178 } // namespace Teuchos
00179 
00180 
00187 #define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \
00188   { \
00189     (out) << #v1" = "<<(v1)<<" == "<<(v2)<<" : "; \
00190     const bool l_result = (v1) == (v2); \
00191     (out) << Teuchos::passfail(l_result) << "\n"; \
00192     if (!l_result) (success) = false; \
00193   }
00194 
00195 
00202 #define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \
00203   { \
00204     (out) << #v1" = "<<(v1)<<" == "#v2" = "<<(v2)<<" : "; \
00205     const bool l_result = (v1) == (v2); \
00206     if (!l_result) (success) = false; \
00207     (out) << Teuchos::passfail(l_result) << "\n"; \
00208   }
00209 
00210 
00217 #define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \
00218   { \
00219     (out) << #v1" = "<<(v1)<<" != "<<(v2)<<" : "; \
00220     const bool l_result = (v1) != (v2); \
00221     (out) << Teuchos::passfail(l_result) << "\n"; \
00222     if (!l_result) (success) = false; \
00223   }
00224 
00225 
00232 #define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \
00233   { \
00234     (out) << #v1" = "<<(v1)<<" != "#v2" = "<<(v2)<<" : "; \
00235     const bool l_result = (v1) != (v2); \
00236     if (!l_result) (success) = false; \
00237     (out) << Teuchos::passfail(l_result) << "\n"; \
00238   }
00239 
00240 
00247 #define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \
00248   { \
00249     const bool l_result = Teuchos::testRelErr( \
00250       #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \
00251     if (!l_result) (success) = false; \
00252   }
00253 
00254 
00264 #define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \
00265   { \
00266     (out) << #iter1" == "#iter2" =  : "; \
00267     const bool l_result = (iter1) == (iter2); \
00268     if (!l_result) (success) = false; \
00269     (out) << Teuchos::passfail(l_result) << "\n"; \
00270   }
00271 
00272 
00279 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
00280   { \
00281     const bool l_result = ( (a)[i] == (val) ); \
00282     if (!l_result) (success) = false; \
00283     if (printPass || !(l_result)) { \
00284       out << #a"["<<i<<"] = " << (a)[i] << " == "#val" = " << (val) \
00285           << " : " << Teuchos::passfail(l_result) << "\n"; \
00286     } \
00287   }
00288 
00289 
00296 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
00297   { \
00298     const bool l_result = ( (a)[i] != (val) ); \
00299     if (!l_result) (success) = false; \
00300     if (printPass || !(l_result)) { \
00301       out << #a"["<<i<<"] = " << (a)[i] << " != "#val" = " << (val) \
00302           << " : " << Teuchos::passfail(l_result) << "\n"; \
00303     } \
00304   }
00305 
00306 
00314 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
00315   { \
00316     std::ostringstream a_i_str; \
00317     a_i_str <<#a<<"("<<i<<","<<j<<")"; \
00318     const bool l_result = Teuchos::testRelErr( \
00319       a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
00320       (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
00321     if (!l_result) (success) = false; \
00322   }
00323 
00324 
00331 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
00332   { \
00333     const bool l_result = ( (a)(i,j) == (val) ); \
00334     if (!l_result) (success) = false; \
00335     if (printPass || !(l_result)) { \
00336       out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
00337           << " : " << Teuchos::passfail(l_result) << "\n"; \
00338     } \
00339   }
00340 
00341 
00348 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
00349   { \
00350     out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
00351     const bool l_result = (v1) comp (v2); \
00352     if (!l_result) (success) = false; \
00353     (out) << Teuchos::passfail(l_result) << "\n"; \
00354   }
00355 
00356 
00363 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success  ) \
00364   try { \
00365     (out) << "Test that code {"#code";} throws " \
00366           <<Teuchos::TypeNameTraits<ExceptType>::name()<<": "; \
00367     code; \
00368     (success) = false; \
00369     (out) << "failed\n"; \
00370   } \
00371   catch (const ExceptType& except) { \
00372     out << "passed\n"; \
00373     out << "\nException message for expected exception:\n\n"; \
00374     { \
00375       Teuchos::OSTab tab(out); \
00376       out << except.what() << "\n\n"; \
00377     } \
00378   }
00379 
00380 
00387 #define TEUCHOS_TEST_NOTHROW( code, out, success  ) \
00388   try { \
00389     (out) << "Test that code {"#code";} does not throw : "; \
00390     code; \
00391     (out) << "passes\n"; \
00392   } \
00393   catch (...) { \
00394     (success) = false; \
00395     out << "failed\n"; \
00396   }
00397 
00398 
00399 //
00400 // Implementations
00401 //
00402 
00403 
00404 inline
00405 const std::string
00406 Teuchos::passfail(const bool result)
00407 {
00408   if (!result)
00409     return "failed";
00410   return "passed";
00411 }
00412 
00413 
00414 template <class Scalar>
00415 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00416 Teuchos::relErr( const Scalar &s1, const Scalar &s2 )
00417 {
00418   typedef Teuchos::ScalarTraits<Scalar> ST;
00419   return
00420     ST::magnitude( s1 - s2 )
00421     / (
00422       ST::magnitude(
00423         RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00424         )
00425       + std::max( ST::magnitude(s1), ST::magnitude(s1) )
00426       );
00427 }
00428 
00429 
00430 template<class Scalar>
00431 bool Teuchos::testRelErr(
00432   const std::string &v1_name,
00433   const Scalar &v1,
00434   const std::string &v2_name,
00435   const Scalar &v2,
00436   const std::string &maxRelErr_error_name,
00437   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00438   const std::string &maxRelErr_warning_name,
00439   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00440   const Ptr<std::ostream> &out
00441   )
00442 {
00443   using std::endl;
00444   typedef ScalarTraits<Scalar> ST;
00445   typedef typename ST::magnitudeType ScalarMag;
00446   typedef ScalarTraits<ScalarMag> SMT;
00447   const ScalarMag rel_err = relErr( v1, v2 );
00448   const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
00449     && rel_err <= maxRelErr_error );
00450   if (!is_null(out)) {
00451     *out
00452       << endl
00453       << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n"
00454       << "       = rel_err(" << v1 << ", " << v2 << ") "
00455       << "= " << rel_err << endl
00456       << "         <= " << maxRelErr_error_name
00457       << " = " << maxRelErr_error << " : " << passfail(success) << endl;
00458     if( success && rel_err >= maxRelErr_warning ) {
00459       *out
00460         << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n"
00461         << "       = rel_err(" << v1 << ", " << v2 << ") "
00462         << "= " << rel_err << endl
00463         << "         >= " << maxRelErr_warning_name
00464         << " = " << maxRelErr_warning << "!\n";
00465     }
00466   }
00467   return success;
00468 }
00469 
00470 
00471 template<class Array1, class Array2>
00472 bool Teuchos::compareArrays(
00473   const Array1 &a1, const std::string &a1_name,
00474   const Array2 &a2, const std::string &a2_name,
00475   Teuchos::FancyOStream &out
00476   )
00477 {
00478   using Teuchos::as;
00479   bool success = true;
00480 
00481   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00482 
00483   const int n = a1.size();
00484 
00485   // Compare sizes
00486   if (as<int>(a2.size()) != n) {
00487     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00488         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00489     return false;
00490   }
00491   
00492   // Compare elements
00493   for( int i = 0; i < n; ++i ) {
00494     const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
00495     if (!result) {
00496       out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
00497           << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
00498       success = false;
00499     }
00500   }
00501   if (success) {
00502     out << "passed\n";
00503   }
00504 
00505   return success;
00506 
00507 }
00508 
00509 
00510 template<class Array1, class Array2, class ScalarMag>
00511 bool Teuchos::compareFloatingArrays(
00512   const Array1 &a1, const std::string &a1_name,
00513   const Array2 &a2, const std::string &a2_name,
00514   const ScalarMag &tol,
00515   Teuchos::FancyOStream &out
00516   )
00517 {
00518   using Teuchos::as;
00519   bool success = true;
00520 
00521   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00522 
00523   const int n = a1.size();
00524 
00525   // Compare sizes
00526   if (as<int>(a2.size()) != n) {
00527     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00528         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00529     return false;
00530   }
00531   
00532   // Compare elements
00533   for( int i = 0; i < n; ++i ) {
00534     const ScalarMag err = relErr( a1[i], a2[i] );
00535     if ( err > tol ) {
00536       out
00537         <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
00538         <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
00539         <<err<<" <= tol = "<<tol<<": failed!\n";
00540       success = false;
00541     }
00542   }
00543   if (success) {
00544     out << "passed\n";
00545   }
00546 
00547   return success;
00548 
00549 }
00550 
00551 
00552 #endif  // TEUCHOS_TESTING_HELPERS_HPP

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