Theoretica
A C++ numerical and automatic mathematical library
error.h
Go to the documentation of this file.
1 
5 
6 #ifndef THEORETICA_ERROR_H
7 #define THEORETICA_ERROR_H
8 
9 #if defined(THEORETICA_THROW_EXCEPTIONS) || defined(THEORETICA_ONLY_EXCEPTIONS)
10 #include <exception>
11 #include <string>
12 
13 #ifndef THEORETICA_NO_PRINT
14 #include <sstream>
15 #endif
16 
17 #endif
18 
19 #include <cerrno>
20 #include <limits>
21 #include "./constants.h"
22 
23 
24 namespace theoretica {
25 
27  enum MATH_ERRCODE {
28  NO_ERROR = 0x00, // No error
29  DIV_BY_ZERO = 0x01, // Division by zero
30  OUT_OF_DOMAIN = 0x02, // An argument is out of range
31  OUT_OF_RANGE = 0x04, // The result would be out of range
32  IMPOSSIBLE_OPERATION = 0x08, // Impossible operation
33  NO_ALGO_CONVERGENCE = 0x10, // The algorithm did not converge
34  INVALID_ARGUMENT = 0x20 // Invalid argument size or value
35  };
36 
37 
40  switch(err) {
41  case NO_ERROR: return 0; break;
42  case DIV_BY_ZERO: return ERANGE; break;
43  case OUT_OF_DOMAIN: return EDOM; break;
44  case OUT_OF_RANGE: return ERANGE; break;
45  case IMPOSSIBLE_OPERATION: return EDOM; break;
46  case NO_ALGO_CONVERGENCE: return ERANGE; break;
47  case INVALID_ARGUMENT: return EINVAL; break;
48  default: return 0; break;
49  }
50  }
51 
52 
54  inline real nan() {
55  return std::numeric_limits<real>::quiet_NaN();
56  }
57 
58 
69  template<typename T>
70  inline bool is_nan(const T& x) {
71  return !(x == x);
72  }
73 
74 
76  inline real inf() {
77  return std::numeric_limits<real>::infinity();
78  }
79 
80 
81 #if defined(THEORETICA_THROW_EXCEPTIONS) || defined(THEORETICA_ONLY_EXCEPTIONS)
82 
83  class math_exception : std::exception {
84 
85  private:
86  MATH_ERRCODE err;
87  std::string func_name;
88  std::string file_name;
89  unsigned int code_line;
90  real val;
91 
92  public:
93  math_exception(MATH_ERRCODE a_err, const std::string& a_func_name,
94  const std::string& a_file_name, unsigned int a_code_line, real a_val)
95  : err(a_err), func_name(a_func_name), file_name(a_file_name),
96  code_line(a_code_line), val(a_val) {}
97 
98  ~math_exception() = default;
99 
100 
102  inline const char* what() const noexcept {
103 
104  switch(err) {
105  case NO_ERROR: return "No error"; break;
106  case DIV_BY_ZERO: return "Division by zero"; break;
107  case OUT_OF_DOMAIN:
108  return "An argument was out of the domain of the called function"; break;
109  case IMPOSSIBLE_OPERATION:
110  return "A mathematically impossible operation was requested"; break;
111  case NO_ALGO_CONVERGENCE: return "The algorithm did not converge"; break;
112  case INVALID_ARGUMENT: return "Invalid argument size or value"; break;
113  default: return "Unknown error"; break;
114  }
115  }
116 
117 
119  inline MATH_ERRCODE err_code() const {
120  return err;
121  }
122 
123 
125  inline std::string get_function_name() const {
126  return func_name;
127  }
128 
129 
131  inline std::string get_file_name() const {
132  return file_name;
133  }
134 
135 
137  inline unsigned int get_line_number() const {
138  return code_line;
139  }
140 
141 
143  inline real get_value() const {
144  return val;
145  }
146 
147 
148 #ifndef THEORETICA_NO_PRINT
149 
151  inline std::string to_string() const {
152 
153  std::stringstream err_str;
154 
155  err_str << file_name << "(" << code_line << "):";
156  err_str << func_name << "(" << val << "): ";
157 
158  switch(err) {
159  case NO_ERROR: err_str << "No error"; break;
160  case DIV_BY_ZERO: err_str << "Division by zero"; break;
161  case OUT_OF_DOMAIN:
162  err_str << "An argument was out of the domain of the called function"; break;
163  case IMPOSSIBLE_OPERATION:
164  err_str << "A mathematically impossible operation was requested"; break;
165  case NO_ALGO_CONVERGENCE: err_str << "The algorithm did not converge"; break;
166  case INVALID_ARGUMENT: err_str << "Invalid argument size or value"; break;
167  default: err_str << "Unknown error"; break;
168  }
169 
170  return err_str.str();
171  }
172 
173 
175  inline operator std::string() {
176  return to_string();
177  }
178 
179 
182  inline friend std::ostream& operator<<(std::ostream& out, const math_exception& obj) {
183  return out << obj.to_string();
184  }
185 
186 #endif
187 
188  };
189 
190 #endif
191 
192 }
193 
194 
198 
199 
200 // Only throw exceptions, without modifying errno
201 #ifdef THEORETICA_ONLY_EXCEPTIONS
202 
203 #define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION) \
204  { throw math_exception(EXCEPTION, F_NAME, __FILE__, __LINE__, VALUE); }
205 
206 #define TH_MATH_ERROR_R(F_NAME, VALUE, EXCEPTION) \
207  TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
208 
209 // Throw exceptions and modify errno
210 #elif defined(THEORETICA_THROW_EXCEPTIONS)
211 
212 #define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION) \
213  { errno = th_errcode_to_errno(EXCEPTION); \
214  throw math_exception(EXCEPTION, F_NAME, __FILE__, __LINE__, VALUE); }
215 
216 // Modify errno only by default
217 #else
218 
219 #define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION) \
220  { errno = th_errcode_to_errno(EXCEPTION); }
221 
222 #endif
223 
224 
225 // Output the value of an expression with additional information,
226 // for debugging purposes.
227 #define TH_DEBUG(VARIABLE) { \
228  std::cout << __FILE__ << ":" << __LINE__ << ": " \
229  << #VARIABLE << " = " << VARIABLE << std::endl; }
230 
231 
232 #endif
Mathematical constants and default algorithm parameters.
std::string string(size_t length)
Generate a random string made of human-readable ASCII characters.
Definition: random.h:102
Main namespace of the library which contains all functions and objects.
Definition: algebra.h:27
double real
A real number, defined as a floating point type.
Definition: constants.h:188
bool is_nan(const T &x)
Check whether a generic variable is (equivalent to) a NaN number.
Definition: error.h:70
real inf()
Return positive infinity in floating point representation.
Definition: error.h:76
MATH_ERRCODE
Math error enumeration.
Definition: error.h:27
int th_errcode_to_errno(MATH_ERRCODE err)
Convert a MATH_ERRCODE to errno error codes.
Definition: error.h:39
real nan()
Return a quiet NaN number in floating point representation.
Definition: error.h:54