|
Teuchos - Trilinos Tools Package
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 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #ifndef TEUCHOS_TESTING_HELPERS_HPP 00043 #define TEUCHOS_TESTING_HELPERS_HPP 00044 00045 00051 #include "Teuchos_ConfigDefs.hpp" 00052 #include "Teuchos_ScalarTraits.hpp" 00053 #include "Teuchos_TypeNameTraits.hpp" 00054 #include "Teuchos_FancyOStream.hpp" 00055 00056 00057 namespace Teuchos { 00058 00059 00064 inline void updateSuccess(const bool result, bool &success); 00065 00066 00071 inline const std::string passfail(const bool result); 00072 00073 00078 TEUCHOSCORE_LIB_DLL_EXPORT const std::string passfail_with_location(const bool result, const std::string &file, const int lineNumber); 00079 00084 void showTestFailureLocation(bool); 00085 00086 00091 bool showTestFailureLocation(); 00092 00093 00098 template <bool hasMachineParameters, class Scalar> 00099 class RelErrSmallNumber { 00100 public: 00101 static Scalar smallNumber() 00102 { 00103 return ScalarTraits<Scalar>::ThisShouldNotCompile(); 00104 } 00105 }; 00106 00107 00112 template <class Scalar> 00113 class RelErrSmallNumber<false,Scalar> { 00114 public: 00115 static Scalar smallNumber() 00116 { 00117 return Scalar(1e-8); 00118 } 00119 }; 00120 00121 00126 template <class Scalar> 00127 class RelErrSmallNumber<true,Scalar> { 00128 public: 00129 static Scalar smallNumber() 00130 { 00131 return Teuchos::ScalarTraits<Scalar>::eps(); 00132 } 00133 }; 00134 00135 00140 template <class Scalar> 00141 Scalar defaultSmallNumber() 00142 { 00143 const bool hasMachineParameters = ScalarTraits<Scalar>::hasMachineParameters; 00144 return RelErrSmallNumber<hasMachineParameters,Scalar>::smallNumber(); 00145 } 00146 00147 00154 template <class Scalar> 00155 typename ScalarTraits<Scalar>::magnitudeType 00156 relErr( const Scalar &s1, const Scalar &s2 ); 00157 00158 00165 template<class Scalar> 00166 bool testRelErr( 00167 const std::string &v1_name, 00168 const Scalar &v1, 00169 const std::string &v2_name, 00170 const Scalar &v2, 00171 const std::string &maxRelErr_error_name, 00172 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error, 00173 const std::string &maxRelErr_warning_name, 00174 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning, 00175 const Ptr<std::ostream> &out 00176 ); 00177 00178 00190 template<class Array1, class Array2> 00191 bool compareArrays( 00192 const Array1 &a1, const std::string &a1_name, 00193 const Array2 &a2, const std::string &a2_name, 00194 Teuchos::FancyOStream &out 00195 ); 00196 00197 00210 template<class Array1, class Array2, class ScalarMag> 00211 bool compareFloatingArrays( 00212 const Array1 &a1, const std::string &a1_name, 00213 const Array2 &a2, const std::string &a2_name, 00214 const ScalarMag &tol, 00215 Teuchos::FancyOStream &out 00216 ); 00217 00218 00219 } // namespace Teuchos 00220 00221 00230 #define TEUCHOS_PASS_FAIL(RESULT) \ 00231 Teuchos::passfail_with_location((RESULT), __FILE__, __LINE__) 00232 00233 00240 #define TEUCHOS_ECHO( statement, out ) \ 00241 (out) << #statement ";\n"; \ 00242 statement; 00243 00250 #define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \ 00251 { \ 00252 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \ 00253 const bool l_result = (v1) == (v2); \ 00254 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00255 if (!l_result) (success) = false; \ 00256 } 00257 00264 #define TEUCHOS_TEST_ASSERT( v1, out, success ) \ 00265 { \ 00266 const bool l_result = v1; \ 00267 (out) << #v1" = "<<l_result<<" == true : "; \ 00268 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00269 if (!l_result) (success) = false; \ 00270 } 00271 00278 #define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \ 00279 { \ 00280 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \ 00281 const bool l_result = (v1) == (v2); \ 00282 if (!l_result) (success) = false; \ 00283 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00284 } 00285 00286 00293 #define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \ 00294 { \ 00295 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "<<Teuchos::toString(v2)<<" : "; \ 00296 const bool l_result = (v1) != (v2); \ 00297 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00298 if (!l_result) (success) = false; \ 00299 } 00300 00301 00308 #define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \ 00309 { \ 00310 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \ 00311 const bool l_result = (v1) != (v2); \ 00312 if (!l_result) (success) = false; \ 00313 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00314 } 00315 00316 00323 #define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \ 00324 { \ 00325 const bool l_result = Teuchos::testRelErr( \ 00326 #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \ 00327 if (!l_result) (success) = false; \ 00328 } 00329 00330 00340 #define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \ 00341 { \ 00342 (out) << #iter1" == "#iter2" = : "; \ 00343 const bool l_result = (iter1) == (iter2); \ 00344 if (!l_result) (success) = false; \ 00345 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00346 } 00347 00348 00358 #define TEUCHOS_TEST_ITER_INEQUALITY( iter1, iter2, out, success ) \ 00359 { \ 00360 (out) << #iter1" != "#iter2" = : "; \ 00361 const bool l_result = (iter1) != (iter2); \ 00362 if (!l_result) (success) = false; \ 00363 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00364 } 00365 00366 00373 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \ 00374 { \ 00375 const bool l_result = ( (a)[i] == (val) ); \ 00376 if (!l_result) (success) = false; \ 00377 if (printPass || !(l_result)) { \ 00378 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \ 00379 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00380 } \ 00381 } 00382 00383 00390 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \ 00391 { \ 00392 const bool l_result = ( (a)[i] != (val) ); \ 00393 if (!l_result) (success) = false; \ 00394 if (printPass || !(l_result)) { \ 00395 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \ 00396 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00397 } \ 00398 } 00399 00400 00408 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \ 00409 { \ 00410 std::ostringstream a_i_str; \ 00411 a_i_str <<#a<<"("<<i<<","<<j<<")"; \ 00412 const bool l_result = Teuchos::testRelErr( \ 00413 a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \ 00414 (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \ 00415 if (!l_result) (success) = false; \ 00416 } 00417 00418 00425 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \ 00426 { \ 00427 const bool l_result = ( (a)(i,j) == (val) ); \ 00428 if (!l_result) (success) = false; \ 00429 if (printPass || !(l_result)) { \ 00430 out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \ 00431 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00432 } \ 00433 } 00434 00435 00445 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \ 00446 { \ 00447 out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \ 00448 const bool l_result = (v1) comp (v2); \ 00449 if (!l_result) (success) = false; \ 00450 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \ 00451 } 00452 00453 00468 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success ) \ 00469 { \ 00470 std::ostream& l_out = (out); \ 00471 try { \ 00472 l_out << "Test that code {"#code";} throws " \ 00473 << Teuchos::TypeNameTraits<ExceptType>::name () << ": "; \ 00474 code; \ 00475 (success) = false; \ 00476 l_out << "failed (code did not throw an exception at all)\n"; \ 00477 } \ 00478 catch (const ExceptType& except) { \ 00479 l_out << "passed\n"; \ 00480 l_out << "\nException message for expected exception:\n\n"; \ 00481 { \ 00482 Teuchos::OSTab l_tab (out); \ 00483 l_out << except.what () << "\n\n"; \ 00484 } \ 00485 } \ 00486 catch (std::exception& except) { \ 00487 l_out << "The code was supposed to throw an exception of type " \ 00488 << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \ 00489 << "instead threw an exception of type " \ 00490 << typeid (except).name () << ", which is a subclass of " \ 00491 << "std::exception. The exception's message is:\n\n"; \ 00492 { \ 00493 Teuchos::OSTab l_tab (out); \ 00494 l_out << except.what () << "\n\n"; \ 00495 } \ 00496 l_out << "failed\n"; \ 00497 } \ 00498 catch (...) { \ 00499 l_out << "The code was supposed to throw an exception of type " \ 00500 << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \ 00501 << "instead threw an exception of some unknown type, which is " \ 00502 << "not a subclass of std::exception. This means we cannot " \ 00503 << "show you the exception's message, if it even has one.\n\n"; \ 00504 l_out << "failed\n"; \ 00505 } \ 00506 } 00507 00508 00515 #define TEUCHOS_TEST_NOTHROW( code, out, success ) \ 00516 { \ 00517 std::ostream& l_out = (out); \ 00518 try { \ 00519 l_out << "Test that code {"#code";} does not throw : "; \ 00520 code; \ 00521 l_out << "passed\n"; \ 00522 } \ 00523 catch (std::exception& except) { \ 00524 (success) = false; \ 00525 l_out << "The code was not supposed to throw an exception, but " \ 00526 << "instead threw an exception of type " \ 00527 << typeid (except).name () << ", which is a subclass of " \ 00528 << "std::exception. The exception's message is:\n\n"; \ 00529 { \ 00530 Teuchos::OSTab l_tab (out); \ 00531 l_out << except.what () << "\n\n"; \ 00532 } \ 00533 l_out << "failed\n"; \ 00534 } \ 00535 catch (...) { \ 00536 (success) = false; \ 00537 l_out << "The code was not supposed to throw an exception, but " \ 00538 << "instead threw an exception of some unknown type, which is " \ 00539 << "not a subclass of std::exception. This means we cannot " \ 00540 << "show you the exception's message, if it even has one.\n\n"; \ 00541 l_out << "failed\n"; \ 00542 } \ 00543 } 00544 00545 // 00546 // Implementations 00547 // 00548 00549 00550 inline 00551 void Teuchos::updateSuccess(const bool result, bool &success) 00552 { 00553 if (!result) success = false; 00554 } 00555 00556 00557 inline 00558 const std::string 00559 Teuchos::passfail(const bool result) 00560 { 00561 if (!result) 00562 return "FAILED"; 00563 return "passed"; 00564 } 00565 00566 00567 template <class Scalar> 00568 typename Teuchos::ScalarTraits<Scalar>::magnitudeType 00569 Teuchos::relErr( const Scalar &s1, const Scalar &s2 ) 00570 { 00571 typedef Teuchos::ScalarTraits<Scalar> ST; 00572 return 00573 ST::magnitude( s1 - s2 ) 00574 / ( 00575 ST::magnitude( 00576 RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber() 00577 ) 00578 + std::max( ST::magnitude(s1), ST::magnitude(s2) ) 00579 ); 00580 } 00581 00582 00583 template<class Scalar> 00584 bool Teuchos::testRelErr( 00585 const std::string &v1_name, 00586 const Scalar &v1, 00587 const std::string &v2_name, 00588 const Scalar &v2, 00589 const std::string &maxRelErr_error_name, 00590 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error, 00591 const std::string &maxRelErr_warning_name, 00592 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning, 00593 const Ptr<std::ostream> &out 00594 ) 00595 { 00596 using std::endl; 00597 typedef ScalarTraits<Scalar> ST; 00598 typedef typename ST::magnitudeType ScalarMag; 00599 typedef ScalarTraits<ScalarMag> SMT; 00600 const ScalarMag rel_err = relErr( v1, v2 ); 00601 const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error) 00602 && rel_err <= maxRelErr_error ); 00603 if (!is_null(out)) { 00604 *out 00605 << endl 00606 << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n" 00607 << " = rel_err(" << v1 << ", " << v2 << ") " 00608 << "= " << rel_err << endl 00609 << " <= " << maxRelErr_error_name 00610 << " = " << maxRelErr_error << " : " << passfail(success) << endl; 00611 if( success && rel_err >= maxRelErr_warning ) { 00612 *out 00613 << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n" 00614 << " = rel_err(" << v1 << ", " << v2 << ") " 00615 << "= " << rel_err << endl 00616 << " >= " << maxRelErr_warning_name 00617 << " = " << maxRelErr_warning << "!\n"; 00618 } 00619 } 00620 return success; 00621 } 00622 00623 00624 template<class Array1, class Array2> 00625 bool Teuchos::compareArrays( 00626 const Array1 &a1, const std::string &a1_name, 00627 const Array2 &a2, const std::string &a2_name, 00628 Teuchos::FancyOStream &out 00629 ) 00630 { 00631 using Teuchos::as; 00632 bool success = true; 00633 00634 out << "Comparing " << a1_name << " == " << a2_name << " ... "; 00635 00636 const int n = a1.size(); 00637 00638 // Compare sizes 00639 if (as<int>(a2.size()) != n) { 00640 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 00641 << a2_name<<".size() = "<<a2.size()<<" : failed!\n"; 00642 return false; 00643 } 00644 00645 // Compare elements 00646 for( int i = 0; i < n; ++i ) { 00647 const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const 00648 if (!result) { 00649 out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == " 00650 << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n"; 00651 success = false; 00652 } 00653 } 00654 if (success) { 00655 out << "passed\n"; 00656 } 00657 00658 return success; 00659 00660 } 00661 00662 00663 template<class Array1, class Array2, class ScalarMag> 00664 bool Teuchos::compareFloatingArrays( 00665 const Array1 &a1, const std::string &a1_name, 00666 const Array2 &a2, const std::string &a2_name, 00667 const ScalarMag &tol, 00668 Teuchos::FancyOStream &out 00669 ) 00670 { 00671 using Teuchos::as; 00672 bool success = true; 00673 00674 out << "Comparing " << a1_name << " == " << a2_name << " ... "; 00675 00676 const int n = a1.size(); 00677 00678 // Compare sizes 00679 if (as<int>(a2.size()) != n) { 00680 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 00681 << a2_name<<".size() = "<<a2.size()<<" : failed!\n"; 00682 return false; 00683 } 00684 00685 // Compare elements 00686 for( int i = 0; i < n; ++i ) { 00687 const ScalarMag err = relErr( a1[i], a2[i] ); 00688 if ( !(err <= tol) ) { 00689 out 00690 <<"\nError, relErr("<<a1_name<<"["<<i<<"]," 00691 <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = " 00692 <<err<<" <= tol = "<<tol<<": failed!\n"; 00693 success = false; 00694 } 00695 } 00696 if (success) { 00697 out << "passed\n"; 00698 } 00699 00700 return success; 00701 00702 } 00703 00704 00705 #endif // TEUCHOS_TESTING_HELPERS_HPP
1.7.6.1