|
Boost : |
From: Guillaume Melquiond (guillaume.melquiond_at_[hidden])
Date: 2008-01-14 09:01:58
Le jeudi 03 janvier 2008 à 17:47 +0000, John Maddock a écrit :
> >> boost::interval<double> in(1u);
> >> but creates a nonsense interval.
> I've since found the issue to be specific to rounded_arith_opp: it negates
> the value being converted even if it's an unsigned type. The attached patch
> fixes this, and also suppresses some pesky MSVC warnings.
I see, the behavior you experienced makes sense. I should check now why
I did not experience it; there may be an optimization bug in GCC that
hided it.
I'm a bit reluctant to apply your fix though, since it will not work
with big unsigned values. I need to think a bit more about it.
> You can see the full set of patches I've been working on here:
> http://svn.boost.org/trac/boost/changeset/42438
>
> Along with some more std lib functions and other goodies here:
> http://svn.boost.org/trac/boost/browser/sandbox/interval_math_toolkit/boost/math/bindings/interval.hpp
>
> The floor/ceil functions are the problematic ones here, these should
> probably throw in the case that the two bounds don't yield the same result
> :-)
I didn't see anything related to floor and ceil in your patch. Which
issues are you referring to?
> The most important addition is for pow: which requires modifying the
> transcendental function traits class support.
That is fine. The support class was also extended for some new functions
like expm1 and the like.
> I also found it very useful to have a traits class that always returned
> nearest rounded results for the transcendental functions when doing
> "approximate" interval arithmetic:
>
> * Using rounded_transc_opp led to situations where the resulting interval
> was invalid (rounding down returned a larger value than rounding up) with
> msvc and std::exp. I would expect to see the same with rounded_transc_std.
These two policies are mainly for use with some "smart" mathematical
libraries that properly compute elementary functions according to the
current rounding mode. As surprising as it may seem, such libraries do
exist. There is one from Sun for instance.
> * Using rounded_transc_exact as a "dummy" class with rounded_arith_opp
> produced quite erroneous results with std::exp, I gave up testing it after
> that. I assume it could be used in conjunction with rounded_transc_std OK,
> but then normal arithmetic would be slower?
This policy is meant to be used when the _exact one is used for the
arithmetic operations. For example, when performing non-guaranteed
computations on wide intervals, or when using an arbitrary precision
type for bounds.
As a summary, mixing rounding policy probably leads to unexpected
results, and calling default elementary functions with a non-exact
policy may also lead to unexpected results. I should redo the
documentation, since these points may not be that clear.
> So providing a traits class that resets the rounding mode to nearest before
> making a std lib call seemed sensible, on the assumption that these calls
> occur much less frequently than normal arithmetic, and that the cost of the
> call will swamp the cost of the rounding mode change anyway. I haven't
> investigated using a correctly rounded solution yet, but that will come :-)
Actually, there is code in the new version in order to support the
CRlibm library for computing correctly-rounded results of elementary
functions. For efficiency reasons, this library only works in rounding
to nearest (while the result is rounded in the wanted direction), so we
are using a scheme similar to the one you are describing here.
When using an elementary function from the standard libm, there could be
an additional y*(1+eps)+eta in order to ensure that the computed values
are rounded outwards. The cost would be negligible with respect to the
rounding mode change.
> Let me know if you want any more information about these patches. I'm not
> sure how these fit with the revised std lib design though?
Except for the test_input.hpp part, they would probably apply with
almost no changes. But I am still not sure about conversions.
In the proposal for standardization, we only support floating-point
bounds, conversions are done through the constructors, and they are
"explicit" when there is a precision loss (that is a potential
widening).
Perhaps this could be a way to do it. Only allow conversions in Boost if
there is no loss. For example, int and unsigned could not be used with
interval<float>, but they could be used with interval<double> on
computers where they are 32bit wide.
Best regards,
Guillaume
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk