1059 lines · plain
1// Copyright John Maddock 2007.2// Copyright Paul A. Bristow 2007.3// Copyright Matt Borland 2024.4// Use, modification and distribution are subject to the5// Boost Software License, Version 1.0. (See accompanying file6// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)7 8#ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP9#define BOOST_MATH_POLICY_ERROR_HANDLING_HPP10 11#include <boost/math/policies/policy.hpp>12#include <boost/math/tools/config.hpp>13#include <boost/math/tools/numeric_limits.hpp>14#include <boost/math/tools/precision.hpp>15#include <boost/math/tools/tuple.hpp>16#include <boost/math/tools/type_traits.hpp>17 18#ifndef BOOST_MATH_HAS_NVRTC19 20#ifndef BOOST_MATH_NO_EXCEPTIONS21#include <boost/math/tools/throw_exception.hpp>22#endif23 24#include <cerrno>25#include <cmath>26#include <complex>27#include <cstdint>28#include <cstring>29#include <iomanip>30#include <sstream>31#ifndef BOOST_MATH_NO_EXCEPTIONS32#include <stdexcept>33#endif34#include <string>35#ifndef BOOST_MATH_NO_RTTI36#include <typeinfo>37#endif38 39#ifdef _MSC_VER40# pragma warning(push) // Quiet warnings in boost/format.hpp41# pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE42# pragma warning(disable: 4512) // assignment operator could not be generated.43# pragma warning(disable: 4127) // conditional expression is constant44// And warnings in error handling:45# pragma warning(disable: 4702) // unreachable code.46// Note that this only occurs when the compiler can deduce code is unreachable,47// for example when policy macros are used to ignore errors rather than throw.48#endif49 50namespace boost{ namespace math{51 52#ifndef BOOST_MATH_NO_EXCEPTIONS53 54class evaluation_error : public std::runtime_error55{56public:57 explicit evaluation_error(const std::string& s) : std::runtime_error(s){}58};59 60class rounding_error : public std::runtime_error61{62public:63 explicit rounding_error(const std::string& s) : std::runtime_error(s){}64};65 66#else67 68class evaluation_error {};69class rounding_error {};70 71#endif72 73namespace policies{74//75// Forward declarations of user error handlers,76// it's up to the user to provide the definition of these:77//78template <class T>79T user_domain_error(const char* function, const char* message, const T& val);80template <class T>81T user_pole_error(const char* function, const char* message, const T& val);82template <class T>83T user_overflow_error(const char* function, const char* message, const T& val);84template <class T>85T user_underflow_error(const char* function, const char* message, const T& val);86template <class T>87T user_denorm_error(const char* function, const char* message, const T& val);88template <class T>89T user_evaluation_error(const char* function, const char* message, const T& val);90template <class T, class TargetType>91TargetType user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);92template <class T>93T user_indeterminate_result_error(const char* function, const char* message, const T& val);94 95namespace detail96{97 98template <class T>99inline std::string prec_format(const T& val)100{101 using prec_type = typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type;102 103 std::stringstream strm { };104 105 if(prec_type::value)106 {107 const std::streamsize prec { static_cast<std::streamsize>(2UL + (prec_type::value * 30103UL) / 100000UL) };108 109 strm << std::setprecision(prec);110 }111 112 strm << val;113 114 return strm.str();115}116 117#ifdef BOOST_MATH_USE_CHARCONV_FOR_CONVERSION118 119template <>120inline std::string prec_format<std::float128_t>(const std::float128_t& val)121{122 char buffer[128] {};123 const auto r = std::to_chars(buffer, buffer + sizeof(buffer), val);124 return std::string(buffer, r.ptr);125}126 127#endif128 129inline void replace_all_in_string(std::string& result, const char* what, const char* with)130{131 std::string::size_type pos = 0;132 std::string::size_type slen = std::strlen(what);133 std::string::size_type rlen = std::strlen(with);134 while((pos = result.find(what, pos)) != std::string::npos)135 {136 result.replace(pos, slen, with);137 pos += rlen;138 }139}140 141template <class T>142inline const char* name_of()143{144#ifndef BOOST_MATH_NO_RTTI145 return typeid(T).name();146#else147 return "unknown";148#endif149}150template <> inline const char* name_of<float>(){ return "float"; }151template <> inline const char* name_of<double>(){ return "double"; }152template <> inline const char* name_of<long double>(){ return "long double"; }153 154#ifdef BOOST_MATH_USE_FLOAT128155template <>156inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()157{158 return "__float128";159}160#endif161 162#ifndef BOOST_MATH_NO_EXCEPTIONS163template <class E, class T>164void raise_error(const char* pfunction, const char* message)165{166 if(pfunction == nullptr)167 {168 pfunction = "Unknown function operating on type %1%";169 }170 if(message == nullptr)171 {172 message = "Cause unknown";173 }174 175 std::string function(pfunction);176 std::string msg("Error in function ");177#ifndef BOOST_MATH_NO_RTTI178 replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());179#else180 replace_all_in_string(function, "%1%", "Unknown");181#endif182 msg += function;183 msg += ": ";184 msg += message;185 186 BOOST_MATH_THROW_EXCEPTION(E(msg))187}188 189template <class E, class T>190void raise_error(const char* pfunction, const char* pmessage, const T& val)191{192 if(pfunction == nullptr)193 {194 pfunction = "Unknown function operating on type %1%";195 }196 if(pmessage == nullptr)197 {198 pmessage = "Cause unknown: error caused by bad argument with value %1%";199 }200 201 std::string function(pfunction);202 std::string message(pmessage);203 std::string msg("Error in function ");204#ifndef BOOST_MATH_NO_RTTI205 replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());206#else207 replace_all_in_string(function, "%1%", "Unknown");208#endif209 msg += function;210 msg += ": ";211 212 std::string sval = prec_format(val);213 replace_all_in_string(message, "%1%", sval.c_str());214 msg += message;215 216 BOOST_MATH_THROW_EXCEPTION(E(msg))217}218#endif219 220template <class T>221BOOST_MATH_GPU_ENABLED inline T raise_domain_error(222 const char* function,223 const char* message,224 const T& val,225 const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)226{227#ifdef BOOST_MATH_NO_EXCEPTIONS228 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");229#else230 raise_error<std::domain_error, T>(function, message, val);231 // we never get here:232 return boost::math::numeric_limits<T>::quiet_NaN();233#endif234}235 236template <class T>237BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error(238 const char* ,239 const char* ,240 const T& ,241 const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)242{243 // This may or may not do the right thing, but the user asked for the error244 // to be ignored so here we go anyway:245 return boost::math::numeric_limits<T>::quiet_NaN();246}247 248template <class T>249BOOST_MATH_GPU_ENABLED inline T raise_domain_error(250 const char* ,251 const char* ,252 const T& ,253 const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)254{255 errno = EDOM;256 // This may or may not do the right thing, but the user asked for the error257 // to be silent so here we go anyway:258 return boost::math::numeric_limits<T>::quiet_NaN();259}260 261template <class T>262BOOST_MATH_GPU_ENABLED inline T raise_domain_error(263 const char* function,264 const char* message,265 const T& val,266 const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)267{268 return user_domain_error(function, message, val);269}270 271template <class T>272BOOST_MATH_GPU_ENABLED inline T raise_pole_error(273 const char* function,274 const char* message,275 const T& val,276 const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)277{278#ifdef BOOST_MATH_NO_EXCEPTIONS279 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");280#else281 return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());282#endif283}284 285template <class T>286BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(287 const char* function,288 const char* message,289 const T& val,290 const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)291{292 return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());293}294 295template <class T>296BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(297 const char* function,298 const char* message,299 const T& val,300 const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)301{302 return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());303}304 305template <class T>306BOOST_MATH_GPU_ENABLED inline T raise_pole_error(307 const char* function,308 const char* message,309 const T& val,310 const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)311{312 return user_pole_error(function, message, val);313}314 315template <class T>316BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(317 const char* function,318 const char* message,319 const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)320{321#ifdef BOOST_MATH_NO_EXCEPTIONS322 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");323#else324 raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");325 // We should never get here:326 return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();327#endif328}329 330template <class T>331BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(332 const char* function,333 const char* message,334 const T& val,335 const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)336{337#ifdef BOOST_MATH_NO_EXCEPTIONS338 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");339#else340 raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow", val);341 // We should never get here:342 return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();343#endif344}345 346template <class T>347BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(348 const char* ,349 const char* ,350 const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)351{352 // This may or may not do the right thing, but the user asked for the error353 // to be ignored so here we go anyway:354 return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();355}356 357template <class T>358BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(359 const char* ,360 const char* ,361 const T&,362 const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)363{364 // This may or may not do the right thing, but the user asked for the error365 // to be ignored so here we go anyway:366 return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();367}368 369template <class T>370BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(371 const char* ,372 const char* ,373 const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)374{375 errno = ERANGE;376 // This may or may not do the right thing, but the user asked for the error377 // to be silent so here we go anyway:378 return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();379}380 381template <class T>382BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(383 const char* ,384 const char* ,385 const T&,386 const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)387{388 errno = ERANGE;389 // This may or may not do the right thing, but the user asked for the error390 // to be silent so here we go anyway:391 return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();392}393 394template <class T>395BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(396 const char* function,397 const char* message,398 const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)399{400 return user_overflow_error(function, message, boost::math::numeric_limits<T>::infinity());401}402 403template <class T>404BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(405 const char* function,406 const char* message,407 const T& val,408 const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)409{410 std::string m(message ? message : "");411 std::string sval = prec_format(val);412 replace_all_in_string(m, "%1%", sval.c_str());413 414 return user_overflow_error(function, m.c_str(), boost::math::numeric_limits<T>::infinity());415}416 417template <class T>418BOOST_MATH_GPU_ENABLED inline T raise_underflow_error(419 const char* function,420 const char* message,421 const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)422{423#ifdef BOOST_MATH_NO_EXCEPTIONS424 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");425#else426 raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");427 // We should never get here:428 return 0;429#endif430}431 432template <class T>433BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error(434 const char* ,435 const char* ,436 const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)437{438 // This may or may not do the right thing, but the user asked for the error439 // to be ignored so here we go anyway:440 return T(0);441}442 443template <class T>444BOOST_MATH_GPU_ENABLED inline T raise_underflow_error(445 const char* /* function */,446 const char* /* message */,447 const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)448{449 errno = ERANGE;450 // This may or may not do the right thing, but the user asked for the error451 // to be silent so here we go anyway:452 return T(0);453}454 455template <class T>456BOOST_MATH_GPU_ENABLED inline T raise_underflow_error(457 const char* function,458 const char* message,459 const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)460{461 return user_underflow_error(function, message, T(0));462}463 464template <class T>465BOOST_MATH_GPU_ENABLED inline T raise_denorm_error(466 const char* function,467 const char* message,468 const T& /* val */,469 const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)470{471#ifdef BOOST_MATH_NO_EXCEPTIONS472 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");473#else474 raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");475 // we never get here:476 return T(0);477#endif478}479 480template <class T>481BOOST_MATH_GPU_ENABLED inline constexpr T raise_denorm_error(482 const char* ,483 const char* ,484 const T& val,485 const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)486{487 // This may or may not do the right thing, but the user asked for the error488 // to be ignored so here we go anyway:489 return val;490}491 492template <class T>493BOOST_MATH_GPU_ENABLED inline T raise_denorm_error(494 const char* ,495 const char* ,496 const T& val,497 const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)498{499 errno = ERANGE;500 // This may or may not do the right thing, but the user asked for the error501 // to be silent so here we go anyway:502 return val;503}504 505template <class T>506BOOST_MATH_GPU_ENABLED inline T raise_denorm_error(507 const char* function,508 const char* message,509 const T& val,510 const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)511{512 return user_denorm_error(function, message, val);513}514 515template <class T>516BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error(517 const char* function,518 const char* message,519 const T& val,520 const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)521{522#ifdef BOOST_MATH_NO_EXCEPTIONS523 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");524#else525 raise_error<boost::math::evaluation_error, T>(function, message, val);526 // we never get here:527 return T(0);528#endif529}530 531template <class T>532BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error(533 const char* ,534 const char* ,535 const T& val,536 const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)537{538 // This may or may not do the right thing, but the user asked for the error539 // to be ignored so here we go anyway:540 return val;541}542 543template <class T>544BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error(545 const char* ,546 const char* ,547 const T& val,548 const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)549{550 errno = EDOM;551 // This may or may not do the right thing, but the user asked for the error552 // to be silent so here we go anyway:553 return val;554}555 556template <class T>557BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error(558 const char* function,559 const char* message,560 const T& val,561 const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)562{563 return user_evaluation_error(function, message, val);564}565 566template <class T, class TargetType>567BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error(568 const char* function,569 const char* message,570 const T& val,571 const TargetType&,572 const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)573{574#ifdef BOOST_MATH_NO_EXCEPTIONS575 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");576#else577 raise_error<boost::math::rounding_error, T>(function, message, val);578 // we never get here:579 return TargetType(0);580#endif581}582 583template <class T, class TargetType>584BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error(585 const char* ,586 const char* ,587 const T& val,588 const TargetType&,589 const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)590{591 // This may or may not do the right thing, but the user asked for the error592 // to be ignored so here we go anyway:593 static_assert(boost::math::numeric_limits<TargetType>::is_specialized, "The target type must have std::numeric_limits specialized.");594 return val > 0 ? (boost::math::numeric_limits<TargetType>::max)() : (boost::math::numeric_limits<TargetType>::is_integer ? (boost::math::numeric_limits<TargetType>::min)() : -(boost::math::numeric_limits<TargetType>::max)());595}596 597template <class T, class TargetType>598BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error(599 const char* ,600 const char* ,601 const T& val,602 const TargetType&,603 const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)604{605 errno = ERANGE;606 // This may or may not do the right thing, but the user asked for the error607 // to be silent so here we go anyway:608 static_assert(boost::math::numeric_limits<TargetType>::is_specialized, "The target type must have std::numeric_limits specialized.");609 return val > 0 ? (boost::math::numeric_limits<TargetType>::max)() : (boost::math::numeric_limits<TargetType>::is_integer ? (boost::math::numeric_limits<TargetType>::min)() : -(boost::math::numeric_limits<TargetType>::max)());610}611template <class T, class TargetType>612BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error(613 const char* function,614 const char* message,615 const T& val,616 const TargetType& t,617 const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)618{619 return user_rounding_error(function, message, val, t);620}621 622template <class T, class R>623BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error(624 const char* function,625 const char* message,626 const T& val,627 const R& ,628 const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)629{630#ifdef BOOST_MATH_NO_EXCEPTIONS631 static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");632#else633 raise_error<std::domain_error, T>(function, message, val);634 // we never get here:635 return boost::math::numeric_limits<T>::quiet_NaN();636#endif637}638 639template <class T, class R>640BOOST_MATH_GPU_ENABLED inline constexpr T raise_indeterminate_result_error(641 const char* ,642 const char* ,643 const T& ,644 const R& result,645 const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)646{647 // This may or may not do the right thing, but the user asked for the error648 // to be ignored so here we go anyway:649 return result;650}651 652template <class T, class R>653BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error(654 const char* ,655 const char* ,656 const T& ,657 const R& result,658 const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)659{660 errno = EDOM;661 // This may or may not do the right thing, but the user asked for the error662 // to be silent so here we go anyway:663 return result;664}665 666template <class T, class R>667BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error(668 const char* function,669 const char* message,670 const T& val,671 const R& ,672 const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)673{674 return user_indeterminate_result_error(function, message, val);675}676 677} // namespace detail678 679template <class T, class Policy>680BOOST_MATH_GPU_ENABLED 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))681{682 typedef typename Policy::domain_error_type policy_type;683 return detail::raise_domain_error(684 function, message ? message : "Domain Error evaluating function at %1%",685 val, policy_type());686}687 688template <class T, class Policy>689BOOST_MATH_GPU_ENABLED 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))690{691 typedef typename Policy::pole_error_type policy_type;692 return detail::raise_pole_error(693 function, message ? message : "Evaluation of function at pole %1%",694 val, policy_type());695}696 697template <class T, class Policy>698BOOST_MATH_GPU_ENABLED 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))699{700 typedef typename Policy::overflow_error_type policy_type;701 return detail::raise_overflow_error<T>(702 function, message ? message : "Overflow Error",703 policy_type());704}705 706template <class T, class Policy>707BOOST_MATH_GPU_ENABLED 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))708{709 typedef typename Policy::overflow_error_type policy_type;710 return detail::raise_overflow_error(711 function, message ? message : "Overflow evaluating function at %1%",712 val, policy_type());713}714 715template <class T, class Policy>716BOOST_MATH_GPU_ENABLED 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))717{718 typedef typename Policy::underflow_error_type policy_type;719 return detail::raise_underflow_error<T>(720 function, message ? message : "Underflow Error",721 policy_type());722}723 724template <class T, class Policy>725BOOST_MATH_GPU_ENABLED 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))726{727 typedef typename Policy::denorm_error_type policy_type;728 return detail::raise_denorm_error<T>(729 function, message ? message : "Denorm Error",730 val,731 policy_type());732}733 734template <class T, class Policy>735BOOST_MATH_GPU_ENABLED 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))736{737 typedef typename Policy::evaluation_error_type policy_type;738 return detail::raise_evaluation_error(739 function, message ? message : "Internal Evaluation Error, best value so far was %1%",740 val, policy_type());741}742 743template <class T, class TargetType, class Policy>744BOOST_MATH_GPU_ENABLED 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))745{746 typedef typename Policy::rounding_error_type policy_type;747 return detail::raise_rounding_error(748 function, message ? message : "Value %1% can not be represented in the target integer type.",749 val, t, policy_type());750}751 752template <class T, class R, class Policy>753BOOST_MATH_GPU_ENABLED 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))754{755 typedef typename Policy::indeterminate_result_error_type policy_type;756 return detail::raise_indeterminate_result_error(757 function, message ? message : "Indeterminate result with value %1%",758 val, result, policy_type());759}760 761//762// checked_narrowing_cast:763//764namespace detail765{766 767template <class R, class T, class Policy>768BOOST_MATH_GPU_ENABLED BOOST_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))769{770 BOOST_MATH_STD_USING771 if(fabs(val) > tools::max_value<R>())772 {773 boost::math::policies::detail::raise_overflow_error<R>(function, nullptr, pol);774 *result = static_cast<R>(val);775 return true;776 }777 return false;778}779template <class R, class T, class Policy>780BOOST_MATH_GPU_ENABLED BOOST_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))781{782 typedef typename R::value_type r_type;783 r_type re, im;784 bool r = check_overflow<r_type>(val.real(), &re, function, pol);785 r = check_overflow<r_type>(val.imag(), &im, function, pol) || r;786 *result = R(re, im);787 return r;788}789template <class R, class T, class Policy>790BOOST_MATH_GPU_ENABLED BOOST_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))791{792 if((val != 0) && (static_cast<R>(val) == 0))793 {794 *result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, nullptr, pol));795 return true;796 }797 return false;798}799template <class R, class T, class Policy>800BOOST_MATH_GPU_ENABLED BOOST_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))801{802 typedef typename R::value_type r_type;803 r_type re, im;804 bool r = check_underflow<r_type>(val.real(), &re, function, pol);805 r = check_underflow<r_type>(val.imag(), &im, function, pol) || r;806 *result = R(re, im);807 return r;808}809template <class R, class T, class Policy>810BOOST_MATH_GPU_ENABLED BOOST_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))811{812 BOOST_MATH_STD_USING813 if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))814 {815 *result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));816 return true;817 }818 return false;819}820template <class R, class T, class Policy>821BOOST_MATH_GPU_ENABLED BOOST_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))822{823 typedef typename R::value_type r_type;824 r_type re, im;825 bool r = check_denorm<r_type>(val.real(), &re, function, pol);826 r = check_denorm<r_type>(val.imag(), &im, function, pol) || r;827 *result = R(re, im);828 return r;829}830 831// Default instantiations with ignore_error policy.832template <class R, class T>833BOOST_MATH_GPU_ENABLED BOOST_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))834{ return false; }835template <class R, class T>836BOOST_MATH_GPU_ENABLED BOOST_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))837{ return false; }838template <class R, class T>839BOOST_MATH_GPU_ENABLED BOOST_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))840{ return false; }841template <class R, class T>842BOOST_MATH_GPU_ENABLED BOOST_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))843{ return false; }844template <class R, class T>845BOOST_MATH_GPU_ENABLED BOOST_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))846{ return false; }847template <class R, class T>848BOOST_MATH_GPU_ENABLED BOOST_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))849{ return false; }850 851} // namespace detail852 853template <class R, class Policy, class T>854BOOST_MATH_GPU_ENABLED BOOST_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)855{856 typedef typename Policy::overflow_error_type overflow_type;857 typedef typename Policy::underflow_error_type underflow_type;858 typedef typename Policy::denorm_error_type denorm_type;859 //860 // Most of what follows will evaluate to a no-op:861 //862 R result = 0;863 if(detail::check_overflow<R>(val, &result, function, overflow_type()))864 return result;865 if(detail::check_underflow<R>(val, &result, function, underflow_type()))866 return result;867 if(detail::check_denorm<R>(val, &result, function, denorm_type()))868 return result;869 870 return static_cast<R>(val);871}872 873template <class T, class Policy>874BOOST_MATH_GPU_ENABLED 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)875{876 if(max_iter >= policies::get_max_series_iterations<Policy>())877 raise_evaluation_error<T>(878 function,879 "Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);880}881 882template <class T, class Policy>883BOOST_MATH_GPU_ENABLED 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)884{885 if(max_iter >= policies::get_max_root_iterations<Policy>())886 raise_evaluation_error<T>(887 function,888 "Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);889}890 891} //namespace policies892 893#ifdef _MSC_VER894# pragma warning(pop)895#endif896 897}} // namespaces boost/math898 899#else // Special values for NVRTC900 901namespace boost {902namespace math {903namespace policies {904 905template <class T, class Policy>906BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error(907 const char* ,908 const char* ,909 const T& ,910 const Policy&) BOOST_MATH_NOEXCEPT(T)911{912 // This may or may not do the right thing, but the user asked for the error913 // to be ignored so here we go anyway:914 return boost::math::numeric_limits<T>::quiet_NaN();915}916 917template <class T, class Policy>918BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(919 const char* function,920 const char* message,921 const T& val,922 const Policy&) BOOST_MATH_NOEXCEPT(T)923{924 return boost::math::numeric_limits<T>::quiet_NaN();925}926 927template <class T, class Policy>928BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(929 const char* ,930 const char* ,931 const Policy&) BOOST_MATH_NOEXCEPT(T)932{933 // This may or may not do the right thing, but the user asked for the error934 // to be ignored so here we go anyway:935 return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : (boost::math::numeric_limits<T>::max)();936}937 938template <class T, class Policy>939BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(940 const char* ,941 const char* ,942 const T&,943 const Policy&) BOOST_MATH_NOEXCEPT(T)944{945 // This may or may not do the right thing, but the user asked for the error946 // to be ignored so here we go anyway:947 return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : (boost::math::numeric_limits<T>::max)();948}949 950template <class T, class Policy>951BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error(952 const char* ,953 const char* ,954 const Policy&) BOOST_MATH_NOEXCEPT(T)955{956 // This may or may not do the right thing, but the user asked for the error957 // to be ignored so here we go anyway:958 return static_cast<T>(0);959}960 961template <class T, class Policy>962BOOST_MATH_GPU_ENABLED inline constexpr T raise_denorm_error(963 const char* ,964 const char* ,965 const T& val,966 const Policy&) BOOST_MATH_NOEXCEPT(T)967{968 // This may or may not do the right thing, but the user asked for the error969 // to be ignored so here we go anyway:970 return val;971}972 973template <class T, class Policy>974BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error(975 const char* ,976 const char* ,977 const T& val,978 const Policy&) BOOST_MATH_NOEXCEPT(T)979{980 // This may or may not do the right thing, but the user asked for the error981 // to be ignored so here we go anyway:982 return val;983}984 985template <class T, class TargetType, class Policy>986BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error(987 const char* ,988 const char* ,989 const T& val,990 const TargetType&,991 const Policy&) BOOST_MATH_NOEXCEPT(T)992{993 // This may or may not do the right thing, but the user asked for the error994 // to be ignored so here we go anyway:995 static_assert(boost::math::numeric_limits<TargetType>::is_specialized, "The target type must have std::numeric_limits specialized.");996 return val > 0 ? (boost::math::numeric_limits<TargetType>::max)() : (boost::math::numeric_limits<TargetType>::is_integer ? (boost::math::numeric_limits<TargetType>::min)() : -(boost::math::numeric_limits<TargetType>::max)());997}998 999template <class T, class R, class Policy>1000BOOST_MATH_GPU_ENABLED inline constexpr T raise_indeterminate_result_error(1001 const char* ,1002 const char* ,1003 const T& ,1004 const R& result,1005 const Policy&) BOOST_MATH_NOEXCEPT(T)1006{1007 // This may or may not do the right thing, but the user asked for the error1008 // to be ignored so here we go anyway:1009 return result;1010}1011 1012template <class R, class Policy, class T>1013BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE R checked_narrowing_cast(T val, const char* function) noexcept(boost::math::is_floating_point_v<R> && boost::math::is_floating_point_v<T>)1014{1015 // We only have ignore error policy so no reason to check1016 return static_cast<R>(val);1017}1018 1019template <class T, class Policy>1020BOOST_MATH_GPU_ENABLED inline void check_series_iterations(const char* function, boost::math::uintmax_t max_iter, const Policy& pol) noexcept(boost::math::is_floating_point_v<T>)1021{1022 if(max_iter >= policies::get_max_series_iterations<Policy>())1023 raise_evaluation_error<T>(1024 function,1025 "Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);1026}1027 1028template <class T, class Policy>1029BOOST_MATH_GPU_ENABLED inline void check_root_iterations(const char* function, boost::math::uintmax_t max_iter, const Policy& pol) noexcept(boost::math::is_floating_point_v<T>)1030{1031 if(max_iter >= policies::get_max_root_iterations<Policy>())1032 raise_evaluation_error<T>(1033 function,1034 "Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);1035}1036 1037} // namespace policies1038} // namespace math1039} // namespace boost1040 1041#endif // BOOST_MATH_HAS_NVRTC1042 1043namespace boost { namespace math { namespace detail {1044 1045//1046// Simple helper function to assist in returning a pair from a single value,1047// that value usually comes from one of the error handlers above:1048//1049template <class T>1050BOOST_MATH_GPU_ENABLED boost::math::pair<T, T> pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T)1051{1052 return boost::math::make_pair(val, val);1053}1054 1055}}} // boost::math::detail1056 1057#endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP1058 1059