Cantera  2.0
checkFinite.cpp
Go to the documentation of this file.
1 /**
2  * @file checkFinite.cpp
3  * Declarations for Multi Dimensional Pointer (mdp) routines that
4  * check for the presence of NaNs in the code.
5  */
6 /*
7  * Copyright 2004 Sandia Corporation. Under the terms of Contract
8  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
9  * retains certain rights in this software.
10  * See file License.txt for licensing information.
11  */
12 
13 #include "cantera/base/ct_defs.h"
14 
15 #include <stdexcept>
16 #include <string>
17 
18 #include <cmath>
19 #include <cstdlib>
20 #include <cstdio>
21 
22 // We expect that there will be special casing based on the computer
23 // system here
24 
25 #ifdef SOLARIS
26 #include <ieeefp.h>
27 #include <sunmath.h>
28 #endif
29 
30 #ifdef _WIN32
31 #include <float.h>
32 #endif
33 
34 using namespace std;
35 
36 namespace mdp
37 {
38 
39 // Utility routine to check to see that a number is finite.
40 /*
41  * @param tmp number to be checked
42  */
43 #ifdef _WIN32
44 void checkFinite(const double tmp)
45 {
46  if (_finite(tmp)) {
47  if (_isnan(tmp)) {
48  printf("checkFinite() ERROR: we have encountered a nan!\n");
49  } else if (_fpclass(tmp) == _FPCLASS_PINF) {
50  printf("checkFinite() ERROR: we have encountered a pos inf!\n");
51  } else {
52  printf("checkFinite() ERROR: we have encountered a neg inf!\n");
53  }
54  const std::string s = "checkFinite()";
55  throw std::range_error(s);
56  }
57 }
58 #else
59 void checkFinite(const double tmp)
60 {
61  if (! finite(tmp)) {
62  if (isnan(tmp)) {
63  printf("checkFinite() ERROR: we have encountered a nan!\n");
64  } else if (isinf(tmp) == 1) {
65  printf("checkFinite() ERROR: we have encountered a pos inf!\n");
66  } else {
67  printf("checkFinite() ERROR: we have encountered a neg inf!\n");
68  }
69  const std::string s = "checkFinite()";
70  throw std::range_error(s);
71  }
72 }
73 #endif
74 
75 
76 // Utility routine to link checkFinte() to fortran program
77 /*
78  * This routine is accessible from fortran, usually
79  *
80  * @param tmp Pointer to the number to check
81  *
82  * @todo link it into the usual way Cantera handles Fortran calls
83  */
84 extern "C" void checkfinite_(double* tmp)
85 {
86  checkFinite(*tmp);
87 }
88 
89 
90 // Utility routine to check that a double stays bounded
91 /*
92  * This routine checks to see if a number stays bounded. The absolute
93  * value of the number is required to stay below the trigger.
94  *
95  * @param tmp Number to be checked
96  * @param trigger bounds on the number. Defaults to 1.0E20
97  */
98 void checkMagnitude(const double tmp, const double trigger)
99 {
100  checkFinite(tmp);
101  if (fabs(tmp) >= trigger) {
102  char sbuf[64];
103  sprintf(sbuf, "checkMagnitude() ERROR: Trigger %g exceeded: %g\n", trigger,
104  tmp);
105  throw std::range_error(sbuf);
106  }
107 }
108 
109 // Utility routine to check to see that a number is neither zero
110 // nor indefinite.
111 /*
112  * This check can be used before using the number in a denominator.
113  *
114  * @param tmp number to be checked
115  */
116 #ifdef _WIN32
117 void checkZeroFinite(const double tmp)
118 {
119  if ((tmp == 0.0) || (! _finite(tmp))) {
120  if (tmp == 0.0) {
121  printf("checkZeroFinite() ERROR: we have encountered a zero!\n");
122  } else if (_isnan(tmp)) {
123  printf("checkZeroFinite() ERROR: we have encountered a nan!\n");
124  } else if (_fpclass(tmp) == _FPCLASS_PINF) {
125  printf("checkZeroFinite() ERROR: we have encountered a pos inf!\n");
126  } else {
127  printf("checkZeroFinite() ERROR: we have encountered a neg inf!\n");
128  }
129  char sbuf[64];
130  sprintf(sbuf, "checkZeroFinite() ERROR: zero or indef exceeded: %g\n",
131  tmp);
132  throw std::range_error(sbuf);
133  }
134 }
135 #else
136 void checkZeroFinite(const double tmp)
137 {
138  if ((tmp == 0.0) || (! finite(tmp))) {
139  if (tmp == 0.0) {
140  printf("checkZeroFinite() ERROR: we have encountered a zero!\n");
141  } else if (isnan(tmp)) {
142  printf("checkZeroFinite() ERROR: we have encountered a nan!\n");
143  } else if (isinf(tmp) == 1) {
144  printf("checkZeroFinite() ERROR: we have encountered a pos inf!\n");
145  } else {
146  printf("checkZeroFinite() ERROR: we have encountered a neg inf!\n");
147  }
148  char sbuf[64];
149  sprintf(sbuf, "checkZeroFinite() ERROR: zero or indef exceeded: %g\n",
150  tmp);
151  throw std::range_error(sbuf);
152  }
153 }
154 #endif
155 }