cantera/Cantera/src/base/checkFinite.cpp
2012-01-09 17:32:01 +00:00

151 lines
4.1 KiB
C++

/**
* @file checkFinite.cpp
* Declarations for Multi Dimensional Pointer (mdp) routines that
* check for the presence of NaNs in the code.
*/
/*
* Copywrite 2004 Sandia Corporation. Under the terms of Contract
* DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
* retains certain rights in this software.
* See file License.txt for licensing information.
*/
#include "ct_defs.h"
#include <stdexcept>
#include <string>
#include <cmath>
#include <cstdlib>
#include <cstdio>
// We expect that there will be special casing based on the computer
// system here
#ifdef SOLARIS
#include <ieeefp.h>
#include <sunmath.h>
#endif
#ifdef WIN32
#include <float.h>
#pragma warning(disable:4290)
#pragma warning(disable:4996)
#endif
using namespace std;
namespace mdp {
// Utility routine to check to see that a number is finite.
/*
* @param tmp number to be checked
*/
#ifdef WIN32
void checkFinite(const double tmp) throw(std::range_error) {
if (_finite(tmp)) {
if(_isnan(tmp)) {
printf("ERROR: we have encountered a nan!\n");
} else if (_fpclass(tmp) == _FPCLASS_PINF) {
printf("ERROR: we have encountered a pos inf!\n");
} else {
printf("ERROR: we have encountered a neg inf!\n");
}
const std::string s = "checkFinite()";
throw std::range_error(s);
}
}
#else
void checkFinite(const double tmp) throw(std::range_error) {
if (! finite(tmp)) {
if(isnan(tmp)) {
printf("ERROR: we have encountered a nan!\n");
} else if (isinf(tmp) == 1) {
printf("ERROR: we have encountered a pos inf!\n");
} else {
printf("ERROR: we have encountered a neg inf!\n");
}
const std::string s = "checkFinite()";
throw std::range_error(s);
}
}
#endif
// Utility routine to link checkFinte() to fortran program
/*
* This routine is accessible from fortran, usually
*
* @param tmp Pointer to the number to check
*
* @todo link it into the usual way Cantera handles Fortran calls
*/
extern "C" void checkfinite_(double * tmp) {
checkFinite(*tmp);
}
// Utility routine to check that a double stays bounded
/*
* This routine checks to see if a number stays bounded. The absolute
* value of the number is required to stay below the trigger.
*
* @param tmp Number to be checked
* @param trigger bounds on the number. Defaults to 1.0E20
*/
void checkMagnitude(const double tmp, const double trigger) throw(std::range_error) {
checkFinite(tmp);
if (fabs(tmp) >= trigger) {
char sbuf[64];
sprintf(sbuf, "checkMagnitude: Trigger %g exceeded: %g\n", trigger,
tmp);
throw std::range_error(sbuf);
}
}
// Utility routine to check to see that a number is neither zero
// nor indefinite.
/*
* This check can be used before using the number in a denominator.
*
* @param tmp number to be checked
*/
#ifdef WIN32
void checkZeroFinite(const double tmp) throw(std::range_error) {
if ((tmp == 0.0) || (! _finite(tmp))) {
if (tmp == 0.0) {
printf("ERROR: we have encountered a zero!\n");
} else if(_isnan(tmp)) {
printf("ERROR: we have encountered a nan!\n");
} else if (_fpclass(tmp) == _FPCLASS_PINF) {
printf("ERROR: we have encountered a pos inf!\n");
} else {
printf("ERROR: we have encountered a neg inf!\n");
}
char sbuf[64];
sprintf(sbuf, "checkZeroFinite: zero or indef exceeded: %g\n",
tmp);
throw std::range_error(sbuf);
}
}
#else
void checkZeroFinite(const double tmp) throw(std::range_error) {
if ((tmp == 0.0) || (! finite(tmp))) {
if (tmp == 0.0) {
printf("ERROR: we have encountered a zero!\n");
} else if(isnan(tmp)) {
printf("ERROR: we have encountered a nan!\n");
} else if (isinf(tmp) == 1) {
printf("ERROR: we have encountered a pos inf!\n");
} else {
printf("ERROR: we have encountered a neg inf!\n");
}
char sbuf[64];
sprintf(sbuf, "checkZeroFinite: zero or indef exceeded: %g\n",
tmp);
throw std::range_error(sbuf);
}
}
#endif
}