Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Click here to view the latest version of this page.
PrevUpHomeNext

Error Handling

Quick Reference

Handling of errors by this library is split into two orthogonal parts:

[Warning] Warning

The default error actions are to throw an exception with an informative error message. If you do not try to catch the exception, you will not see the message!

The kinds of errors that can be raised are:

Domain Error

Occurs when one or more arguments to a function are out of range.

Pole Error

Occurs when the particular arguments cause the function to be evaluated at a pole with no well defined residual value. For example if tgamma is evaluated at exactly -2, the function approaches different limiting values depending upon whether you approach from just above or just below -2. Hence the function has no well defined value at this point and a Pole Error will be raised.

Overflow Error

Occurs when the result is either infinite, or too large to represent in the numeric type being returned by the function.

Underflow Error

Occurs when the result is not zero, but is too small to be represented by any other value in the type being returned by the function.

Denormalisation Error

Occurs when the returned result would be a denormalised value.

Rounding Error

Occurs when the argument to one of the rounding functions trunc, round and modf can not be represented as an integer type, is outside the range of the result type.

Evaluation Error

Occurs if no method of evaluation is known, or when an internal error occurred that prevented the result from being evaluated: this should never occur, but if it does, then it's likely to be due to an iterative method not converging fast enough.

Indeterminate Result Error

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

The action undertaken by each error condition is determined by the current Policy in effect. This can be changed program-wide by setting some configuration macros, or at namespace scope, or at the call site (by specifying a specific policy in the function call).

The available actions are:

throw_on_error

Throws the exception most appropriate to the error condition.

errno_on_error

Sets ::errno to an appropriate value, and then returns the most appropriate result

ignore_error

Ignores the error and simply the returns the most appropriate result.

user_error

Calls a user-supplied error handler.

The following tables show all the permutations of errors and actions, with the default action for each error shown in bold:

Table 1.1. Possible Actions for Domain Errors

Action

Behaviour

throw_on_error

Throws std::domain_error

errno_on_error

Sets ::errno to EDOM and returns std::numeric_limits<T>::quiet_NaN()

ignore_error

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

user_error

Returns the result of boost::math::policies::user_domain_error: this function must be defined by the user.


Table 1.2. Possible Actions for Pole Errors

Action

Behaviour

throw_on_error

Throws std::domain_error

errno_on_error

Sets ::errno to EDOM and returns std::numeric_limits<T>::quiet_NaN()

ignore_error

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

user_error

Returns the result of boost::math::policies::user_pole_error: this function must be defined by the user.


Table 1.3. Possible Actions for Overflow Errors

Action

Behaviour

throw_on_error

Throws std::overflow_error

errno_on_error

Sets ::errno to ERANGE and returns std::numeric_limits<T>::infinity()

ignore_error

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

user_error

Returns the result of boost::math::policies::user_overflow_error: this function must be defined by the user.


Table 1.4. Possible Actions for Underflow Errors

Action

Behaviour

throw_on_error

Throws std::underflow_error

errno_on_error

Sets ::errno to ERANGE and returns 0.

ignore_error

Returns 0

user_error

Returns the result of boost::math::policies::user_underflow_error: this function must be defined by the user.


Table 1.5. Possible Actions for Denorm Errors

Action

Behaviour

throw_on_error

Throws std::underflow_error

errno_on_error

Sets ::errno to ERANGE and returns the denormalised value.

ignore_error

Returns the denormalised value.

user_error

Returns the result of boost::math::policies::user_denorm_error: this function must be defined by the user.


Table 1.6. Possible Actions for Rounding Errors

Action

Behaviour

throw_on_error

Throws boost::math::rounding_error

errno_on_error

Sets ::errno to ERANGE and returns the largest representable value of the target integer type (or the most negative value if the argument to the function was less than zero).

ignore_error

Returns the largest representable value of the target integer type (or the most negative value if the argument to the function was less than zero).

user_error

Returns the result of boost::math::policies::user_rounding_error: this function must be defined by the user.


Table 1.7. Possible Actions for Internal Evaluation Errors

