diff --git a/SConstruct b/SConstruct index 9be5dd15e..f6eba864a 100644 --- a/SConstruct +++ b/SConstruct @@ -701,7 +701,20 @@ else: # *** Compiler Configuration Tests *** # ************************************ -conf = Configure(env) +def CheckStatement(context, function, includes=""): + context.Message('Checking for %s... ' % function) + src = """ +%(include)s +int main(int argc, char** argv) { + %(func)s; + return 0; +} +""" % {'func':function, 'include':includes} + result = context.TryCompile(src, '.cpp') + context.Result(result) + return result + +conf = Configure(env, custom_tests={'CheckStatement': CheckStatement}) # Set up compiler options before running configuration tests env['CXXFLAGS'] = listify(env['cxx_flags']) @@ -757,6 +770,12 @@ def get_expression_value(includes, expression): env['HAS_TIMES_H'] = conf.CheckCHeader('sys/times.h', '""') env['HAS_UNISTD_H'] = conf.CheckCHeader('unistd.h', '""') env['HAS_MATH_H_ERF'] = conf.CheckDeclaration('erf', '#include ', 'C++') + +env['HAS_GLOBAL_ISNAN'] = conf.CheckStatement('::isnan(1.0)', '#include ') +env['HAS_STD_ISNAN'] = conf.CheckStatement('std::isnan(1.0)', '#include ') +env['HAS_UNDERSCORE_ISNAN'] = conf.CheckStatement('_isnan(1.0)', + '#include \n#include ') + env['HAS_BOOST_MATH'] = conf.CheckCXXHeader('boost/math/special_functions/erf.hpp', '<>') boost_version_source = get_expression_value([''], 'BOOST_LIB_VERSION') retcode, boost_lib_version = conf.TryRun(boost_version_source, '.cpp') @@ -1179,6 +1198,10 @@ if not env['HAS_MATH_H_ERF']: else: configh['USE_BOOST_MATH'] = None +cdefine('USE_GLOBAL_ISNAN', 'HAS_GLOBAL_ISNAN') +cdefine('USE_STD_ISNAN', 'HAS_STD_ISNAN') +cdefine('USE_UNDERSCORE_ISNAN', 'HAS_UNDERSCORE_ISNAN') + config_h = env.Command('include/cantera/base/config.h', 'include/cantera/base/config.h.in', ConfigBuilder(configh)) diff --git a/include/cantera/base/config.h.in b/include/cantera/base/config.h.in index 85644a610..977fc2a9d 100644 --- a/include/cantera/base/config.h.in +++ b/include/cantera/base/config.h.in @@ -71,6 +71,11 @@ typedef int ftnlen; // Fortran hidden string length type //---------- C++ Compiler Variations ------------------------------ +// Name for 'isnan' varies for different compilers / standard libraries +%(USE_STD_ISNAN)s +%(USE_GLOBAL_ISNAN)s +%(USE_UNDERSCORE_ISNAN)s + // This define is needed to account for the variability for how // static variables in templated classes are defined. Right now // this is only turned on for the SunPro compiler on Solaris. diff --git a/src/base/checkFinite.cpp b/src/base/checkFinite.cpp index 41384cae9..316e22757 100644 --- a/src/base/checkFinite.cpp +++ b/src/base/checkFinite.cpp @@ -22,50 +22,36 @@ #include #endif -#ifdef _WIN32 -#include +// Compiler-dependent names for 'isnan' and 'finite' +#if defined(USE_UNDERSCORE_ISNAN) + // Windows + #include + #define isnan(x) _isnan(x) + #define finite(x) _finite(x) +#elif defined(USE_STD_ISNAN) + // From C++11 + using std::isnan; + #define finite(x) std::isfinite(x) +#elif defined(USE_GLOBAL_ISNAN) + // From C99 + using ::isnan; + using ::finite; #endif -using namespace std; - namespace Cantera { void checkFinite(const double tmp) { -#if defined _WIN32 - if (_finite(tmp)) { - if (_isnan(tmp)) { - printf("checkFinite() ERROR: we have encountered a nan!\n"); - } else if (_fpclass(tmp) == _FPCLASS_PINF) { - printf("checkFinite() ERROR: we have encountered a pos inf!\n"); - } else { - printf("checkFinite() ERROR: we have encountered a neg inf!\n"); - } - throw std::range_error("checkFinite()"); - } -#elif defined __CYGWIN__ if (!finite(tmp)) { if (isnan(tmp)) { printf("checkFinite() ERROR: we have encountered a nan!\n"); - } else if (isinf(tmp) == 1) { + } else if (tmp > 0) { printf("checkFinite() ERROR: we have encountered a pos inf!\n"); } else { printf("checkFinite() ERROR: we have encountered a neg inf!\n"); } throw std::range_error("checkFinite()"); } -#else - if (!::finite(tmp)) { - if (::isnan(tmp)) { - printf("checkFinite() ERROR: we have encountered a nan!\n"); - } else if (::isinf(tmp) == 1) { - printf("checkFinite() ERROR: we have encountered a pos inf!\n"); - } else { - printf("checkFinite() ERROR: we have encountered a neg inf!\n"); - } - throw std::range_error("checkFinite()"); - } -#endif } }