00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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 }
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
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
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
00526 for( int i = 0; i < n; ++i ) {
00527 const bool result = ( a1[i] == a2[i] );
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
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
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