Action

Behaviour

throw_on_error

Throws boost::math::evaluation_error

errno_on_error

Sets ::errno to EDOM and returns the closest approximation found.

ignore_error

Returns the closest approximation found.

user_error

Returns the result of boost::math::policies::user_evaluation_error: this function must be defined by the user.


Table 1.8. Possible Actions for Indeterminate Result Errors

Action

Behaviour

throw_on_error

Throws std::domain_error

errno_on_error

Sets ::errno to EDOM and returns the same value as ignore_error.

ignore_error

Returns a default result that depends on the function where the error occurred.

user_error

Returns the result of boost::math::policies::user_indeterminate_result_error: this function must be defined by the user.


All these error conditions are in namespace boost::math::policies, made available, for example, a by namespace declaration using namespace boost::math::policies; or individual using declarations using boost::math::policies::overflow_error;.

Rationale

The flexibility of the current implementation should be reasonably obvious: the default behaviours were chosen based on feedback during the formal review of this library. It was felt that:

Finding More Information

There are some pre-processor macro defines that can be used to change the policy defaults. See also the policy section.

An example is at the Policy tutorial in Changing the Policy Defaults.

Full source code of this typical example of passing a 'bad' argument (negative degrees of freedom) to Student's t distribution is in the error handling example.

The various kind of errors are described in more detail below.

Domain Errors

When a special function is passed an argument that is outside the range of values for which that function is defined, then the function returns the result of:

boost::math::policies::raise_domain_error<T>(FunctionName, Message, Val, Policy);

Where T is the floating-point type passed to the function, FunctionName is the name of the function, Message is an error message describing the problem, Val is the value that was out of range, and Policy is the current policy in use for the function that was called.

The default policy behaviour of this function is to throw a std::domain_error C++ exception. But if the Policy is to ignore the error, or set global ::errno, then a NaN will be returned.

This behaviour is chosen to assist compatibility with the behaviour of ISO/IEC 9899:1999 Programming languages - C and with the Draft Technical Report on C++ Library Extensions, 2005-06-24, section 5.2.1, paragraph 6:

"Each of the functions declared above shall return a NaN (Not a Number) if any argument value is a NaN, but it shall not report a domain error. Otherwise, each of the functions declared above shall report a domain error for just those argument values for which:

"the function description's Returns clause explicitly specifies a domain, and those arguments fall outside the specified domain; or

"the corresponding mathematical function value has a non-zero imaginary component; or

"the corresponding mathematical function is not mathematically defined.

"Note 2: A mathematical function is mathematically defined for a given set of argument values if it is explicitly defined for that set of argument values or if its limiting value exists and does not depend on the direction of approach."

Note that in order to support information-rich error messages when throwing exceptions, Message must contain a Boost.Format recognised format specifier: the argument Val is inserted into the error message according to the specifier used.

For example if Message contains a "%1%" then it is replaced by the value of Val to the full precision of T, where as "%.3g" would contain the value of Val to 3 digits. See the Boost.Format documentation for more details.

Evaluation at a pole

When a special function is passed an argument that is at a pole without a well defined residual value, then the function returns the result of:

boost::math::policies::raise_pole_error<T>(FunctionName, Message, Val, Policy);

Where T is the floating point type passed to the function, FunctionName is the name of the function, Message is an error message describing the problem, Val is the value of the argument that is at a pole, and Policy is the current policy in use for the function that was called.

The default behaviour of this function is to throw a std::domain_error exception. But error handling policies can be used to change this, for example to ignore_error and return NaN.

Note that in order to support information-rich error messages when throwing exceptions, Message must contain a Boost.Format recognised format specifier: the argument val is inserted into the error message according to the specifier used.

For example if Message contains a "%1%" then it is replaced by the value of val to the full precision of T, where as "%.3g" would contain the value of val to 3 digits. See the Boost.Format documentation for more details.

Numeric Overflow

When the result of a special function is too large to fit in the argument floating-point type, then the function returns the result of:

