boostorg/interval — pull request #4 by nafur (2014-06-24 15:12:09+00:00)
Title: Enforce rounding in rounded_arith_opp to fix incorrect behaviour.

A discussion between Florian (corzilius@informatik.rwth-aachen.de) and Guillaume (guillaume.melquiond@inria.fr) lead to the proposed patch. Compiling the code stated below with ```clang++ -std=c++11 -O1``` leads to incorrect behaviour. (arch linux x64, clang 3.4.2, boost 1.55.0)
In a nutshell, we compare the results for ```41 * 0.1``` and ```-(-41 * 0.1)``` and the resulting intervals turn out to be disjoint, none of them containing ```4.1```. Note that tiny changes to the code (for example changing the order of the assignments) can make the error vanish.

Guillaume proposed to either switch to ```rounded_transc_std``` or add ```this->force_rounding``` to all occurrences of ```(-x)``` after a deeper look into the generated assembly. (Thanks for this!) So here is a patch for this change.

```C++
#include
#include
#include

using namespace boost::numeric;
using namespace boost::numeric::interval_lib;

typedef save_state> rnd;
typedef checking_no_nan> chk;
typedef interval> Interval;

std::ostream& operator<<(std::ostream& os, const Interval& i) {
return os << std::setprecision(1000) << "[" << i.lower() << ", " << i.upper() << "]";
}

int main() {
Interval I1( double(41) );
Interval I2( -double(41) );
Interval M = Interval( double(1) ) / Interval( double(10) );
Interval R1 = I1 * M;
Interval R2 = -(I2 * M);

if (R1.lower() > R2.upper() || R1.lower() > R2.upper()) {
std::cout << "Error: the intervals" << std::endl;
std::cout << "\t 41 * 0.1 = " << R1 << std::endl;
std::cout << "\t-(-41 * 0.1) = " << R2 << std::endl;
std::cout << "\tare disjoint!" << std::endl;
}
return 0;
}
```