Use configuration checks to determine names for 'isnan' and 'finite'

This commit is contained in:
Ray Speth 2014-05-03 17:39:33 +00:00
parent 0a1909e682
commit 8cfac61a83
3 changed files with 44 additions and 30 deletions

View file

@ -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 <math.h>', 'C++')
env['HAS_GLOBAL_ISNAN'] = conf.CheckStatement('::isnan(1.0)', '#include <cmath>')
env['HAS_STD_ISNAN'] = conf.CheckStatement('std::isnan(1.0)', '#include <cmath>')
env['HAS_UNDERSCORE_ISNAN'] = conf.CheckStatement('_isnan(1.0)',
'#include <cmath>\n#include <float.h>')
env['HAS_BOOST_MATH'] = conf.CheckCXXHeader('boost/math/special_functions/erf.hpp', '<>')
boost_version_source = get_expression_value(['<boost/version.hpp>'], '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))

View file

@ -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.

View file

@ -22,50 +22,36 @@
#include <sunmath.h>
#endif
#ifdef _WIN32
#include <float.h>
// Compiler-dependent names for 'isnan' and 'finite'
#if defined(USE_UNDERSCORE_ISNAN)
// Windows
#include <float.h>
#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
}
}