# Boost :

From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2003-12-12 15:24:59

Guillaume Melquiond wrote:
> Le ven 12/12/2003 à 00:37, Fernando Cacciola a écrit :
>> Guillaume Melquiond wrote:
>
> [...]
>
>>> Another problem with rounding to nearest (that's because it's a
>>> rounding
>>> to "even"). This range may be too big: ( s >= S(LowestT)-S(0.5) ) &&
>>> ( s <= S(HighestT)+S(0.5) ). It's probably better if it's only < for
>>> the
>>> positive part because the biggest positive number of an integer type
>>> is usually odd.
>>
>> Yes I see... essentially the same problem as before right? I think
>> the change you suggest is appropriate, thanks!
>
> No, it's a different problem. The previous problem was caused by the
> fact the mantissa was not wide enough to handle the +0.5 without
> changing the integer value. Now there is enough precision.
>
> However, if the floating-point value is HighestT+0.5 with HighestT
> being
> odd, the closest integer is HighestT+1 when rounding to nearest, ties
> to even. Consequently you get an integer outside of your range.
> That's for
> the theory (it doesn't depend on the implementation).
>
OK, I got it now.

> Now that I'm explaining the theory, I realize that there is a more
> general problem when converting a floating-point number halfway
> between
> two integers. Let's suppose k is an integer. If the floating-point
> value
> is f=k+0.5, then the implementation always compute floor(f+0.5)=k+1 as
> the rounded value. So the applied rounding is rounding to nearest,
> ties
> to plus infinity.
>
> So the problem is: this implemented rounding is not really a standard
> one. The standard one is "ties to even" and in the future there may be
> "ties away from zero" (in the revised ieee 754 that includes decimal
> floating-point numbers).
>
Oh, I see. I was under the assumption that floor(f+0.5) tied to even, but as
you've shown, it does not.

> So I'm not sure what the best thing to do is. At least, the
> documentation should mention the default rounding to nearest is a
> strange one. But it may be worthwhile to use a more thorough
> implementation.
>
> And rather than only relying only on floor and ceil, maybe a third
> function could be used (it's just a quick thought, there probably are
> some drawbacks).
>
OK, I think I should try to figure out a corrected implementation that ties
to even as most people would expect.
If you'd like to suggest something I'd appreciate it.

>>> In the definition part of the documentation, the notions of "range"
>>> of a
>>> type and "overflow" don't match the later explanation of float to
>>> int rounding.
>> I can't find what 'later explanation' are you referring to... or I
>> don't see the error :-)
>> Can you be more specific?
>
> In the definition part, you explain a value is out of range if it is
> smaller than the smallest target value or bigger than the biggest
> target value. But, in the rounding to integer part, a value is out of
> range if
> it is outside of the destination range plus a fuzz (-1/0, -0.5/+0.5,
> 0/+1). Maybe I'm misunderstanding the definitions.
>
hmmm, help me out... I still don't follow.....

Considering that the "value" being used in the definition of overflow is an
"abstract" value, not a "typed" value in any particular format, why is it
not true that given: H=the biggest target (typed) value, then any N>abt(H)
is out-of-range w.r.t to the target type?
This is what the definition says.

IOW, how is it that the value is out if it's outside "Range(T) + something"?
Why plus something?

>>> You should also be a bit more cautious when speaking of
>>> "correct rounding". Sometimes what you describe is only a "faithful
>>> rounding" (a faithful rounding becomes correct only when the
>>> direction
>>> of rounding is precisely known). But I'm splitting hairs.
>>
>> I never quite understood the difference :-)
>> So if you can help me out with the right descriptions I'd much
>> appreciate it.
>
> The rounding is faithful when the user can't foretell the direction of
> rounding. When the result is only guaranteed to be less than 1 ulp
> away
> to the real value, the rounding is faithful.
>
OK

> The rounding is directed when a direction is given. Rounding towards
> -inf, towards +inf, towards zero, away from zero, etc are directed
> rounding.
>
OK

> And finally there is the rounding to nearest. There are lot of them
> depending on the way the ties are handled (random, to even, to odd,
> toward zero, away from zero, etc).
>
OK

> Depending on the people, correct rounding may mean two things:
> directed rounding and to nearest rounding, or only to nearest
> rounding.
>
aha, I was only aquainted of the second definition (with random tie)

> In fact, the only problem may be this sentence: "if v==prev or
> v==next,
> the representation is correctly rounded". You should remove
> "correctly"
> and put the "correctly rounded" of the next sentence in bold.

Oh yes, this would match the correct definition for "correctly" rounded.
Furthermore, I think I can replace "correctly" by "faithfully" in the
original sentence, right?

> Later you can add that in case of rounding to nearest, the precision is
1/2 ulp
> and not just 1 ulp.
>
Indeed.. I can also just add a new sentence wih the error bound for
"correctly" rounded and leave that one for "faithfull" rounding.

> Finally in the "Standard (numeric) Conversions", you may want to use
> "faithfully" rather than "correctly" since the user can't know the
> direction of rounding unless she takes a look at the implementation
> (both software and hardware).
>
Right.

>>> And why return the smallest normalized
>>> floating-point number? Why not the smallest floating-point number?
>>
>> This is because the ISO98 standard doesn't know about subnormals, so
>> the smallest value that can be portably represented as far as C++ is
>> concerned must be normalized.
>> (this is why numeric_limits<a_float_type>::min() returns a normalized
>> number)
>>
>>> Or even better the two of them?
>>
>> Because subnormals don't legally exist in C++.
>
> Yes, and they also are not forbidden, are they? It's why I suggested
> to
> put both a smallest and a really_smallest (hum...) values.
>
OK, I'll see how to implement it as portable as possible.

>>> And what about ulp(1) or the smallest
>>> floating-point number following 1?
>>>
>> This is way too big, isn't it?
>> smallest() substitutes numeric_limits<a_float_type>::min().
>
> No, I was just suggesting adding a new field, not replacing smallest.
> I rather had in mind the necessary values in order to fully define a
> classical floating-point type.
>
ha, OK, I see.

Fernando Cacciola
SciSoft