• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Copyright John Maddock 2007.
2 //  Copyright Paul A. Bristow 2007.
3 
4 //  Use, modification and distribution are subject to the
5 //  Boost Software License, Version 1.0. (See accompanying file
6 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
9 #define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
10 
11 #include <stdexcept>
12 #include <iomanip>
13 #include <string>
14 #include <cstring>
15 #include <typeinfo>
16 #include <cerrno>
17 #include <boost/config/no_tr1/complex.hpp>
18 #include <boost/config/no_tr1/cmath.hpp>
19 #include <stdexcept>
20 #include <boost/math/tools/config.hpp>
21 #include <boost/math/policies/policy.hpp>
22 #include <boost/math/tools/precision.hpp>
23 #include <boost/throw_exception.hpp>
24 #include <boost/cstdint.hpp>
25 #ifdef BOOST_MSVC
26 #  pragma warning(push) // Quiet warnings in boost/format.hpp
27 #  pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
28 #  pragma warning(disable: 4512) // assignment operator could not be generated.
29 #  pragma warning(disable: 4127) // conditional expression is constant
30 // And warnings in error handling:
31 #  pragma warning(disable: 4702) // unreachable code.
32 // Note that this only occurs when the compiler can deduce code is unreachable,
33 // for example when policy macros are used to ignore errors rather than throw.
34 #endif
35 #include <sstream>
36 
37 namespace boost{ namespace math{
38 
39 class evaluation_error : public std::runtime_error
40 {
41 public:
evaluation_error(const std::string & s)42    evaluation_error(const std::string& s) : std::runtime_error(s){}
43 };
44 
45 class rounding_error : public std::runtime_error
46 {
47 public:
rounding_error(const std::string & s)48    rounding_error(const std::string& s) : std::runtime_error(s){}
49 };
50 
51 namespace policies{
52 //
53 // Forward declarations of user error handlers,
54 // it's up to the user to provide the definition of these:
55 //
56 template <class T>
57 T user_domain_error(const char* function, const char* message, const T& val);
58 template <class T>
59 T user_pole_error(const char* function, const char* message, const T& val);
60 template <class T>
61 T user_overflow_error(const char* function, const char* message, const T& val);
62 template <class T>
63 T user_underflow_error(const char* function, const char* message, const T& val);
64 template <class T>
65 T user_denorm_error(const char* function, const char* message, const T& val);
66 template <class T>
67 T user_evaluation_error(const char* function, const char* message, const T& val);
68 template <class T, class TargetType>
69 T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
70 template <class T>
71 T user_indeterminate_result_error(const char* function, const char* message, const T& val);
72 
73 namespace detail
74 {
75 
76 template <class T>
prec_format(const T & val)77 std::string prec_format(const T& val)
78 {
79    typedef typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type prec_type;
80    std::stringstream ss;
81    if(prec_type::value)
82    {
83       int prec = 2 + (prec_type::value * 30103UL) / 100000UL;
84       ss << std::setprecision(prec);
85    }
86    ss << val;
87    return ss.str();
88 }
89 
replace_all_in_string(std::string & result,const char * what,const char * with)90 inline void replace_all_in_string(std::string& result, const char* what, const char* with)
91 {
92    std::string::size_type pos = 0;
93    std::string::size_type slen = std::strlen(what);
94    std::string::size_type rlen = std::strlen(with);
95    while((pos = result.find(what, pos)) != std::string::npos)
96    {
97       result.replace(pos, slen, with);
98       pos += rlen;
99    }
100 }
101 
102 template <class T>
name_of()103 inline const char* name_of()
104 {
105 #ifndef BOOST_NO_RTTI
106    return typeid(T).name();
107 #else
108    return "unknown";
109 #endif
110 }
name_of()111 template <> inline const char* name_of<float>(){ return "float"; }
name_of()112 template <> inline const char* name_of<double>(){ return "double"; }
name_of()113 template <> inline const char* name_of<long double>(){ return "long double"; }
114 
115 #ifdef BOOST_MATH_USE_FLOAT128
116 template <>
name_of()117 inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()
118 {
119    return "__float128";
120 }
121 #endif
122 
123 template <class E, class T>
raise_error(const char * pfunction,const char * message)124 void raise_error(const char* pfunction, const char* message)
125 {
126   if(pfunction == 0)
127      pfunction = "Unknown function operating on type %1%";
128   if(message == 0)
129      message = "Cause unknown";
130 
131   std::string function(pfunction);
132   std::string msg("Error in function ");
133 #ifndef BOOST_NO_RTTI
134   replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
135 #else
136   replace_all_in_string(function, "%1%", "Unknown");
137 #endif
138   msg += function;
139   msg += ": ";
140   msg += message;
141 
142   E e(msg);
143   boost::throw_exception(e);
144 }
145 
146 template <class E, class T>
raise_error(const char * pfunction,const char * pmessage,const T & val)147 void raise_error(const char* pfunction, const char* pmessage, const T& val)
148 {
149   if(pfunction == 0)
150      pfunction = "Unknown function operating on type %1%";
151   if(pmessage == 0)
152      pmessage = "Cause unknown: error caused by bad argument with value %1%";
153 
154   std::string function(pfunction);
155   std::string message(pmessage);
156   std::string msg("Error in function ");
157 #ifndef BOOST_NO_RTTI
158   replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
159 #else
160   replace_all_in_string(function, "%1%", "Unknown");
161 #endif
162   msg += function;
163   msg += ": ";
164 
165   std::string sval = prec_format(val);
166   replace_all_in_string(message, "%1%", sval.c_str());
167   msg += message;
168 
169   E e(msg);
170   boost::throw_exception(e);
171 }
172 
173 template <class T>
raise_domain_error(const char * function,const char * message,const T & val,const::boost::math::policies::domain_error<::boost::math::policies::throw_on_error> &)174 inline T raise_domain_error(
175            const char* function,
176            const char* message,
177            const T& val,
178            const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
179 {
180    raise_error<std::domain_error, T>(function, message, val);
181    // we never get here:
182    return std::numeric_limits<T>::quiet_NaN();
183 }
184 
185 template <class T>
raise_domain_error(const char *,const char *,const T &,const::boost::math::policies::domain_error<::boost::math::policies::ignore_error> &)186 inline BOOST_MATH_CONSTEXPR T raise_domain_error(
187            const char* ,
188            const char* ,
189            const T& ,
190            const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
191 {
192    // This may or may not do the right thing, but the user asked for the error
193    // to be ignored so here we go anyway:
194    return std::numeric_limits<T>::quiet_NaN();
195 }
196 
197 template <class T>
raise_domain_error(const char *,const char *,const T &,const::boost::math::policies::domain_error<::boost::math::policies::errno_on_error> &)198 inline T raise_domain_error(
199            const char* ,
200            const char* ,
201            const T& ,
202            const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
203 {
204    errno = EDOM;
205    // This may or may not do the right thing, but the user asked for the error
206    // to be silent so here we go anyway:
207    return std::numeric_limits<T>::quiet_NaN();
208 }
209 
210 template <class T>
raise_domain_error(const char * function,const char * message,const T & val,const::boost::math::policies::domain_error<::boost::math::policies::user_error> &)211 inline T raise_domain_error(
212            const char* function,
213            const char* message,
214            const T& val,
215            const  ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
216 {
217    return user_domain_error(function, message, val);
218 }
219 
220 template <class T>
raise_pole_error(const char * function,const char * message,const T & val,const::boost::math::policies::pole_error<::boost::math::policies::throw_on_error> &)221 inline T raise_pole_error(
222            const char* function,
223            const char* message,
224            const T& val,
225            const  ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
226 {
227    return boost::math::policies::detail::raise_domain_error(function, message, val,  ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
228 }
229 
230 template <class T>
raise_pole_error(const char * function,const char * message,const T & val,const::boost::math::policies::pole_error<::boost::math::policies::ignore_error> &)231 inline BOOST_MATH_CONSTEXPR T raise_pole_error(
232            const char* function,
233            const char* message,
234            const T& val,
235            const  ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
236 {
237    return  ::boost::math::policies::detail::raise_domain_error(function, message, val,  ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
238 }
239 
240 template <class T>
raise_pole_error(const char * function,const char * message,const T & val,const::boost::math::policies::pole_error<::boost::math::policies::errno_on_error> &)241 inline BOOST_MATH_CONSTEXPR T raise_pole_error(
242            const char* function,
243            const char* message,
244            const T& val,
245            const  ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
246 {
247    return  ::boost::math::policies::detail::raise_domain_error(function, message, val,  ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
248 }
249 
250 template <class T>
raise_pole_error(const char * function,const char * message,const T & val,const::boost::math::policies::pole_error<::boost::math::policies::user_error> &)251 inline T raise_pole_error(
252            const char* function,
253            const char* message,
254            const T& val,
255            const  ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
256 {
257    return user_pole_error(function, message, val);
258 }
259 
260 
261 template <class T>
raise_overflow_error(const char * function,const char * message,const::boost::math::policies::overflow_error<::boost::math::policies::throw_on_error> &)262 inline T raise_overflow_error(
263            const char* function,
264            const char* message,
265            const  ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
266 {
267    raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
268    // We should never get here:
269    return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
270 }
271 
272 template <class T>
raise_overflow_error(const char * function,const char * message,const T & val,const::boost::math::policies::overflow_error<::boost::math::policies::throw_on_error> &)273 inline T raise_overflow_error(
274            const char* function,
275            const char* message,
276            const T& val,
277            const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
278 {
279    raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow", val);
280    // We should never get here:
281    return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
282 }
283 
284 template <class T>
raise_overflow_error(const char *,const char *,const::boost::math::policies::overflow_error<::boost::math::policies::ignore_error> &)285 inline BOOST_MATH_CONSTEXPR T raise_overflow_error(
286            const char* ,
287            const char* ,
288            const  ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
289 {
290    // This may or may not do the right thing, but the user asked for the error
291    // to be ignored so here we go anyway:
292    return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
293 }
294 
295 template <class T>
raise_overflow_error(const char *,const char *,const T &,const::boost::math::policies::overflow_error<::boost::math::policies::ignore_error> &)296 inline BOOST_MATH_CONSTEXPR T raise_overflow_error(
297            const char* ,
298            const char* ,
299            const T&,
300            const  ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
301 {
302    // This may or may not do the right thing, but the user asked for the error
303    // to be ignored so here we go anyway:
304    return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
305 }
306 
307 template <class T>
raise_overflow_error(const char *,const char *,const::boost::math::policies::overflow_error<::boost::math::policies::errno_on_error> &)308 inline T raise_overflow_error(
309            const char* ,
310            const char* ,
311            const  ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
312 {
313    errno = ERANGE;
314    // This may or may not do the right thing, but the user asked for the error
315    // to be silent so here we go anyway:
316    return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
317 }
318 
319 template <class T>
raise_overflow_error(const char *,const char *,const T &,const::boost::math::policies::overflow_error<::boost::math::policies::errno_on_error> &)320 inline T raise_overflow_error(
321            const char* ,
322            const char* ,
323            const T&,
324            const  ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
325 {
326    errno = ERANGE;
327    // This may or may not do the right thing, but the user asked for the error
328    // to be silent so here we go anyway:
329    return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
330 }
331 
332 template <class T>
raise_overflow_error(const char * function,const char * message,const::boost::math::policies::overflow_error<::boost::math::policies::user_error> &)333 inline T raise_overflow_error(
334            const char* function,
335            const char* message,
336            const  ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
337 {
338    return user_overflow_error(function, message, std::numeric_limits<T>::infinity());
339 }
340 
341 template <class T>
raise_overflow_error(const char * function,const char * message,const T & val,const::boost::math::policies::overflow_error<::boost::math::policies::user_error> &)342 inline T raise_overflow_error(
343            const char* function,
344            const char* message,
345            const T& val,
346            const  ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
347 {
348    std::string m(message ? message : "");
349    std::string sval = prec_format(val);
350    replace_all_in_string(m, "%1%", sval.c_str());
351 
352    return user_overflow_error(function, m.c_str(), std::numeric_limits<T>::infinity());
353 }
354 
355 template <class T>
raise_underflow_error(const char * function,const char * message,const::boost::math::policies::underflow_error<::boost::math::policies::throw_on_error> &)356 inline T raise_underflow_error(
357            const char* function,
358            const char* message,
359            const  ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
360 {
361    raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
362    // We should never get here:
363    return 0;
364 }
365 
366 template <class T>
raise_underflow_error(const char *,const char *,const::boost::math::policies::underflow_error<::boost::math::policies::ignore_error> &)367 inline BOOST_MATH_CONSTEXPR T raise_underflow_error(
368            const char* ,
369            const char* ,
370            const  ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
371 {
372    // This may or may not do the right thing, but the user asked for the error
373    // to be ignored so here we go anyway:
374    return T(0);
375 }
376 
377 template <class T>
raise_underflow_error(const char *,const char *,const::boost::math::policies::underflow_error<::boost::math::policies::errno_on_error> &)378 inline T raise_underflow_error(
379            const char* /* function */,
380            const char* /* message */,
381            const  ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
382 {
383    errno = ERANGE;
384    // This may or may not do the right thing, but the user asked for the error
385    // to be silent so here we go anyway:
386    return T(0);
387 }
388 
389 template <class T>
raise_underflow_error(const char * function,const char * message,const::boost::math::policies::underflow_error<::boost::math::policies::user_error> &)390 inline T raise_underflow_error(
391            const char* function,
392            const char* message,
393            const  ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
394 {
395    return user_underflow_error(function, message, T(0));
396 }
397 
398 template <class T>
raise_denorm_error(const char * function,const char * message,const T &,const::boost::math::policies::denorm_error<::boost::math::policies::throw_on_error> &)399 inline T raise_denorm_error(
400            const char* function,
401            const char* message,
402            const T& /* val */,
403            const  ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
404 {
405    raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
406    // we never get here:
407    return T(0);
408 }
409 
410 template <class T>
raise_denorm_error(const char *,const char *,const T & val,const::boost::math::policies::denorm_error<::boost::math::policies::ignore_error> &)411 inline BOOST_MATH_CONSTEXPR T raise_denorm_error(
412            const char* ,
413            const char* ,
414            const T&  val,
415            const  ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
416 {
417    // This may or may not do the right thing, but the user asked for the error
418    // to be ignored so here we go anyway:
419    return val;
420 }
421 
422 template <class T>
raise_denorm_error(const char *,const char *,const T & val,const::boost::math::policies::denorm_error<::boost::math::policies::errno_on_error> &)423 inline T raise_denorm_error(
424            const char* ,
425            const char* ,
426            const T& val,
427            const  ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
428 {
429    errno = ERANGE;
430    // This may or may not do the right thing, but the user asked for the error
431    // to be silent so here we go anyway:
432    return val;
433 }
434 
435 template <class T>
raise_denorm_error(const char * function,const char * message,const T & val,const::boost::math::policies::denorm_error<::boost::math::policies::user_error> &)436 inline T raise_denorm_error(
437            const char* function,
438            const char* message,
439            const T& val,
440            const  ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
441 {
442    return user_denorm_error(function, message, val);
443 }
444 
445 template <class T>
raise_evaluation_error(const char * function,const char * message,const T & val,const::boost::math::policies::evaluation_error<::boost::math::policies::throw_on_error> &)446 inline T raise_evaluation_error(
447            const char* function,
448            const char* message,
449            const T& val,
450            const  ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
451 {
452    raise_error<boost::math::evaluation_error, T>(function, message, val);
453    // we never get here:
454    return T(0);
455 }
456 
457 template <class T>
raise_evaluation_error(const char *,const char *,const T & val,const::boost::math::policies::evaluation_error<::boost::math::policies::ignore_error> &)458 inline BOOST_MATH_CONSTEXPR T raise_evaluation_error(
459            const char* ,
460            const char* ,
461            const T& val,
462            const  ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
463 {
464    // This may or may not do the right thing, but the user asked for the error
465    // to be ignored so here we go anyway:
466    return val;
467 }
468 
469 template <class T>
raise_evaluation_error(const char *,const char *,const T & val,const::boost::math::policies::evaluation_error<::boost::math::policies::errno_on_error> &)470 inline T raise_evaluation_error(
471            const char* ,
472            const char* ,
473            const T& val,
474            const  ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
475 {
476    errno = EDOM;
477    // This may or may not do the right thing, but the user asked for the error
478    // to be silent so here we go anyway:
479    return val;
480 }
481 
482 template <class T>
raise_evaluation_error(const char * function,const char * message,const T & val,const::boost::math::policies::evaluation_error<::boost::math::policies::user_error> &)483 inline T raise_evaluation_error(
484            const char* function,
485            const char* message,
486            const T& val,
487            const  ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
488 {
489    return user_evaluation_error(function, message, val);
490 }
491 
492 template <class T, class TargetType>
raise_rounding_error(const char * function,const char * message,const T & val,const TargetType &,const::boost::math::policies::rounding_error<::boost::math::policies::throw_on_error> &)493 inline TargetType raise_rounding_error(
494            const char* function,
495            const char* message,
496            const T& val,
497            const TargetType&,
498            const  ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
499 {
500    raise_error<boost::math::rounding_error, T>(function, message, val);
501    // we never get here:
502    return TargetType(0);
503 }
504 
505 template <class T, class TargetType>
raise_rounding_error(const char *,const char *,const T & val,const TargetType &,const::boost::math::policies::rounding_error<::boost::math::policies::ignore_error> &)506 inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(
507            const char* ,
508            const char* ,
509            const T& val,
510            const TargetType&,
511            const  ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
512 {
513    // This may or may not do the right thing, but the user asked for the error
514    // to be ignored so here we go anyway:
515    BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
516    return  val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
517 }
518 
519 template <class T, class TargetType>
raise_rounding_error(const char *,const char *,const T & val,const TargetType &,const::boost::math::policies::rounding_error<::boost::math::policies::errno_on_error> &)520 inline TargetType raise_rounding_error(
521            const char* ,
522            const char* ,
523            const T& val,
524            const TargetType&,
525            const  ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
526 {
527    errno = ERANGE;
528    // This may or may not do the right thing, but the user asked for the error
529    // to be silent so here we go anyway:
530    BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
531    return  val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
532 }
533 
534 template <class T>
raise_rounding_error(const char *,const char *,const T & val,const T &,const::boost::math::policies::rounding_error<::boost::math::policies::errno_on_error> &)535 inline T raise_rounding_error(
536            const char* ,
537            const char* ,
538            const T& val,
539            const T&,
540            const  ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
541 {
542    errno = ERANGE;
543    // This may or may not do the right thing, but the user asked for the error
544    // to be silent so here we go anyway:
545    return  val > 0 ? boost::math::tools::max_value<T>() : -boost::math::tools::max_value<T>();
546 }
547 
548 template <class T, class TargetType>
raise_rounding_error(const char * function,const char * message,const T & val,const TargetType & t,const::boost::math::policies::rounding_error<::boost::math::policies::user_error> &)549 inline TargetType raise_rounding_error(
550            const char* function,
551            const char* message,
552            const T& val,
553            const TargetType& t,
554            const  ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
555 {
556    return user_rounding_error(function, message, val, t);
557 }
558 
559 template <class T, class R>
raise_indeterminate_result_error(const char * function,const char * message,const T & val,const R &,const::boost::math::policies::indeterminate_result_error<::boost::math::policies::throw_on_error> &)560 inline T raise_indeterminate_result_error(
561            const char* function,
562            const char* message,
563            const T& val,
564            const R& ,
565            const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
566 {
567    raise_error<std::domain_error, T>(function, message, val);
568    // we never get here:
569    return std::numeric_limits<T>::quiet_NaN();
570 }
571 
572 template <class T, class R>
raise_indeterminate_result_error(const char *,const char *,const T &,const R & result,const::boost::math::policies::indeterminate_result_error<::boost::math::policies::ignore_error> &)573 inline BOOST_MATH_CONSTEXPR T raise_indeterminate_result_error(
574            const char* ,
575            const char* ,
576            const T& ,
577            const R& result,
578            const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
579 {
580    // This may or may not do the right thing, but the user asked for the error
581    // to be ignored so here we go anyway:
582    return result;
583 }
584 
585 template <class T, class R>
raise_indeterminate_result_error(const char *,const char *,const T &,const R & result,const::boost::math::policies::indeterminate_result_error<::boost::math::policies::errno_on_error> &)586 inline T raise_indeterminate_result_error(
587            const char* ,
588            const char* ,
589            const T& ,
590            const R& result,
591            const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)
592 {
593    errno = EDOM;
594    // This may or may not do the right thing, but the user asked for the error
595    // to be silent so here we go anyway:
596    return result;
597 }
598 
599 template <class T, class R>
raise_indeterminate_result_error(const char * function,const char * message,const T & val,const R &,const::boost::math::policies::indeterminate_result_error<::boost::math::policies::user_error> &)600 inline T raise_indeterminate_result_error(
601            const char* function,
602            const char* message,
603            const T& val,
604            const R& ,
605            const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
606 {
607    return user_indeterminate_result_error(function, message, val);
608 }
609 
610 }  // namespace detail
611 
612 template <class T, class Policy>
raise_domain_error(const char * function,const char * message,const T & val,const Policy &)613 inline BOOST_MATH_CONSTEXPR T raise_domain_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
614 {
615    typedef typename Policy::domain_error_type policy_type;
616    return detail::raise_domain_error(
617       function, message ? message : "Domain Error evaluating function at %1%",
618       val, policy_type());
619 }
620 
621 template <class T, class Policy>
raise_pole_error(const char * function,const char * message,const T & val,const Policy &)622 inline BOOST_MATH_CONSTEXPR T raise_pole_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
623 {
624    typedef typename Policy::pole_error_type policy_type;
625    return detail::raise_pole_error(
626       function, message ? message : "Evaluation of function at pole %1%",
627       val, policy_type());
628 }
629 
630 template <class T, class Policy>
raise_overflow_error(const char * function,const char * message,const Policy &)631 inline BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const char* message, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
632 {
633    typedef typename Policy::overflow_error_type policy_type;
634    return detail::raise_overflow_error<T>(
635       function, message ? message : "Overflow Error",
636       policy_type());
637 }
638 
639 template <class T, class Policy>
raise_overflow_error(const char * function,const char * message,const T & val,const Policy &)640 inline BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
641 {
642    typedef typename Policy::overflow_error_type policy_type;
643    return detail::raise_overflow_error(
644       function, message ? message : "Overflow evaluating function at %1%",
645       val, policy_type());
646 }
647 
648 template <class T, class Policy>
raise_underflow_error(const char * function,const char * message,const Policy &)649 inline BOOST_MATH_CONSTEXPR T raise_underflow_error(const char* function, const char* message, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
650 {
651    typedef typename Policy::underflow_error_type policy_type;
652    return detail::raise_underflow_error<T>(
653       function, message ? message : "Underflow Error",
654       policy_type());
655 }
656 
657 template <class T, class Policy>
raise_denorm_error(const char * function,const char * message,const T & val,const Policy &)658 inline BOOST_MATH_CONSTEXPR T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
659 {
660    typedef typename Policy::denorm_error_type policy_type;
661    return detail::raise_denorm_error<T>(
662       function, message ? message : "Denorm Error",
663       val,
664       policy_type());
665 }
666 
667 template <class T, class Policy>
raise_evaluation_error(const char * function,const char * message,const T & val,const Policy &)668 inline BOOST_MATH_CONSTEXPR T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
669 {
670    typedef typename Policy::evaluation_error_type policy_type;
671    return detail::raise_evaluation_error(
672       function, message ? message : "Internal Evaluation Error, best value so far was %1%",
673       val, policy_type());
674 }
675 
676 template <class T, class TargetType, class Policy>
raise_rounding_error(const char * function,const char * message,const T & val,const TargetType & t,const Policy &)677 inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
678 {
679    typedef typename Policy::rounding_error_type policy_type;
680    return detail::raise_rounding_error(
681       function, message ? message : "Value %1% can not be represented in the target integer type.",
682       val, t, policy_type());
683 }
684 
685 template <class T, class R, class Policy>
raise_indeterminate_result_error(const char * function,const char * message,const T & val,const R & result,const Policy &)686 inline BOOST_MATH_CONSTEXPR T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
687 {
688    typedef typename Policy::indeterminate_result_error_type policy_type;
689    return detail::raise_indeterminate_result_error(
690       function, message ? message : "Indeterminate result with value %1%",
691       val, result, policy_type());
692 }
693 
694 //
695 // checked_narrowing_cast:
696 //
697 namespace detail
698 {
699 
700 template <class R, class T, class Policy>
check_overflow(T val,R * result,const char * function,const Policy & pol)701 inline bool check_overflow(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
702 {
703    BOOST_MATH_STD_USING
704    if(fabs(val) > tools::max_value<R>())
705    {
706       boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol);
707       *result = static_cast<R>(val);
708       return true;
709    }
710    return false;
711 }
712 template <class R, class T, class Policy>
check_overflow(std::complex<T> val,R * result,const char * function,const Policy & pol)713 inline bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
714 {
715    typedef typename R::value_type r_type;
716    r_type re, im;
717    bool r = check_overflow<r_type>(val.real(), &re, function, pol);
718    r = check_overflow<r_type>(val.imag(), &im, function, pol) || r;
719    *result = R(re, im);
720    return r;
721 }
722 template <class R, class T, class Policy>
check_underflow(T val,R * result,const char * function,const Policy & pol)723 inline bool check_underflow(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
724 {
725    if((val != 0) && (static_cast<R>(val) == 0))
726    {
727       *result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, 0, pol));
728       return true;
729    }
730    return false;
731 }
732 template <class R, class T, class Policy>
check_underflow(std::complex<T> val,R * result,const char * function,const Policy & pol)733 inline bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
734 {
735    typedef typename R::value_type r_type;
736    r_type re, im;
737    bool r = check_underflow<r_type>(val.real(), &re, function, pol);
738    r = check_underflow<r_type>(val.imag(), &im, function, pol) || r;
739    *result = R(re, im);
740    return r;
741 }
742 template <class R, class T, class Policy>
check_denorm(T val,R * result,const char * function,const Policy & pol)743 inline bool check_denorm(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
744 {
745    BOOST_MATH_STD_USING
746    if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
747    {
748       *result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));
749       return true;
750    }
751    return false;
752 }
753 template <class R, class T, class Policy>
check_denorm(std::complex<T> val,R * result,const char * function,const Policy & pol)754 inline bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
755 {
756    typedef typename R::value_type r_type;
757    r_type re, im;
758    bool r = check_denorm<r_type>(val.real(), &re, function, pol);
759    r = check_denorm<r_type>(val.imag(), &im, function, pol) || r;
760    *result = R(re, im);
761    return r;
762 }
763 
764 // Default instantiations with ignore_error policy.
765 template <class R, class T>
check_overflow(T,R *,const char *,const overflow_error<ignore_error> &)766 inline BOOST_MATH_CONSTEXPR bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
767 { return false; }
768 template <class R, class T>
check_overflow(std::complex<T>,R *,const char *,const overflow_error<ignore_error> &)769 inline BOOST_MATH_CONSTEXPR bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
770 { return false; }
771 template <class R, class T>
check_underflow(T,R *,const char *,const underflow_error<ignore_error> &)772 inline BOOST_MATH_CONSTEXPR bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
773 { return false; }
774 template <class R, class T>
check_underflow(std::complex<T>,R *,const char *,const underflow_error<ignore_error> &)775 inline BOOST_MATH_CONSTEXPR bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
776 { return false; }
777 template <class R, class T>
check_denorm(T,R *,const char *,const denorm_error<ignore_error> &)778 inline BOOST_MATH_CONSTEXPR bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
779 { return false; }
780 template <class R, class T>
check_denorm(std::complex<T>,R *,const char *,const denorm_error<ignore_error> &)781 inline BOOST_MATH_CONSTEXPR bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
782 { return false; }
783 
784 } // namespace detail
785 
786 template <class R, class Policy, class T>
checked_narrowing_cast(T val,const char * function)787 inline R checked_narrowing_cast(T val, const char* function) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
788 {
789    typedef typename Policy::overflow_error_type overflow_type;
790    typedef typename Policy::underflow_error_type underflow_type;
791    typedef typename Policy::denorm_error_type denorm_type;
792    //
793    // Most of what follows will evaluate to a no-op:
794    //
795    R result = 0;
796    if(detail::check_overflow<R>(val, &result, function, overflow_type()))
797       return result;
798    if(detail::check_underflow<R>(val, &result, function, underflow_type()))
799       return result;
800    if(detail::check_denorm<R>(val, &result, function, denorm_type()))
801       return result;
802 
803    return static_cast<R>(val);
804 }
805 
806 template <class T, class Policy>
check_series_iterations(const char * function,boost::uintmax_t max_iter,const Policy & pol)807 inline void check_series_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
808 {
809    if(max_iter >= policies::get_max_series_iterations<Policy>())
810       raise_evaluation_error<T>(
811          function,
812          "Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
813 }
814 
815 template <class T, class Policy>
check_root_iterations(const char * function,boost::uintmax_t max_iter,const Policy & pol)816 inline void check_root_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
817 {
818    if(max_iter >= policies::get_max_root_iterations<Policy>())
819       raise_evaluation_error<T>(
820          function,
821          "Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
822 }
823 
824 } //namespace policies
825 
826 namespace detail{
827 
828 //
829 // Simple helper function to assist in returning a pair from a single value,
830 // that value usually comes from one of the error handlers above:
831 //
832 template <class T>
pair_from_single(const T & val)833 std::pair<T, T> pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T)
834 {
835    return std::make_pair(val, val);
836 }
837 
838 }
839 
840 #ifdef BOOST_MSVC
841 #  pragma warning(pop)
842 #endif
843 
844 }} // namespaces boost/math
845 
846 #endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP
847 
848