
namespace CGAL {

/*!
\ingroup nt_util

\brief The class `Protect_FPU_rounding` allows to reduce the number of rounding mode changes when evaluating sequences of interval arithmetic operations.

\anchor protect_fpu_rouding

Floating-point arithmetic, as specified by the IEEE-754 standard, allows to use
so-called directed rounding for the following arithmetic operations: addition,
subtraction, multiplication, division and square root. The default behavior is
that the result of such an arithmetic operation is the closest floating-point
number to the exact real result of the operation (rounding to the nearest).
The other rounding modes are: round towards plus infinity, round towards minus
infinity, and round towards zero.

Interval arithmetic uses such directed rounding modes to offer guaranteed
enclosures for the evaluation of real functions, such as with \cgal's
`Interval_nt` class.

In order to efficiently evaluate sequences of interval arithmetic operations,
such as a geometric predicate computing for example a determinant, it is
advised to reduce the number of rounding mode changes, which otherwise are
performed for each arithmetic operation. \cgal exploits the fact that it is
possible to compute a sequence of interval arithmetic operations by doing only
one rounding mode change around the whole function evaluation in order to
benefit from this optimization.

The class `Protect_FPU_rounding` allows to easily benefit from this.
Its constructor saves the current rounding mode in the object, and then sets
the current rounding mode to the value provided as argument to the constructor.
The destructor sets the rounding mode back to the saved value.
This allows to protect a block of code determined by a C++ scope, and have
the destructor take care of restoring the value automatically.

The related class `Set_ieee_double_precision` allows to similarly protect
a block of code from excess precision on some machines (x86 typically with
the traditional FPU, not the more recent SSE2). Note that
`Protect_FPU_rounding`, when changing rounding modes, also sets the precision
to the correct 64 bit precision, hence providing a similar effect to
`Set_ieee_double_precision`. This notably affects the `Residue` class.

Note for Visual C++ 64-bit users: due to a compiler bug, the stack unwinding
process happening when an exception is thrown does not correctly execute the
rounding mode restoration when the `Protect_FPU_rounding` object is
destroyed. Therefore, for this configuration, some explicit code has to be
added.

\cgalHeading{Parameters}

The template parameter `Protected` is a Boolean parameter, which defaults
to `true`. It follows the same parameter of the `Interval_nt` class.
When it is `false`, the constructor and the destructor of the class do
nothing (this is meant to be used in a context where you know that the rounding
mode change has been taken care of at a higher level in the call stack.

What follows describes the behavior when the parameter has its default value,
`true`.

\sa `CGAL::Set_ieee_double_precision`

*/
template< typename Protected >
struct Protect_FPU_rounding {

/// \name Creation
/// @{

/*!
The current rounding mode is saved in the object, and rounding mode is set to `r`
which can be any of `CGAL_FE_TONEAREST`, `CGAL_FE_TOWARDZERO`,
`CGAL_FE_UPWARD` (the default) and `CGAL_FE_DOWNWARD`.
*/
Protect_FPU_rounding(FPU_CW_t r = CGAL_FE_UPWARD);



/*!
The rounding mode is restored to the saved value.
*/
~Protect_FPU_rounding();

/// @}

}; // end class
} /* end namespace CGAL */

namespace CGAL {

/*!
\ingroup nt_util

\brief The class `Set_ieee_double_precision` provides a mechanism to set
the correct 53 bits precision for a block of code. It does so by having
a default constructor that sets a particular mode on the FPU which corrects
the problem, and have its destructor reset the mode to its previous state.

\details
\anchor set_ieee_double_precision

The IEEE754 standard specifies that the precision of double precision
floating-point numbers should be 53 bits, with 11 bits for the exponent range.

Some processors violate this rule by providing excess precision during some
computations (when values are in registers). This is the case of the x86
Intel processor and compatible processors (note that the SSE2 more recent
alternative FPU is fortunately not affected by this issue). The effect of such
excess precision can be a problem for some computations, since it can produce
so-called double rounding effects, where actually <I>less</I> precision is
actually provided! It can also be the root of non-deterministic computations
depending on compiler optimizations or not (since this affects how long
variables are kept in registers), for example numerical floating-point
values get computed with slightly different results. Finally, it affects code
that carefully makes use of cancellation properties, like `Residue`.



If the platform is not affected by the excess precision problem, this class becomes an empty class doing nothing.

Note that nothing can be done for the excess range of the exponent, which
affects underflow and overflow cases, fortunately less frequent.

Note also that in the process of setting the correct precision, the rounding
mode is also set to the nearest.

Moreover, some compilers provide a flag that performs this setting at the
time of program startup. For example, GCC provides the option <TT>-mpc64</TT>
since release 4.3 which does exactly this. Other compilers may have similar
options.

Similarly, some third-party libraries may do the same thing as part of their
startup process, and this is notably the case of LEDA (at least some versions
of it). \cgal does not enforce this at startup as it would impact
computations with long double performed by other codes in the same program.

Note that this property is notably required for proper functioning of the
`Residue` class that performs modular arithmetic using efficient
floating-point operations.

Note concerning Visual C++ 64-bit: due to a compiler bug, the stack unwinding
process happening when an exception is thrown does not correctly execute the
restoring operation when the `Set_ieee_double_precision` object is
destroyed. Therefore, for this configuration, some explicit code has to be
added if you care about the state being restored.

\sa `CGAL::Protect_FPU_rounding<Protected>`
\sa `CGAL::Residue`

*/

class Set_ieee_double_precision {
public:

/// \name Creation

/// @{

/*!
Sets the precision of operations on double to 53bits.
Note that the rounding mode is set to the nearest in the same process.
*/
Set_ieee_double_precision();

/*!
The precision and rounding modes are reset to the values they held before the
constructor was called.
*/
~Set_ieee_double_precision();

/// @}

}; /* end Set_ieee_double_precision */


/*!

Sets the precision of operations on double to 53bits.
Note that the rounding mode is set to the nearest in the same process.

The function does the same thing as the default constructor of `Set_ieee_double_precision`
except that it does not perform the save and restore of the previous state.

\relates Set_ieee_double_precision
*/
void force_ieee_double_precision();


} /* end namespace CGAL */
