Copyright (c) Menno Rubingh 2016.  Web: [http://rubinghsoftware.de]

MR Mar 2016.

Handling of FLOATING-POINT ERRORS in this RPInterpreter implementation

1) How floating-point errors are handled internally.

This implementation internally does NO checking for floating-point errors
at the point where the math operations are executed during the evaluation of
an expression.
Rationale: to maximize processing speed of RPInterpreter::evaluate().

Instead, this implementation uses the "native" handling of floating point errors, 
which is to set the result to
    0            on underflow;
    +- HUGE_VAL  on overflow, and on pole error (division by zero);
    NaN          on domain error.

On under/overflow and divbyzero in a math operation, this implementation
simply uses the 0 and +-HUGE_VAL result and continues the calculation chain
with this value.  All math operations correctly handle +-HUGE_VAL as an
input (e.g. 1.0/HUGE_VAL poduces zero), and the output variables are simply
set to these values.

It is OK that output variables are set to +-HUGE_VAL (after an overflow
or divbyzero), because the values +-HUGE_VAL are correctly processed by a 
       double clip( double iVal )
           if ( iVal < MYMIN ) { return MYMIN; }
           if ( iVal > MYMAX ) { return MYMAX; }
           return iVal;
in the client code (where MYMIN and MYMAX are any finite double numbers).

The only serious error, i.e. the only error that needs to be checked for
most applications, is therefore the DOMAIN ERROR (see below).

2) How we check for a DOMAIN ERROR.

A DOMAIN ERROR means that a math operation was executed on operand values that lie
outside the intervals for with the operation is defined, such as such as raising
a negative number to a negative noninteger power.  (By the way, note that dividing
zero by zero is a domain error, not a pole error).

Occurrence of a DOMAIN ERROR occurring anywhere during the evaluation of a single
expression, or during a series of evaluation of expressions, can be checked in
two ways:

  1) By using feclearexcept() and fetestexcept(FE_INVALID) before and after a chain
     of math operations.  This detects any occurrence of a domain error anywhere
     in the chain.

  2) By calling isnan() on the double result of a chain of math operations, to
     test whether the number is a NaN.  Any domain error produces a NaN result,
     and any math operation with a NaN input produces a NaN output.  So the
     occurrence of a domain error anywhere in the chain of math operations 
     leading to the result number can be checked by testing whether the result
     number is a NaN.

This implementation uses method 2.

In this implementation of RPInterpreter, the check for a NaN result value is made
at the point where a variable is passed from interpreter to client, that is in
the function RPInterpreter::getVar().  This function returns false when the value
of the variable is a NaN, and true if it is not a NaN.