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 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 }
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
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
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
00493 for( int i = 0; i < n; ++i ) {
00494 const bool result = ( a1[i] == a2[i] );
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
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
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