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
37namespace boost{ namespace math{
38
39class evaluation_error : public std::runtime_error
40{
41public:
42 evaluation_error(const std::string& s) : std::runtime_error(s){}
43};
44
45class rounding_error : public std::runtime_error
46{
47public:
48 rounding_error(const std::string& s) : std::runtime_error(s){}
49};
50
51namespace policies{
52//
53// Forward declarations of user error handlers,
54// it's up to the user to provide the definition of these:
55//
56template <class T>
57T user_domain_error(const char* function, const char* message, const T& val);
58template <class T>
59T user_pole_error(const char* function, const char* message, const T& val);
60template <class T>
61T user_overflow_error(const char* function, const char* message, const T& val);
62template <class T>
63T user_underflow_error(const char* function, const char* message, const T& val);
64template <class T>
65T user_denorm_error(const char* function, const char* message, const T& val);
66template <class T>
67T user_evaluation_error(const char* function, const char* message, const T& val);
68template <class T, class TargetType>
69T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
70template <class T>
71T user_indeterminate_result_error(const char* function, const char* message, const T& val);
72
73namespace detail
74{
75
76template <class T>
77std::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
90inline 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(s: what);
94 std::string::size_type rlen = std::strlen(s: with);
95 while((pos = result.find(s: what, pos: pos)) != std::string::npos)
96 {
97 result.replace(pos: pos, n1: slen, s: with);
98 pos += rlen;
99 }
100}
101
102template <class T>
103inline const char* name_of()
104{
105#ifndef BOOST_NO_RTTI
106 return typeid(T).name();
107#else
108 return "unknown";
109#endif
110}
111template <> inline const char* name_of<float>(){ return "float"; }
112template <> inline const char* name_of<double>(){ return "double"; }
113template <> inline const char* name_of<long double>(){ return "long double"; }
114
115#ifdef BOOST_MATH_USE_FLOAT128
116template <>
117inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()
118{
119 return "__float128";
120}
121#endif
122
123template <class E, class T>
124void 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
146template <class E, class T>
147void 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(result&: message, what: "%1%", with: sval.c_str());
167 msg += message;
168
169 E e(msg);
170 boost::throw_exception(e);
171}
172
173template <class T>
174inline 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
185template <class T>
186inline 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
197template <class T>
198inline 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
210template <class T>
211inline 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
220template <class T>
221inline 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
230template <class T>
231inline 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
240template <class T>
241inline 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
250template <class T>
251inline 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
261template <class T>
262inline 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
272template <class T>
273inline 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
284template <class T>
285inline 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
295template <class T>
296inline 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
307template <class T>
308inline 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
319template <class T>
320inline 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
332template <class T>
333inline 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
341template <class T>
342inline 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(result&: m, what: "%1%", with: sval.c_str());
351
352 return user_overflow_error(function, m.c_str(), std::numeric_limits<T>::infinity());
353}
354
355template <class T>
356inline 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
366template <class T>
367inline 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
377template <class T>
378inline 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
389template <class T>
390inline 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
398template <class T>
399inline 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
410template <class T>
411inline 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
422template <class T>
423inline 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
435template <class T>
436inline 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
445template <class T>
446inline 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
457template <class T>
458inline 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
469template <class T>
470inline 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
482template <class T>
483inline 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
492template <class T, class TargetType>
493inline 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
505template <class T, class TargetType>
506inline 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
519template <class T, class TargetType>
520inline 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
534template <class T>
535inline 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
548template <class T, class TargetType>
549inline 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
559template <class T, class R>
560inline 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
572template <class T, class R>
573inline 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
585template <class T, class R>
586inline 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
599template <class T, class R>
600inline 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
612template <class T, class Policy>
613inline 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
621template <class T, class Policy>
622inline 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
630template <class T, class Policy>
631inline 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
639template <class T, class Policy>
640inline 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
648template <class T, class Policy>
649inline 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
657template <class T, class Policy>
658inline 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
667template <class T, class Policy>
668inline 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
676template <class T, class TargetType, class Policy>
677inline 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
685template <class T, class R, class Policy>
686inline 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//
697namespace detail
698{
699
700template <class R, class T, class Policy>
701inline 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}
712template <class R, class T, class Policy>
713inline 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}
722template <class R, class T, class Policy>
723inline 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}
732template <class R, class T, class Policy>
733inline 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}
742template <class R, class T, class Policy>
743inline 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}
753template <class R, class T, class Policy>
754inline 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.
765template <class R, class T>
766inline 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; }
768template <class R, class T>
769inline 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; }
771template <class R, class T>
772inline 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; }
774template <class R, class T>
775inline 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; }
777template <class R, class T>
778inline 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; }
780template <class R, class T>
781inline 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
786template <class R, class Policy, class T>
787inline 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
806template <class T, class Policy>
807inline 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
815template <class T, class Policy>
816inline 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
826namespace 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//
832template <class T>
833std::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

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