Solved: Why does boost::numeric::interval::widen not behave the same as manually applying the same logic


I have the following test code
Can somebody please explain why widen is not doing exactly the same as manually applying the widening to the limits.
See for a live demo

Best Answer:

Root Cause

The problem is floating point inexact representation. If we simplify the test program and use a decimal representation, there is no issue:
Live On Coliru

Interval Policies & Rounding Modes

It looks like the naive manual implementation results in boundaries that are closest to the intended representation if the representation cannot be exact.
By contrast it looks like widen makes sure that if the result cannot be represented exactly, the widening is guaranteed to be at least the requested amount, never accidentally slightly less due to representation issues. This means that in these situations
  • the widened lower bound may be lower than the manually calculated one
  • the widened upper bound may be higher than the manually calculated one

The behaviour can be adjusted, because it comes from the rounding policy which supplies sub_down and add_up primitives.
I would suggest not to change it, though:

if you need precise computations with the float or double types, use the default rounded_math;

rounded_math<T> is already the default.
If you insist on having identical results as the manual method (even if they are inferior):
Prints Live On Coliru

Further Caveats

There’s a documentation warning:

Warning! Guaranteed interval arithmetic for native floating-point format is not supported on every combination of processor, operating system, and compiler.

There is a list of specific compiler quirks/flags you have to keep in mind.

If you have better answer, please add a comment about this, thank you!