Boost logo

Boost :

From: Robert Ramey (ramey_at_[hidden])
Date: 2006-05-15 23:10:34


David Abrahams wrote:
> "Robert Ramey" <ramey_at_[hidden]> writes:
>
>> David Abrahams wrote:
>>> "Robert Ramey" <ramey_at_[hidden]> writes:
>>>
>>>> I think we should go in the opposite direction. A float is a
>>>> a legitmate floating point value. A union of float and some
>>>> other special non-floating point values is something else.
>>>
>>> Notwithstanding the fact that NaN is "not a number," it is a
>>> legitimate floating-point value, i.e. a legitimate value for the
>>> type float.
>>
>> I guess it depends what one means by "legitimate". It is
>> is certainly "legal" in C++ - no question about that fact.
>> Its certainly not a number - no question about that either.
>> The problem is that C++ makes float a union of two
>> different things
>
> Not any more than a pointer is a "union of two different things."
> There are quite a few operations on pointers that suddenly become
> verboten when the pointer is null, and even more such operations when
> the pointer is dangling.

pointers make no pretense to implement the operations of another
system - in this case arithmetic. The concept of a pointer
being the "union of two different things" is intuitively acceptable
while its not for something meant to model a real number.

>> and that is what creates all the problems we have with it. C++
>> should correct this by making the result of arithmetic operations
>> which result in Nan's either undefined or throw exceptions. Oh I
>> know that this would break a lot of existing code.

> Not only break, but break unfixably. There are important numerical
> applications where large collections of individual floating values
> (e.g. vectors and matrices) have to be computed in parallel, and one
> or more NaNs in the result do not render the whole calculation
> useless.

I suppose that's possible. I'm not familiar with such applications.
It sounds to me that they would be implemented in special hardware
and sort of out of the C++ mainstream.

> Besides all that, eliminating NaNs from the serialization problem
> space is really impossible. Even if we struck them from the C++
> language, someone would effectively recreate them using
> optional<float> or the equivalent.

Actually that would be an improvement in that the "union" would
be explicit, visible and modifiable. In fact I could see the utility
right now of a "safe_float" which would look something like

#ifndef NDEBUG
BOOST_STRONG_TYPE(float, safe_float)
safe_float operator/(safe_float x, safe_float y){
    if(y < epsilon) // machine dependent epsilon
        throw overflow_exception
    return x / y;
}
...
#else
#define safe_float float
#endif

>> I would argue that such code is already broken anyway - it just
>> looks like its working.

> Really, you still think so?

My view on this is in another post.

> If so, I'd like to know how you measure "brokenness."

A program which produces an undefined result is "broke"

BTW - as far as the serialization system is concerned I
never had a problem with the idea of recovering the exact
kind of "undefined" data. Its just that there's no way to
do it with archives which might be ported from one machine
to another as there is no guarentee that the reading
machine has the same set of of undefined results as the
source machine. Its even worse, there is way to write
portable code which will generate any specific one
of the "undefined" types. One might hack something
together that would recover some undefined type
but it wouldn't be guarenteed to the the same original
type of undefined type. So the whole effort would be
for naught.

There was a discussion of this
on the list a while ago and this was the conclusion. It
was in the course of this discussion that I reached the
conclusions I've stated here.

Robert Ramey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk