|
Teuchos Package Browser (Single Doxygen Collection) Version of the Day
|
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_ConfigDefs.hpp" 00039 #include "Teuchos_ScalarTraits.hpp" 00040 #include "Teuchos_TypeNameTraits.hpp" 00041 #include "Teuchos_FancyOStream.hpp" 00042 00043 00044 namespace Teuchos { 00045 00046 00051 inline void updateSuccess(const bool result, bool &success); 00052 00053 00058 inline const std::string passfail(const bool result); 00059 00060 00065 TEUCHOS_LIB_DLL_EXPORT const std::string passfail_with_location(const bool result, const std::string &file, const int lineNumber); 00066 00071 void showTestFailureLocation(bool); 00072 00073 00078 bool showTestFailureLocation(); 00079 00080 00085 template <bool hasMachineParameters, class Scalar> 00086 class RelErrSmallNumber { 00087 public: 00088 static Scalar smallNumber() 00089 { 00090 return ScalarTraits<Scalar>::ThisShouldNotCompile(); 00091 } 00092 }; 00093 00094 00099 template <class Scalar> 00100 class RelErrSmallNumber<false,Scalar> { 00101 public: 00102 static Scalar smallNumber() 00103 { 00104 return Scalar(1e-8); 00105 } 00106 }; 00107 00108 00113 template <class Scalar> 00114 class RelErrSmallNumber<true,Scalar> { 00115 public: 00116 static Scalar smallNumber() 00117 { 00118 return Teuchos::ScalarTraits<Scalar>::eps(); 00119 } 00120 }; 00121 00122 00127 template <class Scalar> 00128 Scalar defaultSmallNumber() 00129 { 00130 const bool hasMachineParameters = ScalarTraits<Scalar>::hasMachineParameters; 00131 return RelErrSmallNumber<hasMachineParameters,Scalar>::smallNumber(); 00132 } 00133 00134 00141 template <class Scalar> 00142 typename ScalarTraits<Scalar>::magnitudeType 00143 relErr( const Scalar &s1, const Scalar &s2 ); 00144 00145 00152 template<class Scalar> 00153 bool testRelErr( 00154 const std::string &v1_name, 00155 const Scalar &v1, 00156 const std::string &v2_name, 00157 const Scalar &v2, 00158 const std::string &maxRelErr_error_name, 00159 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error, 00160 const std::string &maxRelErr_warning_name, 00161 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning, 00162 const Ptr<std::ostream> &out 00163 ); 00164 00165 00177 template<class Array1, class Array2> 00178 bool compareArrays( 00179 const Array1 &a1, const std::string &a1_name, 00180 const Array2 &a2, const std::string &a2_name, 00181 Teuchos::FancyOStream &out 00182 ); 00183 00184 00197 template<class Array1, class Array2, class ScalarMag> 00198 bool compareFloatingArrays( 00199 const Array1 &a1, const std::string &a1_name, 00200 const Array2 &a2, const std::string &a2_name, 00201 const ScalarMag &tol, 00202 Teuchos::FancyOStream &out 00203 ); 00204 00205 00206 } // namespace Teuchos 00207 00208 00217 #define TEUCHOS_PASS_FAIL(RESULT) \ 00218 Teuchos::passfail_with_location((RESULT), __FILE__, __LINE__) 00219 00220 00227 #define TEUCHOS_ECHO( statement, out ) \ 00228 (out) << #statement ";\n"; \ 00229 statement; 00230 00237 #define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \ 00238 { \ 00239 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \ 00240 const bool l_result = (v1) == (v2); \ 00241 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00242 if (!l_result) (success) = false; \ 00243 } 00244 00251 #define TEUCHOS_TEST_ASSERT( v1, out, success ) \ 00252 { \ 00253 const bool l_result = v1; \ 00254 (out) << #v1" = "<<l_result<<" == true : "; \ 00255 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00256 if (!l_result) (success) = false; \ 00257 } 00258 00265 #define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \ 00266 { \ 00267 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \ 00268 const bool l_result = (v1) == (v2); \ 00269 if (!l_result) (success) = false; \ 00270 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00271 } 00272 00273 00280 #define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \ 00281 { \ 00282 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "<<Teuchos::toString(v2)<<" : "; \ 00283 const bool l_result = (v1) != (v2); \ 00284 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00285 if (!l_result) (success) = false; \ 00286 } 00287 00288 00295 #define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \ 00296 { \ 00297 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \ 00298 const bool l_result = (v1) != (v2); \ 00299 if (!l_result) (success) = false; \ 00300 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00301 } 00302 00303 00310 #define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \ 00311 { \ 00312 const bool l_result = Teuchos::testRelErr( \ 00313 #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \ 00314 if (!l_result) (success) = false; \ 00315 } 00316 00317 00327 #define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \ 00328 { \ 00329 (out) << #iter1" == "#iter2" = : "; \ 00330 const bool l_result = (iter1) == (iter2); \ 00331 if (!l_result) (success) = false; \ 00332 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00333 } 00334 00335 00342 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \ 00343 { \ 00344 const bool l_result = ( (a)[i] == (val) ); \ 00345 if (!l_result) (success) = false; \ 00346 if (printPass || !(l_result)) { \ 00347 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \ 00348 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00349 } \ 00350 } 00351 00352 00359 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \ 00360 { \ 00361 const bool l_result = ( (a)[i] != (val) ); \ 00362 if (!l_result) (success) = false; \ 00363 if (printPass || !(l_result)) { \ 00364 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \ 00365 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00366 } \ 00367 } 00368 00369 00377 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \ 00378 { \ 00379 std::ostringstream a_i_str; \ 00380 a_i_str <<#a<<"("<<i<<","<<j<<")"; \ 00381 const bool l_result = Teuchos::testRelErr( \ 00382 a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \ 00383 (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \ 00384 if (!l_result) (success) = false; \ 00385 } 00386 00387 00394 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \ 00395 { \ 00396 const bool l_result = ( (a)(i,j) == (val) ); \ 00397 if (!l_result) (success) = false; \ 00398 if (printPass || !(l_result)) { \ 00399 out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \ 00400 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00401 } \ 00402 } 00403 00404 00411 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \ 00412 { \ 00413 out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \ 00414 const bool l_result = (v1) comp (v2); \ 00415 if (!l_result) (success) = false; \ 00416 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00417 } 00418 00419 00426 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success ) \ 00427 try { \ 00428 (out) << "Test that code {"#code";} throws " \ 00429 <<Teuchos::TypeNameTraits<ExceptType>::name()<<": "; \ 00430 code; \ 00431 (success) = false; \ 00432 (out) << "failed\n"; \ 00433 } \ 00434 catch (const ExceptType& except) { \ 00435 out << "passed\n"; \ 00436 out << "\nException message for expected exception:\n\n"; \ 00437 { \ 00438 Teuchos::OSTab l_tab(out); \ 00439 out << except.what() << "\n\n"; \ 00440 } \ 00441 } 00442 00443 00450 #define TEUCHOS_TEST_NOTHROW( code, out, success ) \ 00451 try { \ 00452 (out) << "Test that code {"#code";} does not throw : "; \ 00453 code; \ 00454 (out) << "passes\n"; \ 00455 } \ 00456 catch (...) { \ 00457 (success) = false; \ 00458 out << "failed\n"; \ 00459 } 00460 00461 00462 // 00463 // Implementations 00464 // 00465 00466 00467 inline 00468 void Teuchos::updateSuccess(const bool result, bool &success) 00469 { 00470 if (!result) success = false; 00471 } 00472 00473 00474 inline 00475 const std::string 00476 Teuchos::passfail(const bool result) 00477 { 00478 if (!result) 00479 return "FAILED"; 00480 return "passed"; 00481 } 00482 00483 00484 template <class Scalar> 00485 typename Teuchos::ScalarTraits<Scalar>::magnitudeType 00486 Teuchos::relErr( const Scalar &s1, const Scalar &s2 ) 00487 { 00488 typedef Teuchos::ScalarTraits<Scalar> ST; 00489 return 00490 ST::magnitude( s1 - s2 ) 00491 / ( 00492 ST::magnitude( 00493 RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber() 00494 ) 00495 + std::max( ST::magnitude(s1), ST::magnitude(s1) ) 00496 ); 00497 } 00498 00499 00500 template<class Scalar> 00501 bool Teuchos::testRelErr( 00502 const std::string &v1_name, 00503 const Scalar &v1, 00504 const std::string &v2_name, 00505 const Scalar &v2, 00506 const std::string &maxRelErr_error_name, 00507 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error, 00508 const std::string &maxRelErr_warning_name, 00509 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning, 00510 const Ptr<std::ostream> &out 00511 ) 00512 { 00513 using std::endl; 00514 typedef ScalarTraits<Scalar> ST; 00515 typedef typename ST::magnitudeType ScalarMag; 00516 typedef ScalarTraits<ScalarMag> SMT; 00517 const ScalarMag rel_err = relErr( v1, v2 ); 00518 const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error) 00519 && rel_err <= maxRelErr_error ); 00520 if (!is_null(out)) { 00521 *out 00522 << endl 00523 << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n" 00524 << " = rel_err(" << v1 << ", " << v2 << ") " 00525 << "= " << rel_err << endl 00526 << " <= " << maxRelErr_error_name 00527 << " = " << maxRelErr_error << " : " << passfail(success) << endl; 00528 if( success && rel_err >= maxRelErr_warning ) { 00529 *out 00530 << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n" 00531 << " = rel_err(" << v1 << ", " << v2 << ") " 00532 << "= " << rel_err << endl 00533 << " >= " << maxRelErr_warning_name 00534 << " = " << maxRelErr_warning << "!\n"; 00535 } 00536 } 00537 return success; 00538 } 00539 00540 00541 template<class Array1, class Array2> 00542 bool Teuchos::compareArrays( 00543 const Array1 &a1, const std::string &a1_name, 00544 const Array2 &a2, const std::string &a2_name, 00545 Teuchos::FancyOStream &out 00546 ) 00547 { 00548 using Teuchos::as; 00549 bool success = true; 00550 00551 out << "Comparing " << a1_name << " == " << a2_name << " ... "; 00552 00553 const int n = a1.size(); 00554 00555 // Compare sizes 00556 if (as<int>(a2.size()) != n) { 00557 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 00558 << a2_name<<".size() = "<<a2.size()<<" : failed!\n"; 00559 return false; 00560 } 00561 00562 // Compare elements 00563 for( int i = 0; i < n; ++i ) { 00564 const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const 00565 if (!result) { 00566 out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == " 00567 << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n"; 00568 success = false; 00569 } 00570 } 00571 if (success) { 00572 out << "passed\n"; 00573 } 00574 00575 return success; 00576 00577 } 00578 00579 00580 template<class Array1, class Array2, class ScalarMag> 00581 bool Teuchos::compareFloatingArrays( 00582 const Array1 &a1, const std::string &a1_name, 00583 const Array2 &a2, const std::string &a2_name, 00584 const ScalarMag &tol, 00585 Teuchos::FancyOStream &out 00586 ) 00587 { 00588 using Teuchos::as; 00589 bool success = true; 00590 00591 out << "Comparing " << a1_name << " == " << a2_name << " ... "; 00592 00593 const int n = a1.size(); 00594 00595 // Compare sizes 00596 if (as<int>(a2.size()) != n) { 00597 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 00598 << a2_name<<".size() = "<<a2.size()<<" : failed!\n"; 00599 return false; 00600 } 00601 00602 // Compare elements 00603 for( int i = 0; i < n; ++i ) { 00604 const ScalarMag err = relErr( a1[i], a2[i] ); 00605 if ( err > tol ) { 00606 out 00607 <<"\nError, relErr("<<a1_name<<"["<<i<<"]," 00608 <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = " 00609 <<err<<" <= tol = "<<tol<<": failed!\n"; 00610 success = false; 00611 } 00612 } 00613 if (success) { 00614 out << "passed\n"; 00615 } 00616 00617 return success; 00618 00619 } 00620 00621 00622 #endif // TEUCHOS_TESTING_HELPERS_HPP
1.7.4