From 5b233f973070352796e22008b5fa89d74591aa8d Mon Sep 17 00:00:00 2001 From: Guido Kanschat Date: Fri, 3 Jul 2015 12:09:45 +0200 Subject: [PATCH] check for std::isnan and make sure we never use a function that does not exist --- cmake/checks/check_01_cxx_features.cmake | 8 +++ include/deal.II/base/config.h.in | 1 + include/deal.II/base/numbers.h | 75 ++++++++++++++++++++++-- include/deal.II/lac/vector.templates.h | 2 + source/base/config.cc | 47 --------------- source/lac/solver_control.cc | 10 +--- 6 files changed, 83 insertions(+), 60 deletions(-) diff --git a/cmake/checks/check_01_cxx_features.cmake b/cmake/checks/check_01_cxx_features.cmake index 1bb9f98169..46022e6857 100644 --- a/cmake/checks/check_01_cxx_features.cmake +++ b/cmake/checks/check_01_cxx_features.cmake @@ -393,6 +393,14 @@ IF(DEAL_II_HAVE_CXX11) DEAL_II_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) ENDIF() +CHECK_CXX_SOURCE_COMPILES( + " + #include + int main(){ double d=0; std::isnan (d); return 0; } + " + DEAL_II_HAVE_STD_ISNAN) + + CHECK_CXX_SOURCE_COMPILES( " #include diff --git a/include/deal.II/base/config.h.in b/include/deal.II/base/config.h.in index a70d2deb99..d3b7a96964 100644 --- a/include/deal.II/base/config.h.in +++ b/include/deal.II/base/config.h.in @@ -107,6 +107,7 @@ #cmakedefine DEAL_II_HAVE_CXX11_IS_TRIVIALLY_COPYABLE #cmakedefine DEAL_II_HAVE_ISNAN +#cmakedefine DEAL_II_HAVE_STD_ISNAN #cmakedefine DEAL_II_HAVE_UNDERSCORE_ISNAN #cmakedefine DEAL_II_HAVE_ISFINITE diff --git a/include/deal.II/base/numbers.h b/include/deal.II/base/numbers.h index ae134e637a..699157fb7e 100644 --- a/include/deal.II/base/numbers.h +++ b/include/deal.II/base/numbers.h @@ -90,6 +90,18 @@ namespace numbers */ static const double SQRT1_2 = 0.70710678118654752440; + /** + * Check whether a value is not a number. + * + * This function uses either std::isnan, + * isnan, or _isnan, whichever is + * available on the system and returns the result. + * + * If none of the functions detecting NaN is available, this + * function returns false. + */ + bool is_nan (const double x); + /** * Return @p true if the given value is a finite floating point number, i.e. * is neither plus or minus infinity nor NaN (not a number). @@ -222,13 +234,68 @@ namespace numbers real_type abs (const std::complex &x); }; -} + // --------------- inline and template functions ---------------- // + inline bool is_nan (const double x) + { +#ifdef DEAL_II_HAVE_STD_ISNAN + return std::isnan(x); +#elif defined(DEAL_II_HAVE_ISNAN) + return isnan(x); +#elif defined(DEAL_II_HAVE_UNDERSCORE_ISNAN) + return _isnan(x); +#else + return false; +#endif + } + + inline bool is_finite (const double x) + { +#ifdef DEAL_II_HAVE_ISFINITE + return !is_nan(x) && std::isfinite (x); +#else + // Check against infinities. Note + // that if x is a NaN, then both + // comparisons will be false + return ((x >= -std::numeric_limits::max()) + && + (x <= std::numeric_limits::max())); +#endif + } + + + + inline bool is_finite (const std::complex &x) + { + // Check complex numbers for infinity + // by testing real and imaginary part + return ( is_finite (x.real()) + && + is_finite (x.imag()) ); + } + + + + inline bool is_finite (const std::complex &x) + { + // Check complex numbers for infinity + // by testing real and imaginary part + return ( is_finite (x.real()) + && + is_finite (x.imag()) ); + } + + + + inline bool is_finite (const std::complex &x) + { + // Same for std::complex + return ( is_finite (x.real()) + && + is_finite (x.imag()) ); + } -// --------------- inline and template functions ---------------- // -namespace numbers -{ template const number & NumberTraits::conjugate (const number &x) diff --git a/include/deal.II/lac/vector.templates.h b/include/deal.II/lac/vector.templates.h index 45d39d3f40..e80d2600b6 100644 --- a/include/deal.II/lac/vector.templates.h +++ b/include/deal.II/lac/vector.templates.h @@ -1472,6 +1472,7 @@ Vector::lp_norm (const real_type p) const } + template <> typename Vector::real_type Vector::lp_norm (const real_type) const @@ -1481,6 +1482,7 @@ Vector::lp_norm (const real_type) const } + template typename Vector::real_type Vector::linfty_norm () const diff --git a/source/base/config.cc b/source/base/config.cc index 265c04035c..983eef3023 100644 --- a/source/base/config.cc +++ b/source/base/config.cc @@ -22,53 +22,6 @@ DEAL_II_NAMESPACE_OPEN namespace numbers { - bool is_finite (const double x) - { -#ifdef DEAL_II_HAVE_ISFINITE - return !std::isnan(x) && std::isfinite (x); -#else - // Check against infinities. Note - // that if x is a NaN, then both - // comparisons will be false - return ((x >= -std::numeric_limits::max()) - && - (x <= std::numeric_limits::max())); -#endif - } - - - - bool is_finite (const std::complex &x) - { - // Check complex numbers for infinity - // by testing real and imaginary part - return ( is_finite (x.real()) - && - is_finite (x.imag()) ); - } - - - - bool is_finite (const std::complex &x) - { - // Check complex numbers for infinity - // by testing real and imaginary part - return ( is_finite (x.real()) - && - is_finite (x.imag()) ); - } - - - - bool is_finite (const std::complex &x) - { - // Same for std::complex - return ( is_finite (x.real()) - && - is_finite (x.imag()) ); - } - - template const bool NumberTraits::is_complex; diff --git a/source/lac/solver_control.cc b/source/lac/solver_control.cc index 9f1439fc69..87acec4f1b 100644 --- a/source/lac/solver_control.cc +++ b/source/lac/solver_control.cc @@ -92,15 +92,7 @@ SolverControl::check (const unsigned int step, } if ((step >= maxsteps) || -#ifdef DEAL_II_HAVE_ISNAN - isnan(check_value) || -#else -# ifdef DEAL_II_HAVE_UNDERSCORE_ISNAN - // on Microsoft Windows, the - // function is called _isnan - _isnan(check_value) || -# endif -#endif + numbers::is_nan(check_value) || (check_failure && (check_value > failure_residual)) ) { -- 2.39.5