Theoretica
Mathematical Library
Loading...
Searching...
No Matches
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
11#include <exception>
12
13#ifndef THEORETICA_NO_PRINT
14#include <sstream>
15#endif
16
17#endif
18
19#include <string>
20#include <cerrno>
21#include <limits>
22#include "./constants.h"
23
24
25namespace theoretica {
26
27
29 enum class MathError : int {
30 None = 0x00,
31 DivByZero = 0x01,
32 OutOfDomain = 0x02,
33 OutOfRange = 0x04,
34 ImpossibleOperation = 0x08,
35 NoConvergence = 0x10,
36 InvalidArgument = 0x20
37 };
38
39
41 inline int to_errno(MathError err) {
42 switch(err) {
43 case MathError::None: return 0; break;
44 case MathError::DivByZero: return ERANGE; break;
45 case MathError::OutOfDomain: return EDOM; break;
46 case MathError::OutOfRange: return ERANGE; break;
47 case MathError::ImpossibleOperation: return EDOM; break;
48 case MathError::NoConvergence: return ERANGE; break;
49 case MathError::InvalidArgument: return EINVAL; break;
50 default: return 0; break;
51 }
52 }
53
54
56 inline const char* to_cstring(MathError err) {
57 switch (err) {
58 case MathError::None: return "No error"; break;
59 case MathError::DivByZero: return "Division by zero"; break;
61 return "An argument was out of the domain of the called function"; break;
63 return "A mathematically impossible operation was requested"; break;
64 case MathError::NoConvergence: return "The algorithm did not converge"; break;
65 case MathError::InvalidArgument: return "Invalid argument size or value"; break;
66 default: return "Unknown error"; break;
67 }
68 }
69
70
72 inline std::string to_string(MathError err) {
73 return to_cstring(err);
74 }
75
76
79 return std::numeric_limits<real>::quiet_NaN();
80 }
81
82
93 template<typename T>
94 inline bool is_nan(const T& x) {
95 return !(x == x);
96 }
97
98
101 return std::numeric_limits<real>::infinity();
102 }
103
104
106 inline bool is_inf(real x) {
107 return (x == inf()) || (x == -inf());
108 }
109
110
111#if defined(THEORETICA_THROW_EXCEPTIONS) || defined(THEORETICA_ONLY_EXCEPTIONS)
112
113 class math_exception : std::exception {
114
115 private:
116 MathError err;
117 std::string func_name;
118 std::string file_name;
119 unsigned int code_line;
120 real val;
121
122 public:
123 math_exception(MathError a_err, const std::string& a_func_name,
124 const std::string& a_file_name, unsigned int a_code_line, real a_val)
125 : err(a_err), func_name(a_func_name), file_name(a_file_name),
126 code_line(a_code_line), val(a_val) {}
127
128 ~math_exception() = default;
129
130
132 inline const char* what() const noexcept {
133 return to_cstring(err);
134 }
135
136
138 inline MathError err_code() const {
139 return err;
140 }
141
142
144 inline std::string get_function_name() const {
145 return func_name;
146 }
147
148
150 inline std::string get_file_name() const {
151 return file_name;
152 }
153
154
156 inline unsigned int get_line_number() const {
157 return code_line;
158 }
159
160
162 inline real get_value() const {
163 return val;
164 }
165
166
167#ifndef THEORETICA_NO_PRINT
168
170 inline std::string to_string() const {
171
172 std::stringstream err_str;
173
174 err_str << file_name << "(" << code_line << "):";
175 err_str << func_name << "(" << val << "): ";
176
177 switch(err) {
178 case MathError::None: err_str << "No error"; break;
179 case MathError::DivByZero: err_str << "Division by zero"; break;
181 err_str << "An argument was out of the domain of the called function"; break;
183 err_str << "A mathematically impossible operation was requested"; break;
184 case MathError::NoConvergence: err_str << "The algorithm did not converge"; break;
185 case MathError::InvalidArgument: err_str << "Invalid argument size or value"; break;
186 default: err_str << "Unknown error"; break;
187 }
188
189 return err_str.str();
190 }
191
192
194 inline operator std::string() {
195 return to_string();
196 }
197
198
201 inline friend std::ostream& operator<<(std::ostream& out, const math_exception& obj) {
202 return out << obj.to_string();
203 }
204
205#endif
206
207 };
208
209#endif
210
211}
212
213
217
218
219// Only throw exceptions, without modifying errno
220#ifdef THEORETICA_ONLY_EXCEPTIONS
221
222#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION) \
223 { throw theoretica::math_exception(EXCEPTION, F_NAME, __FILE__, __LINE__, VALUE); }
224
225#define TH_MATH_ERROR_R(F_NAME, VALUE, EXCEPTION) \
226 TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
227
228// Throw exceptions and modify errno
229#elif defined(THEORETICA_THROW_EXCEPTIONS)
230
231#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION) \
232 { errno = theoretica::to_errno(EXCEPTION); \
233 throw math_exception(EXCEPTION, F_NAME, __FILE__, __LINE__, VALUE); }
234
235// Modify errno only by default
236#else
237
238#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION) \
239 { errno = theoretica::to_errno(EXCEPTION); }
240
241#endif
242
243
244// Output the value of an expression with additional information,
245// for debugging purposes.
246#define TH_DEBUG(VARIABLE) { \
247 std::cout << __FILE__ << ":" << __LINE__ << ": " \
248 << #VARIABLE << " = " << VARIABLE << std::endl; }
249
250
251#endif
Mathematical constants and default algorithm parameters.
#define TH_CONSTEXPR
Enable constexpr in function declarations if C++14 is supported.
Definition constants.h:161
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:198
bool is_nan(const T &x)
Check whether a generic variable is (equivalent to) a NaN number.
Definition error.h:94
TH_CONSTEXPR real nan()
Return a quiet NaN number in floating point representation.
Definition error.h:78
int to_errno(MathError err)
Convert an MathError class enum to conventional errno codes.
Definition error.h:41
std::string to_string(MathError err)
Convert a MathError class enum to a string description.
Definition error.h:72
MathError
Math error enumeration.
Definition error.h:29
@ InvalidArgument
Invalid argument.
@ OutOfDomain
Argument out of domain.
@ OutOfRange
Result out of range.
@ ImpossibleOperation
Mathematically impossible operation.
@ NoConvergence
Algorithm did not converge.
@ DivByZero
Division by zero.
bool is_inf(real x)
Check whether a real number is infinite.
Definition error.h:106
TH_CONSTEXPR real inf()
Get positive infinity in floating point representation.
Definition error.h:100
const char * to_cstring(MathError err)
Convert a MathError class enum to a string description.
Definition error.h:56