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