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

Indeterminate Result Error

std::domain_error

errno_on_error

Will set global ::errno ::errno to one of the following values depending upon the error type (often EDOM = 33 and ERANGE = 34), 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

Indeterminate Result Error

EDOM

ignore_error

Will return 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 (perhaps NaN) as to the result: which may be significantly in error.

Indeterminate Result Error

Depends on the function where the error occurred

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_rounding_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>
T user_indeterminate_result_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 six 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

Rounding Error

boost::math::policies::rounding_error<action>

Raised When one of the rounding functions round, trunc or modf is called with an argument that has no integer representation, or is too large to be represented in the result type

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

When the action is throw_on_error then throws boost::math::rounding_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

Indeterminate Result Error

boost::math::policies::indeterminate_result_error<action>

Raised when the result of a function is not defined for the values that were passed to it.

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

When the action is throw_on_error then throws std::domain_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 boost::math::tgamma;

//using namespace boost::math::policies; may also be convenient.
using boost::math::policies::policy;
using boost::math::policies::evaluation_error;
using boost::math::policies::domain_error;
using boost::math::policies::overflow_error;
using boost::math::policies::domain_error;
using boost::math::policies::pole_error;
using boost::math::policies::errno_on_error;

// Define a policy:
typedef policy<
  domain_error<errno_on_error>,
  pole_error<errno_on_error>,
  overflow_error<errno_on_error>,
  evaluation_error<errno_on_error>
> my_policy;

double my_value = 0.; // 

// Call the function applying my_policy:
double t1 = tgamma(my_value, my_policy());

// Alternatively (and equivalently) we could use helpful function
// make_policy and define everything at the call site:
double t2 = tgamma(my_value,
  make_policy(
    domain_error<errno_on_error>(),
    pole_error<errno_on_error>(),
    overflow_error<errno_on_error>(),
    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 boost::math::normal_distribution;

using namespace boost::math::policies;

// Define a specific policy:
typedef policy<
      overflow_error<ignore_error>
      > my_policy;

// Define the distribution, using my_policy:
typedef normal_distribution<double, my_policy> my_norm;

// Construct a my_norm distribution, using default mean and standard deviation,
// and get a 0.05 or 5% quantile:
double q = quantile(my_norm(), 0.05); // = -1.64485

PrevUpHomeNext