Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Error Handling Policies

There are two orthogonal aspects to error handling:

Available Actions When an Error is Raised

What to do with the error is encapsulated by an enumerated type:

namespace boost { namespace math { namespace policies {

enum error_policy_type
{
   throw_on_error = 0, // throw an exception.
   errno_on_error = 1, // set ::errno & return 0, NaN, infinity or best guess.
   ignore_error = 2, // return 0, NaN, infinity or best guess.
   user_error = 3  // call a user-defined error handler.
};

}}} // namespaces

The various enumerated values have the following meanings:

throw_on_error

Will throw one of the following exceptions, depending upon the type of the error:

Error Type

Exception

Domain Error

std::domain_error

Pole Error

std::domain_error

Overflow Error

std::overflow_error

Underflow Error

std::underflow_error

Denorm Error

std::underflow_error

Evaluation Error

boost::math::evaluation_error

errno_on_error

Will set global ::errno to one of the following values depending upon the error type, and then return the same value as if the error had been ignored:

Error Type

errno value

Domain Error

EDOM

Pole Error

EDOM

Overflow Error

ERANGE

Underflow Error

ERANGE

Denorm Error

ERANGE

Evaluation Error

EDOM

ignore_error

Will return a one of the values below depending on the error type (::errno is NOT changed)::

Error Type

Returned Value

Domain Error

std::numeric_limits<T>::quiet_NaN()

Pole Error

std::numeric_limits<T>::quiet_NaN()

Overflow Error

std::numeric_limits<T>::infinity()

Underflow Error

0

Denorm Error

The denormalised value.

Evaluation Error

The best guess as to the result: which may be significantly in error.

user_error

Will call a user defined error handler: these are forward declared in boost/math/policies/error_handling.hpp, but the actual definitions must be provided by the user:

namespace boost{ namespace math{ namespace policies{

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);

}}} // namespaces

Note that the strings function and message may contain "%1%" format specifiers designed to be used in conjunction with Boost.Format. If these strings are to be presented to the program's end-user then the "%1%" format specifier should be replaced with the name of type T in the function string, and if there is a %1% specifier in the message string then it should be replaced with the value of val.

There is more information on user-defined error handlers in the tutorial here.

Kinds of Error Raised

There are five kinds of error reported by this library, which are summarised in the following table:

Error Type

Policy Class

Description

Domain Error

boost::math::policies::domain_error<action>

Raised when more or more arguments are outside the defined range of the function.

Defaults to boost::math::policies::domain_error<throw_on_error>

When the action is set to throw_on_error then throws std::domain_error

Pole Error

boost::math::policies::pole_error<action>

Raised when more or more arguments would cause the function to be evaluated at a pole.

Defaults to boost::math::policies::pole_error<throw_on_error>

When the action is throw_on_error then throw a std::domain_error

Overflow Error

boost::math::policies::overflow_error<action>

Raised when the result of the function is outside the representable range of the floating point type used.

Defaults to boost::math::policies::overflow_error<throw_on_error>.

When the action is throw_on_error then throws a std::overflow_error.

Underflow Error

boost::math::policies::underflow_error<action>

Raised when the result of the function is too small to be represented in the floating point type used.

Defaults to boost::math::policies::underflow_error<ignore_error>

When the specified action is throw_on_error then throws a std::underflow_error

Denorm Error

boost::math::policies::denorm_error<action>

Raised when the result of the function is a denormalised value.

Defaults to boost::math::policies::denorm_error<ignore_error>

When the action is throw_on_error then throws a std::underflow_error

Evaluation Error

boost::math::policies::evaluation_error<action>

Raised when the result of the function is well defined and finite, but we were unable to compute it. Typically this occurs when an iterative method fails to converge. Of course ideally this error should never be raised: feel free to report it as a bug if it is!

Defaults to boost::math::policies::evaluation_error<throw_on_error>

When the action is throw_on_error then throws boost::math::evaluation_error

Examples

Suppose we want a call to tgamma to behave in a C-compatible way and set global ::errno rather than throw an exception, we can achieve this at the call site using:

#include <boost/math/special_functions/gamma.hpp>

using namespace boost::math::policies;
using namespace boost::math;

// Define a policy:
typedef policy<
      domain_error<errno_on_error>, 
      pole_error<errno_on_error>,
      overflow_error<errno_on_error>,
      policies::evaluation_error<errno_on_error> 
      > my_policy;
      
// call the function:
double t1 = tgamma(some_value, my_policy());

// Alternatively we could use make_policy and define everything at the call site:
double t2 = tgamma(some_value, make_policy(
         domain_error<errno_on_error>(), 
         pole_error<errno_on_error>(),
         overflow_error<errno_on_error>(),
         policies::evaluation_error<errno_on_error>() 
      ));

Suppose we want a statistical distribution to return infinities, rather than throw exceptions, then we can use:

#include <boost/math/distributions/normal.hpp>

using namespace boost::math::policies;
using namespace boost::math;

// Define a policy:
typedef policy<
      overflow_error<ignore_error>
      > my_policy;
      
// Define the distribution:
typedef normal_distribution<double, my_policy> my_norm;

// Get a quantile:
double q = quantile(my_norm(), 0.05);


PrevUpHomeNext