File indexing completed on 2025-01-18 09:39:48
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
0009 #define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
0010
0011 #include <boost/math/tools/config.hpp>
0012 #include <iomanip>
0013 #include <string>
0014 #include <cstring>
0015 #ifndef BOOST_NO_RTTI
0016 #include <typeinfo>
0017 #endif
0018 #include <cerrno>
0019 #include <complex>
0020 #include <cmath>
0021 #include <cstdint>
0022 #include <boost/math/policies/policy.hpp>
0023 #include <boost/math/tools/precision.hpp>
0024 #ifndef BOOST_NO_EXCEPTIONS
0025 #include <stdexcept>
0026 #include <boost/math/tools/throw_exception.hpp>
0027 #endif
0028
0029 #ifdef _MSC_VER
0030 # pragma warning(push)
0031 # pragma warning(disable: 4996)
0032 # pragma warning(disable: 4512)
0033 # pragma warning(disable: 4127)
0034
0035 # pragma warning(disable: 4702)
0036
0037
0038 #endif
0039 #include <sstream>
0040
0041 namespace boost{ namespace math{
0042
0043 #ifndef BOOST_NO_EXCEPTIONS
0044
0045 class evaluation_error : public std::runtime_error
0046 {
0047 public:
0048 explicit evaluation_error(const std::string& s) : std::runtime_error(s){}
0049 };
0050
0051 class rounding_error : public std::runtime_error
0052 {
0053 public:
0054 explicit rounding_error(const std::string& s) : std::runtime_error(s){}
0055 };
0056
0057 #endif
0058
0059 namespace policies{
0060
0061
0062
0063
0064 template <class T>
0065 T user_domain_error(const char* function, const char* message, const T& val);
0066 template <class T>
0067 T user_pole_error(const char* function, const char* message, const T& val);
0068 template <class T>
0069 T user_overflow_error(const char* function, const char* message, const T& val);
0070 template <class T>
0071 T user_underflow_error(const char* function, const char* message, const T& val);
0072 template <class T>
0073 T user_denorm_error(const char* function, const char* message, const T& val);
0074 template <class T>
0075 T user_evaluation_error(const char* function, const char* message, const T& val);
0076 template <class T, class TargetType>
0077 TargetType user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
0078 template <class T>
0079 T user_indeterminate_result_error(const char* function, const char* message, const T& val);
0080
0081 namespace detail
0082 {
0083
0084 template <class T>
0085 inline std::string prec_format(const T& val)
0086 {
0087 typedef typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type prec_type;
0088 std::stringstream ss;
0089 if(prec_type::value)
0090 {
0091 int prec = 2 + (prec_type::value * 30103UL) / 100000UL;
0092 ss << std::setprecision(prec);
0093 }
0094 ss << val;
0095 return ss.str();
0096 }
0097
0098 #ifdef BOOST_MATH_USE_CHARCONV_FOR_CONVERSION
0099
0100 template <>
0101 inline std::string prec_format<std::float128_t>(const std::float128_t& val)
0102 {
0103 char buffer[128] {};
0104 const auto r = std::to_chars(buffer, buffer + sizeof(buffer), val);
0105 return std::string(buffer, r.ptr);
0106 }
0107
0108 #endif
0109
0110 inline void replace_all_in_string(std::string& result, const char* what, const char* with)
0111 {
0112 std::string::size_type pos = 0;
0113 std::string::size_type slen = std::strlen(what);
0114 std::string::size_type rlen = std::strlen(with);
0115 while((pos = result.find(what, pos)) != std::string::npos)
0116 {
0117 result.replace(pos, slen, with);
0118 pos += rlen;
0119 }
0120 }
0121
0122 template <class T>
0123 inline const char* name_of()
0124 {
0125 #ifndef BOOST_NO_RTTI
0126 return typeid(T).name();
0127 #else
0128 return "unknown";
0129 #endif
0130 }
0131 template <> inline const char* name_of<float>(){ return "float"; }
0132 template <> inline const char* name_of<double>(){ return "double"; }
0133 template <> inline const char* name_of<long double>(){ return "long double"; }
0134
0135 #ifdef BOOST_MATH_USE_FLOAT128
0136 template <>
0137 inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()
0138 {
0139 return "__float128";
0140 }
0141 #endif
0142
0143 #ifndef BOOST_NO_EXCEPTIONS
0144 template <class E, class T>
0145 void raise_error(const char* pfunction, const char* message)
0146 {
0147 if(pfunction == nullptr)
0148 {
0149 pfunction = "Unknown function operating on type %1%";
0150 }
0151 if(message == nullptr)
0152 {
0153 message = "Cause unknown";
0154 }
0155
0156 std::string function(pfunction);
0157 std::string msg("Error in function ");
0158 #ifndef BOOST_NO_RTTI
0159 replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
0160 #else
0161 replace_all_in_string(function, "%1%", "Unknown");
0162 #endif
0163 msg += function;
0164 msg += ": ";
0165 msg += message;
0166
0167 BOOST_MATH_THROW_EXCEPTION(E(msg))
0168 }
0169
0170 template <class E, class T>
0171 void raise_error(const char* pfunction, const char* pmessage, const T& val)
0172 {
0173 if(pfunction == nullptr)
0174 {
0175 pfunction = "Unknown function operating on type %1%";
0176 }
0177 if(pmessage == nullptr)
0178 {
0179 pmessage = "Cause unknown: error caused by bad argument with value %1%";
0180 }
0181
0182 std::string function(pfunction);
0183 std::string message(pmessage);
0184 std::string msg("Error in function ");
0185 #ifndef BOOST_NO_RTTI
0186 replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
0187 #else
0188 replace_all_in_string(function, "%1%", "Unknown");
0189 #endif
0190 msg += function;
0191 msg += ": ";
0192
0193 std::string sval = prec_format(val);
0194 replace_all_in_string(message, "%1%", sval.c_str());
0195 msg += message;
0196
0197 BOOST_MATH_THROW_EXCEPTION(E(msg))
0198 }
0199 #endif
0200
0201 template <class T>
0202 inline T raise_domain_error(
0203 const char* function,
0204 const char* message,
0205 const T& val,
0206 const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
0207 {
0208 #ifdef BOOST_NO_EXCEPTIONS
0209 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0210 #else
0211 raise_error<std::domain_error, T>(function, message, val);
0212
0213 return std::numeric_limits<T>::quiet_NaN();
0214 #endif
0215 }
0216
0217 template <class T>
0218 inline constexpr T raise_domain_error(
0219 const char* ,
0220 const char* ,
0221 const T& ,
0222 const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0223 {
0224
0225
0226 return std::numeric_limits<T>::quiet_NaN();
0227 }
0228
0229 template <class T>
0230 inline T raise_domain_error(
0231 const char* ,
0232 const char* ,
0233 const T& ,
0234 const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
0235 {
0236 errno = EDOM;
0237
0238
0239 return std::numeric_limits<T>::quiet_NaN();
0240 }
0241
0242 template <class T>
0243 inline T raise_domain_error(
0244 const char* function,
0245 const char* message,
0246 const T& val,
0247 const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
0248 {
0249 return user_domain_error(function, message, val);
0250 }
0251
0252 template <class T>
0253 inline T raise_pole_error(
0254 const char* function,
0255 const char* message,
0256 const T& val,
0257 const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
0258 {
0259 #ifdef BOOST_NO_EXCEPTIONS
0260 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0261 #else
0262 return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
0263 #endif
0264 }
0265
0266 template <class T>
0267 inline constexpr T raise_pole_error(
0268 const char* function,
0269 const char* message,
0270 const T& val,
0271 const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0272 {
0273 return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
0274 }
0275
0276 template <class T>
0277 inline constexpr T raise_pole_error(
0278 const char* function,
0279 const char* message,
0280 const T& val,
0281 const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
0282 {
0283 return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
0284 }
0285
0286 template <class T>
0287 inline T raise_pole_error(
0288 const char* function,
0289 const char* message,
0290 const T& val,
0291 const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
0292 {
0293 return user_pole_error(function, message, val);
0294 }
0295
0296 template <class T>
0297 inline T raise_overflow_error(
0298 const char* function,
0299 const char* message,
0300 const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
0301 {
0302 #ifdef BOOST_NO_EXCEPTIONS
0303 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0304 #else
0305 raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
0306
0307 return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
0308 #endif
0309 }
0310
0311 template <class T>
0312 inline T raise_overflow_error(
0313 const char* function,
0314 const char* message,
0315 const T& val,
0316 const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
0317 {
0318 #ifdef BOOST_NO_EXCEPTIONS
0319 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0320 #else
0321 raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow", val);
0322
0323 return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
0324 #endif
0325 }
0326
0327 template <class T>
0328 inline constexpr T raise_overflow_error(
0329 const char* ,
0330 const char* ,
0331 const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0332 {
0333
0334
0335 return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
0336 }
0337
0338 template <class T>
0339 inline constexpr T raise_overflow_error(
0340 const char* ,
0341 const char* ,
0342 const T&,
0343 const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0344 {
0345
0346
0347 return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
0348 }
0349
0350 template <class T>
0351 inline T raise_overflow_error(
0352 const char* ,
0353 const char* ,
0354 const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
0355 {
0356 errno = ERANGE;
0357
0358
0359 return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
0360 }
0361
0362 template <class T>
0363 inline T raise_overflow_error(
0364 const char* ,
0365 const char* ,
0366 const T&,
0367 const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
0368 {
0369 errno = ERANGE;
0370
0371
0372 return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
0373 }
0374
0375 template <class T>
0376 inline T raise_overflow_error(
0377 const char* function,
0378 const char* message,
0379 const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
0380 {
0381 return user_overflow_error(function, message, std::numeric_limits<T>::infinity());
0382 }
0383
0384 template <class T>
0385 inline T raise_overflow_error(
0386 const char* function,
0387 const char* message,
0388 const T& val,
0389 const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
0390 {
0391 std::string m(message ? message : "");
0392 std::string sval = prec_format(val);
0393 replace_all_in_string(m, "%1%", sval.c_str());
0394
0395 return user_overflow_error(function, m.c_str(), std::numeric_limits<T>::infinity());
0396 }
0397
0398 template <class T>
0399 inline T raise_underflow_error(
0400 const char* function,
0401 const char* message,
0402 const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
0403 {
0404 #ifdef BOOST_NO_EXCEPTIONS
0405 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0406 #else
0407 raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
0408
0409 return 0;
0410 #endif
0411 }
0412
0413 template <class T>
0414 inline constexpr T raise_underflow_error(
0415 const char* ,
0416 const char* ,
0417 const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0418 {
0419
0420
0421 return T(0);
0422 }
0423
0424 template <class T>
0425 inline T raise_underflow_error(
0426 const char* ,
0427 const char* ,
0428 const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
0429 {
0430 errno = ERANGE;
0431
0432
0433 return T(0);
0434 }
0435
0436 template <class T>
0437 inline T raise_underflow_error(
0438 const char* function,
0439 const char* message,
0440 const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
0441 {
0442 return user_underflow_error(function, message, T(0));
0443 }
0444
0445 template <class T>
0446 inline T raise_denorm_error(
0447 const char* function,
0448 const char* message,
0449 const T& ,
0450 const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
0451 {
0452 #ifdef BOOST_NO_EXCEPTIONS
0453 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0454 #else
0455 raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
0456
0457 return T(0);
0458 #endif
0459 }
0460
0461 template <class T>
0462 inline constexpr T raise_denorm_error(
0463 const char* ,
0464 const char* ,
0465 const T& val,
0466 const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0467 {
0468
0469
0470 return val;
0471 }
0472
0473 template <class T>
0474 inline T raise_denorm_error(
0475 const char* ,
0476 const char* ,
0477 const T& val,
0478 const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
0479 {
0480 errno = ERANGE;
0481
0482
0483 return val;
0484 }
0485
0486 template <class T>
0487 inline T raise_denorm_error(
0488 const char* function,
0489 const char* message,
0490 const T& val,
0491 const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
0492 {
0493 return user_denorm_error(function, message, val);
0494 }
0495
0496 template <class T>
0497 inline T raise_evaluation_error(
0498 const char* function,
0499 const char* message,
0500 const T& val,
0501 const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
0502 {
0503 #ifdef BOOST_NO_EXCEPTIONS
0504 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0505 #else
0506 raise_error<boost::math::evaluation_error, T>(function, message, val);
0507
0508 return T(0);
0509 #endif
0510 }
0511
0512 template <class T>
0513 inline constexpr T raise_evaluation_error(
0514 const char* ,
0515 const char* ,
0516 const T& val,
0517 const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0518 {
0519
0520
0521 return val;
0522 }
0523
0524 template <class T>
0525 inline T raise_evaluation_error(
0526 const char* ,
0527 const char* ,
0528 const T& val,
0529 const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
0530 {
0531 errno = EDOM;
0532
0533
0534 return val;
0535 }
0536
0537 template <class T>
0538 inline T raise_evaluation_error(
0539 const char* function,
0540 const char* message,
0541 const T& val,
0542 const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
0543 {
0544 return user_evaluation_error(function, message, val);
0545 }
0546
0547 template <class T, class TargetType>
0548 inline TargetType raise_rounding_error(
0549 const char* function,
0550 const char* message,
0551 const T& val,
0552 const TargetType&,
0553 const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
0554 {
0555 #ifdef BOOST_NO_EXCEPTIONS
0556 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0557 #else
0558 raise_error<boost::math::rounding_error, T>(function, message, val);
0559
0560 return TargetType(0);
0561 #endif
0562 }
0563
0564 template <class T, class TargetType>
0565 inline constexpr TargetType raise_rounding_error(
0566 const char* ,
0567 const char* ,
0568 const T& val,
0569 const TargetType&,
0570 const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0571 {
0572
0573
0574 static_assert(std::numeric_limits<TargetType>::is_specialized, "The target type must have std::numeric_limits specialized.");
0575 return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
0576 }
0577
0578 template <class T, class TargetType>
0579 inline TargetType raise_rounding_error(
0580 const char* ,
0581 const char* ,
0582 const T& val,
0583 const TargetType&,
0584 const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
0585 {
0586 errno = ERANGE;
0587
0588
0589 static_assert(std::numeric_limits<TargetType>::is_specialized, "The target type must have std::numeric_limits specialized.");
0590 return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
0591 }
0592 template <class T, class TargetType>
0593 inline TargetType raise_rounding_error(
0594 const char* function,
0595 const char* message,
0596 const T& val,
0597 const TargetType& t,
0598 const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
0599 {
0600 return user_rounding_error(function, message, val, t);
0601 }
0602
0603 template <class T, class R>
0604 inline T raise_indeterminate_result_error(
0605 const char* function,
0606 const char* message,
0607 const T& val,
0608 const R& ,
0609 const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
0610 {
0611 #ifdef BOOST_NO_EXCEPTIONS
0612 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_NO_EXCEPTIONS set.");
0613 #else
0614 raise_error<std::domain_error, T>(function, message, val);
0615
0616 return std::numeric_limits<T>::quiet_NaN();
0617 #endif
0618 }
0619
0620 template <class T, class R>
0621 inline constexpr T raise_indeterminate_result_error(
0622 const char* ,
0623 const char* ,
0624 const T& ,
0625 const R& result,
0626 const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
0627 {
0628
0629
0630 return result;
0631 }
0632
0633 template <class T, class R>
0634 inline T raise_indeterminate_result_error(
0635 const char* ,
0636 const char* ,
0637 const T& ,
0638 const R& result,
0639 const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)
0640 {
0641 errno = EDOM;
0642
0643
0644 return result;
0645 }
0646
0647 template <class T, class R>
0648 inline T raise_indeterminate_result_error(
0649 const char* function,
0650 const char* message,
0651 const T& val,
0652 const R& ,
0653 const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
0654 {
0655 return user_indeterminate_result_error(function, message, val);
0656 }
0657
0658 }
0659
0660 template <class T, class Policy>
0661 inline 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))
0662 {
0663 typedef typename Policy::domain_error_type policy_type;
0664 return detail::raise_domain_error(
0665 function, message ? message : "Domain Error evaluating function at %1%",
0666 val, policy_type());
0667 }
0668
0669 template <class T, class Policy>
0670 inline 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))
0671 {
0672 typedef typename Policy::pole_error_type policy_type;
0673 return detail::raise_pole_error(
0674 function, message ? message : "Evaluation of function at pole %1%",
0675 val, policy_type());
0676 }
0677
0678 template <class T, class Policy>
0679 inline 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))
0680 {
0681 typedef typename Policy::overflow_error_type policy_type;
0682 return detail::raise_overflow_error<T>(
0683 function, message ? message : "Overflow Error",
0684 policy_type());
0685 }
0686
0687 template <class T, class Policy>
0688 inline 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))
0689 {
0690 typedef typename Policy::overflow_error_type policy_type;
0691 return detail::raise_overflow_error(
0692 function, message ? message : "Overflow evaluating function at %1%",
0693 val, policy_type());
0694 }
0695
0696 template <class T, class Policy>
0697 inline 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))
0698 {
0699 typedef typename Policy::underflow_error_type policy_type;
0700 return detail::raise_underflow_error<T>(
0701 function, message ? message : "Underflow Error",
0702 policy_type());
0703 }
0704
0705 template <class T, class Policy>
0706 inline 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))
0707 {
0708 typedef typename Policy::denorm_error_type policy_type;
0709 return detail::raise_denorm_error<T>(
0710 function, message ? message : "Denorm Error",
0711 val,
0712 policy_type());
0713 }
0714
0715 template <class T, class Policy>
0716 inline 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))
0717 {
0718 typedef typename Policy::evaluation_error_type policy_type;
0719 return detail::raise_evaluation_error(
0720 function, message ? message : "Internal Evaluation Error, best value so far was %1%",
0721 val, policy_type());
0722 }
0723
0724 template <class T, class TargetType, class Policy>
0725 inline 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))
0726 {
0727 typedef typename Policy::rounding_error_type policy_type;
0728 return detail::raise_rounding_error(
0729 function, message ? message : "Value %1% can not be represented in the target integer type.",
0730 val, t, policy_type());
0731 }
0732
0733 template <class T, class R, class Policy>
0734 inline 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))
0735 {
0736 typedef typename Policy::indeterminate_result_error_type policy_type;
0737 return detail::raise_indeterminate_result_error(
0738 function, message ? message : "Indeterminate result with value %1%",
0739 val, result, policy_type());
0740 }
0741
0742
0743
0744
0745 namespace detail
0746 {
0747
0748 template <class R, class T, class Policy>
0749 BOOST_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))
0750 {
0751 BOOST_MATH_STD_USING
0752 if(fabs(val) > tools::max_value<R>())
0753 {
0754 boost::math::policies::detail::raise_overflow_error<R>(function, nullptr, pol);
0755 *result = static_cast<R>(val);
0756 return true;
0757 }
0758 return false;
0759 }
0760 template <class R, class T, class Policy>
0761 BOOST_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))
0762 {
0763 typedef typename R::value_type r_type;
0764 r_type re, im;
0765 bool r = check_overflow<r_type>(val.real(), &re, function, pol);
0766 r = check_overflow<r_type>(val.imag(), &im, function, pol) || r;
0767 *result = R(re, im);
0768 return r;
0769 }
0770 template <class R, class T, class Policy>
0771 BOOST_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))
0772 {
0773 if((val != 0) && (static_cast<R>(val) == 0))
0774 {
0775 *result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, nullptr, pol));
0776 return true;
0777 }
0778 return false;
0779 }
0780 template <class R, class T, class Policy>
0781 BOOST_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))
0782 {
0783 typedef typename R::value_type r_type;
0784 r_type re, im;
0785 bool r = check_underflow<r_type>(val.real(), &re, function, pol);
0786 r = check_underflow<r_type>(val.imag(), &im, function, pol) || r;
0787 *result = R(re, im);
0788 return r;
0789 }
0790 template <class R, class T, class Policy>
0791 BOOST_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))
0792 {
0793 BOOST_MATH_STD_USING
0794 if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
0795 {
0796 *result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));
0797 return true;
0798 }
0799 return false;
0800 }
0801 template <class R, class T, class Policy>
0802 BOOST_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))
0803 {
0804 typedef typename R::value_type r_type;
0805 r_type re, im;
0806 bool r = check_denorm<r_type>(val.real(), &re, function, pol);
0807 r = check_denorm<r_type>(val.imag(), &im, function, pol) || r;
0808 *result = R(re, im);
0809 return r;
0810 }
0811
0812
0813 template <class R, class T>
0814 BOOST_FORCEINLINE constexpr bool check_overflow(T , R* , const char* , const overflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
0815 { return false; }
0816 template <class R, class T>
0817 BOOST_FORCEINLINE constexpr bool check_overflow(std::complex<T> , R* , const char* , const overflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
0818 { return false; }
0819 template <class R, class T>
0820 BOOST_FORCEINLINE constexpr bool check_underflow(T , R* , const char* , const underflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
0821 { return false; }
0822 template <class R, class T>
0823 BOOST_FORCEINLINE constexpr bool check_underflow(std::complex<T> , R* , const char* , const underflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
0824 { return false; }
0825 template <class R, class T>
0826 BOOST_FORCEINLINE constexpr bool check_denorm(T , R* , const char* , const denorm_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
0827 { return false; }
0828 template <class R, class T>
0829 BOOST_FORCEINLINE constexpr bool check_denorm(std::complex<T> , R* , const char* , const denorm_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
0830 { return false; }
0831
0832 }
0833
0834 template <class R, class Policy, class T>
0835 BOOST_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)
0836 {
0837 typedef typename Policy::overflow_error_type overflow_type;
0838 typedef typename Policy::underflow_error_type underflow_type;
0839 typedef typename Policy::denorm_error_type denorm_type;
0840
0841
0842
0843 R result = 0;
0844 if(detail::check_overflow<R>(val, &result, function, overflow_type()))
0845 return result;
0846 if(detail::check_underflow<R>(val, &result, function, underflow_type()))
0847 return result;
0848 if(detail::check_denorm<R>(val, &result, function, denorm_type()))
0849 return result;
0850
0851 return static_cast<R>(val);
0852 }
0853
0854 template <class T, class Policy>
0855 inline 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)
0856 {
0857 if(max_iter >= policies::get_max_series_iterations<Policy>())
0858 raise_evaluation_error<T>(
0859 function,
0860 "Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
0861 }
0862
0863 template <class T, class Policy>
0864 inline 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)
0865 {
0866 if(max_iter >= policies::get_max_root_iterations<Policy>())
0867 raise_evaluation_error<T>(
0868 function,
0869 "Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
0870 }
0871
0872 }
0873
0874 namespace detail{
0875
0876
0877
0878
0879
0880 template <class T>
0881 std::pair<T, T> pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T)
0882 {
0883 return std::make_pair(val, val);
0884 }
0885
0886 }
0887
0888 #ifdef _MSC_VER
0889 # pragma warning(pop)
0890 #endif
0891
0892 }}
0893
0894 #endif
0895