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

source code of boost/libs/math/include/boost/math/policies/error_handling.hpp