123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847 |
- // Copyright John Maddock 2007.
- // Copyright Paul A. Bristow 2007.
- // Use, modification and distribution are subject to the
- // Boost Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
- #define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
- #include <stdexcept>
- #include <iomanip>
- #include <string>
- #include <cstring>
- #include <typeinfo>
- #include <cerrno>
- #include <boost/config/no_tr1/complex.hpp>
- #include <boost/config/no_tr1/cmath.hpp>
- #include <stdexcept>
- #include <boost/math/tools/config.hpp>
- #include <boost/math/policies/policy.hpp>
- #include <boost/math/tools/precision.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/cstdint.hpp>
- #ifdef BOOST_MSVC
- # pragma warning(push) // Quiet warnings in boost/format.hpp
- # pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
- # pragma warning(disable: 4512) // assignment operator could not be generated.
- # pragma warning(disable: 4127) // conditional expression is constant
- // And warnings in error handling:
- # pragma warning(disable: 4702) // unreachable code.
- // Note that this only occurs when the compiler can deduce code is unreachable,
- // for example when policy macros are used to ignore errors rather than throw.
- #endif
- #include <sstream>
- namespace boost{ namespace math{
- class evaluation_error : public std::runtime_error
- {
- public:
- evaluation_error(const std::string& s) : std::runtime_error(s){}
- };
- class rounding_error : public std::runtime_error
- {
- public:
- rounding_error(const std::string& s) : std::runtime_error(s){}
- };
- namespace policies{
- //
- // Forward declarations of user error handlers,
- // it's up to the user to provide the definition of these:
- //
- template <class T>
- T user_domain_error(const char* function, const char* message, const T& val);
- template <class T>
- T user_pole_error(const char* function, const char* message, const T& val);
- template <class T>
- T user_overflow_error(const char* function, const char* message, const T& val);
- template <class T>
- T user_underflow_error(const char* function, const char* message, const T& val);
- template <class T>
- T user_denorm_error(const char* function, const char* message, const T& val);
- template <class T>
- T user_evaluation_error(const char* function, const char* message, const T& val);
- template <class T, class TargetType>
- T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
- template <class T>
- T user_indeterminate_result_error(const char* function, const char* message, const T& val);
- namespace detail
- {
- template <class T>
- std::string prec_format(const T& val)
- {
- typedef typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type prec_type;
- std::stringstream ss;
- if(prec_type::value)
- {
- int prec = 2 + (prec_type::value * 30103UL) / 100000UL;
- ss << std::setprecision(prec);
- }
- ss << val;
- return ss.str();
- }
- inline void replace_all_in_string(std::string& result, const char* what, const char* with)
- {
- std::string::size_type pos = 0;
- std::string::size_type slen = std::strlen(what);
- std::string::size_type rlen = std::strlen(with);
- while((pos = result.find(what, pos)) != std::string::npos)
- {
- result.replace(pos, slen, with);
- pos += rlen;
- }
- }
- template <class T>
- inline const char* name_of()
- {
- #ifndef BOOST_NO_RTTI
- return typeid(T).name();
- #else
- return "unknown";
- #endif
- }
- template <> inline const char* name_of<float>(){ return "float"; }
- template <> inline const char* name_of<double>(){ return "double"; }
- template <> inline const char* name_of<long double>(){ return "long double"; }
- #ifdef BOOST_MATH_USE_FLOAT128
- template <>
- inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()
- {
- return "__float128";
- }
- #endif
- template <class E, class T>
- void raise_error(const char* pfunction, const char* message)
- {
- if(pfunction == 0)
- pfunction = "Unknown function operating on type %1%";
- if(message == 0)
- message = "Cause unknown";
- std::string function(pfunction);
- std::string msg("Error in function ");
- #ifndef BOOST_NO_RTTI
- replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
- #else
- replace_all_in_string(function, "%1%", "Unknown");
- #endif
- msg += function;
- msg += ": ";
- msg += message;
- E e(msg);
- boost::throw_exception(e);
- }
- template <class E, class T>
- void raise_error(const char* pfunction, const char* pmessage, const T& val)
- {
- if(pfunction == 0)
- pfunction = "Unknown function operating on type %1%";
- if(pmessage == 0)
- pmessage = "Cause unknown: error caused by bad argument with value %1%";
- std::string function(pfunction);
- std::string message(pmessage);
- std::string msg("Error in function ");
- #ifndef BOOST_NO_RTTI
- replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
- #else
- replace_all_in_string(function, "%1%", "Unknown");
- #endif
- msg += function;
- msg += ": ";
- std::string sval = prec_format(val);
- replace_all_in_string(message, "%1%", sval.c_str());
- msg += message;
- E e(msg);
- boost::throw_exception(e);
- }
- template <class T>
- inline T raise_domain_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
- {
- raise_error<std::domain_error, T>(function, message, val);
- // we never get here:
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <class T>
- inline BOOST_MATH_CONSTEXPR T raise_domain_error(
- const char* ,
- const char* ,
- const T& ,
- const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- // This may or may not do the right thing, but the user asked for the error
- // to be ignored so here we go anyway:
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <class T>
- inline T raise_domain_error(
- const char* ,
- const char* ,
- const T& ,
- const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- errno = EDOM;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <class T>
- inline T raise_domain_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
- {
- return user_domain_error(function, message, val);
- }
- template <class T>
- inline T raise_pole_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
- {
- return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
- }
- template <class T>
- inline BOOST_MATH_CONSTEXPR T raise_pole_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
- }
- template <class T>
- inline BOOST_MATH_CONSTEXPR T raise_pole_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
- }
- template <class T>
- inline T raise_pole_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
- {
- return user_pole_error(function, message, val);
- }
- template <class T>
- inline T raise_overflow_error(
- const char* function,
- const char* message,
- const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
- {
- raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
- // We should never get here:
- return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
- }
- template <class T>
- inline T raise_overflow_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
- {
- raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow", val);
- // We should never get here:
- return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
- }
- template <class T>
- inline BOOST_MATH_CONSTEXPR T raise_overflow_error(
- const char* ,
- const char* ,
- const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- // This may or may not do the right thing, but the user asked for the error
- // to be ignored so here we go anyway:
- return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
- }
- template <class T>
- inline BOOST_MATH_CONSTEXPR T raise_overflow_error(
- const char* ,
- const char* ,
- const T&,
- const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- // This may or may not do the right thing, but the user asked for the error
- // to be ignored so here we go anyway:
- return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
- }
- template <class T>
- inline T raise_overflow_error(
- const char* ,
- const char* ,
- const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- errno = ERANGE;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
- }
- template <class T>
- inline T raise_overflow_error(
- const char* ,
- const char* ,
- const T&,
- const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- errno = ERANGE;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
- }
- template <class T>
- inline T raise_overflow_error(
- const char* function,
- const char* message,
- const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
- {
- return user_overflow_error(function, message, std::numeric_limits<T>::infinity());
- }
- template <class T>
- inline T raise_overflow_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
- {
- std::string m(message ? message : "");
- std::string sval = prec_format(val);
- replace_all_in_string(m, "%1%", sval.c_str());
- return user_overflow_error(function, m.c_str(), std::numeric_limits<T>::infinity());
- }
- template <class T>
- inline T raise_underflow_error(
- const char* function,
- const char* message,
- const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
- {
- raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
- // We should never get here:
- return 0;
- }
- template <class T>
- inline BOOST_MATH_CONSTEXPR T raise_underflow_error(
- const char* ,
- const char* ,
- const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- // This may or may not do the right thing, but the user asked for the error
- // to be ignored so here we go anyway:
- return T(0);
- }
- template <class T>
- inline T raise_underflow_error(
- const char* /* function */,
- const char* /* message */,
- const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- errno = ERANGE;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- return T(0);
- }
- template <class T>
- inline T raise_underflow_error(
- const char* function,
- const char* message,
- const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
- {
- return user_underflow_error(function, message, T(0));
- }
- template <class T>
- inline T raise_denorm_error(
- const char* function,
- const char* message,
- const T& /* val */,
- const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
- {
- raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
- // we never get here:
- return T(0);
- }
- template <class T>
- inline BOOST_MATH_CONSTEXPR T raise_denorm_error(
- const char* ,
- const char* ,
- const T& val,
- const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- // This may or may not do the right thing, but the user asked for the error
- // to be ignored so here we go anyway:
- return val;
- }
- template <class T>
- inline T raise_denorm_error(
- const char* ,
- const char* ,
- const T& val,
- const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- errno = ERANGE;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- return val;
- }
- template <class T>
- inline T raise_denorm_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
- {
- return user_denorm_error(function, message, val);
- }
- template <class T>
- inline T raise_evaluation_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
- {
- raise_error<boost::math::evaluation_error, T>(function, message, val);
- // we never get here:
- return T(0);
- }
- template <class T>
- inline BOOST_MATH_CONSTEXPR T raise_evaluation_error(
- const char* ,
- const char* ,
- const T& val,
- const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- // This may or may not do the right thing, but the user asked for the error
- // to be ignored so here we go anyway:
- return val;
- }
- template <class T>
- inline T raise_evaluation_error(
- const char* ,
- const char* ,
- const T& val,
- const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- errno = EDOM;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- return val;
- }
- template <class T>
- inline T raise_evaluation_error(
- const char* function,
- const char* message,
- const T& val,
- const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
- {
- return user_evaluation_error(function, message, val);
- }
- template <class T, class TargetType>
- inline TargetType raise_rounding_error(
- const char* function,
- const char* message,
- const T& val,
- const TargetType&,
- const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
- {
- raise_error<boost::math::rounding_error, T>(function, message, val);
- // we never get here:
- return TargetType(0);
- }
- template <class T, class TargetType>
- inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(
- const char* ,
- const char* ,
- const T& val,
- const TargetType&,
- const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- // This may or may not do the right thing, but the user asked for the error
- // to be ignored so here we go anyway:
- BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
- return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
- }
- template <class T, class TargetType>
- inline TargetType raise_rounding_error(
- const char* ,
- const char* ,
- const T& val,
- const TargetType&,
- const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- errno = ERANGE;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
- return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
- }
- template <class T>
- inline T raise_rounding_error(
- const char* ,
- const char* ,
- const T& val,
- const T&,
- const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- errno = ERANGE;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- return val > 0 ? boost::math::tools::max_value<T>() : -boost::math::tools::max_value<T>();
- }
- template <class T, class TargetType>
- inline TargetType raise_rounding_error(
- const char* function,
- const char* message,
- const T& val,
- const TargetType& t,
- const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
- {
- return user_rounding_error(function, message, val, t);
- }
- template <class T, class R>
- inline T raise_indeterminate_result_error(
- const char* function,
- const char* message,
- const T& val,
- const R& ,
- const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
- {
- raise_error<std::domain_error, T>(function, message, val);
- // we never get here:
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <class T, class R>
- inline BOOST_MATH_CONSTEXPR T raise_indeterminate_result_error(
- const char* ,
- const char* ,
- const T& ,
- const R& result,
- const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
- {
- // This may or may not do the right thing, but the user asked for the error
- // to be ignored so here we go anyway:
- return result;
- }
- template <class T, class R>
- inline T raise_indeterminate_result_error(
- const char* ,
- const char* ,
- const T& ,
- const R& result,
- const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)
- {
- errno = EDOM;
- // This may or may not do the right thing, but the user asked for the error
- // to be silent so here we go anyway:
- return result;
- }
- template <class T, class R>
- inline T raise_indeterminate_result_error(
- const char* function,
- const char* message,
- const T& val,
- const R& ,
- const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
- {
- return user_indeterminate_result_error(function, message, val);
- }
- } // namespace detail
- template <class T, class Policy>
- inline BOOST_MATH_CONSTEXPR T raise_domain_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::domain_error_type policy_type;
- return detail::raise_domain_error(
- function, message ? message : "Domain Error evaluating function at %1%",
- val, policy_type());
- }
- template <class T, class Policy>
- inline BOOST_MATH_CONSTEXPR T raise_pole_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::pole_error_type policy_type;
- return detail::raise_pole_error(
- function, message ? message : "Evaluation of function at pole %1%",
- val, policy_type());
- }
- template <class T, class Policy>
- inline BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const char* message, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::overflow_error_type policy_type;
- return detail::raise_overflow_error<T>(
- function, message ? message : "Overflow Error",
- policy_type());
- }
- template <class T, class Policy>
- inline BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::overflow_error_type policy_type;
- return detail::raise_overflow_error(
- function, message ? message : "Overflow evaluating function at %1%",
- val, policy_type());
- }
- template <class T, class Policy>
- inline BOOST_MATH_CONSTEXPR T raise_underflow_error(const char* function, const char* message, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::underflow_error_type policy_type;
- return detail::raise_underflow_error<T>(
- function, message ? message : "Underflow Error",
- policy_type());
- }
- template <class T, class Policy>
- inline BOOST_MATH_CONSTEXPR T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::denorm_error_type policy_type;
- return detail::raise_denorm_error<T>(
- function, message ? message : "Denorm Error",
- val,
- policy_type());
- }
- template <class T, class Policy>
- inline BOOST_MATH_CONSTEXPR T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::evaluation_error_type policy_type;
- return detail::raise_evaluation_error(
- function, message ? message : "Internal Evaluation Error, best value so far was %1%",
- val, policy_type());
- }
- template <class T, class TargetType, class Policy>
- inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::rounding_error_type policy_type;
- return detail::raise_rounding_error(
- function, message ? message : "Value %1% can not be represented in the target integer type.",
- val, t, policy_type());
- }
- template <class T, class R, class Policy>
- inline BOOST_MATH_CONSTEXPR T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
- {
- typedef typename Policy::indeterminate_result_error_type policy_type;
- return detail::raise_indeterminate_result_error(
- function, message ? message : "Indeterminate result with value %1%",
- val, result, policy_type());
- }
- //
- // checked_narrowing_cast:
- //
- namespace detail
- {
- template <class R, class T, class Policy>
- inline bool check_overflow(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
- {
- BOOST_MATH_STD_USING
- if(fabs(val) > tools::max_value<R>())
- {
- boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol);
- *result = static_cast<R>(val);
- return true;
- }
- return false;
- }
- template <class R, class T, class Policy>
- inline bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
- {
- typedef typename R::value_type r_type;
- r_type re, im;
- bool r = check_overflow<r_type>(val.real(), &re, function, pol);
- r = check_overflow<r_type>(val.imag(), &im, function, pol) || r;
- *result = R(re, im);
- return r;
- }
- template <class R, class T, class Policy>
- inline bool check_underflow(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
- {
- if((val != 0) && (static_cast<R>(val) == 0))
- {
- *result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, 0, pol));
- return true;
- }
- return false;
- }
- template <class R, class T, class Policy>
- inline bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
- {
- typedef typename R::value_type r_type;
- r_type re, im;
- bool r = check_underflow<r_type>(val.real(), &re, function, pol);
- r = check_underflow<r_type>(val.imag(), &im, function, pol) || r;
- *result = R(re, im);
- return r;
- }
- template <class R, class T, class Policy>
- inline bool check_denorm(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
- {
- BOOST_MATH_STD_USING
- if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
- {
- *result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));
- return true;
- }
- return false;
- }
- template <class R, class T, class Policy>
- inline bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
- {
- typedef typename R::value_type r_type;
- r_type re, im;
- bool r = check_denorm<r_type>(val.real(), &re, function, pol);
- r = check_denorm<r_type>(val.imag(), &im, function, pol) || r;
- *result = R(re, im);
- return r;
- }
- // Default instantiations with ignore_error policy.
- template <class R, class T>
- inline BOOST_MATH_CONSTEXPR bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
- { return false; }
- template <class R, class T>
- inline BOOST_MATH_CONSTEXPR bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
- { return false; }
- template <class R, class T>
- inline BOOST_MATH_CONSTEXPR bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
- { return false; }
- template <class R, class T>
- inline BOOST_MATH_CONSTEXPR bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
- { return false; }
- template <class R, class T>
- inline BOOST_MATH_CONSTEXPR bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
- { return false; }
- template <class R, class T>
- inline BOOST_MATH_CONSTEXPR bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
- { return false; }
- } // namespace detail
- template <class R, class Policy, class T>
- inline R checked_narrowing_cast(T val, const char* function) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
- {
- typedef typename Policy::overflow_error_type overflow_type;
- typedef typename Policy::underflow_error_type underflow_type;
- typedef typename Policy::denorm_error_type denorm_type;
- //
- // Most of what follows will evaluate to a no-op:
- //
- R result = 0;
- if(detail::check_overflow<R>(val, &result, function, overflow_type()))
- return result;
- if(detail::check_underflow<R>(val, &result, function, underflow_type()))
- return result;
- if(detail::check_denorm<R>(val, &result, function, denorm_type()))
- return result;
- return static_cast<R>(val);
- }
- template <class T, class Policy>
- inline void check_series_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
- {
- if(max_iter >= policies::get_max_series_iterations<Policy>())
- raise_evaluation_error<T>(
- function,
- "Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
- }
- template <class T, class Policy>
- inline void check_root_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
- {
- if(max_iter >= policies::get_max_root_iterations<Policy>())
- raise_evaluation_error<T>(
- function,
- "Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
- }
- } //namespace policies
- namespace detail{
- //
- // Simple helper function to assist in returning a pair from a single value,
- // that value usually comes from one of the error handlers above:
- //
- template <class T>
- std::pair<T, T> pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T)
- {
- return std::make_pair(val, val);
- }
- }
- #ifdef BOOST_MSVC
- # pragma warning(pop)
- #endif
- }} // namespaces boost/math
- #endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP
|