boost::math::policies::raise_overflow_error<T>(FunctionName, Message, Policy);

Where T is the floating-point type passed to the function, FunctionName is the name of the function, Message is an error message describing the problem, and Policy is the current policy in use for the function that was called.

The default policy for this function is that std::overflow_error C++ exception is thrown. But if, for example, an ignore_error policy is used, then returns std::numeric_limits<T>::infinity(). In this situation if the type T doesn't support infinities, the maximum value for the type is returned.

Numeric Underflow

If the result of a special function is known to be non-zero, but the calculated result underflows to zero, then the function returns the result of:

boost::math::policies::raise_underflow_error<T>(FunctionName, Message, Policy);

Where T is the floating point type passed to the function, FunctionName is the name of the function, Message is an error message describing the problem, and Policy is the current policy in use for the called function.

The default version of this function returns zero. But with another policy, like throw_on_error, throws an std::underflow_error C++ exception.

Denormalisation Errors

If the result of a special function is a denormalised value z then the function returns the result of:

boost::math::policies::raise_denorm_error<T>(z, FunctionName, Message, Policy);

Where T is the floating point type passed to the function, FunctionName is the name of the function, Message is an error message describing the problem, and Policy is the current policy in use for the called function.

The default version of this function returns z. But with another policy, like throw_on_error throws an std::underflow_error C++ exception.

Evaluation Errors

When a special function calculates a result that is known to be erroneous, or where the result is incalculable then it calls:

boost::math::policies::raise_evaluation_error<T>(FunctionName, Message, Val, Policy);

Where T is the floating point type passed to the function, FunctionName is the name of the function, Message is an error message describing the problem, Val is the erroneous value, and Policy is the current policy in use for the called function.

The default behaviour of this function is to throw a boost::math::evaluation_error.

Note that in order to support information rich error messages when throwing exceptions, Message must contain a Boost.Format recognised format specifier: the argument val is inserted into the error message according to the specifier used.

For example if Message contains a "%1%" then it is replaced by the value of val to the full precision of T, where as "%.3g" would contain the value of val to 3 digits. See the Boost.Format documentation for more details.

Indeterminate Result Errors

When the result of a special function is indeterminate for the value that was passed to it, then the function returns the result of:

boost::math::policies::raise_overflow_error<T>(FunctionName, Message, Val, Default, Policy);

Where T is the floating-point type passed to the function, FunctionName is the name of the function, Message is an error message describing the problem, Val is the value for which the result is indeterminate, Default is an alternative default result that must be returned for ignore_error and errno_on_erro policies, and Policy is the current policy in use for the function that was called.

The default policy for this function is ignore_error: note that this error type is reserved for situations where the result is mathematically undefined or indeterminate, but there is none the less a convention for what the result should be: for example the C99 standard specifies that the result of 00 is 1, even though the result is actually mathematically indeterminate.

Rounding Errors

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 then the value returned is the result of a call to:

boost::math::policies::raise_rounding_error<T>(FunctionName, Message, Val, Policy);

Where T is the floating point type passed to the function, FunctionName is the name of the function, Message is an error message describing the problem, Val is the erroneous argument, and Policy is the current policy in use for the called function.

The default behaviour of this function is to throw a boost::math::rounding_error.

Note that in order to support information rich error messages when throwing exceptions, Message must contain a Boost.Format recognised format specifier: the argument val is inserted into the error message according to the specifier used.

For example if Message contains a "%1%" then it is replaced by the value of val to the full precision of T, where as "%.3g" would contain the value of val to 3 digits. See the Boost.Format documentation for more details.

Errors from typecasts

Many special functions evaluate their results at a higher precision than their arguments in order to ensure full machine precision in the result: for example, a function passed a float argument may evaluate its result using double precision internally. Many of the errors listed above may therefore occur not during evaluation, but when converting the result to the narrower result type. The function:

template <class T, class Policy, class U>
T checked_narrowing_cast(U const& val, const char* function);

Is used to perform these conversions, and will call the error handlers listed above on overflow, underflow or denormalisation.


PrevUpHomeNext