Topic: Can a compiler avoid a floating point multiply?
Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 11 Dec 2002 03:36:24 +0000 (UTC) Raw View
witless@attbi.com (Witless) wrote in message
> What I intended to say was that, when viewed in its canonical
> representation, numbers have continuous subfields. By "number"
> I meant floating point.
I don't consider myself an expert on floating point processors, but
let's assume that's true. But this is still a gotcha:
> By hardware address I meant within the
> layout defined by the floating point hardware.
I think you're agreeing that the byte order, when viewing floats,
may be different than the byte order when viewing other data
types, and certainly unsigned char's.
Recall that (this branch of) this thread was about casting to unsigned
char.
> Thus I would be
> extremely surprised to find a layout on any platform within
> which there was a byte containing two discontinuous regions of
> the same subfield.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 9 Dec 2002 07:17:44 +0000 (UTC) Raw View
kuyper@wizard.net ("James Kuyper Jr.") writes:
[...]
| If unsigned long uses a re-arranged byte ordering, it doesn't seem
| implausible to me that a floating-point representation would do the
| same. This is particularly true if the floating point operations are
| emulated in software, rather than implemented in hardware. 'float'
| might actually BE unsigned long, with bit masks use in the software
| emulation to pull out the exponent and mantissa.
| In that case, if unsigned long has anything other than a pure
| little-endian or pure big-endian byte ordering, then either the
| exponent or the mantissa, and possible both, will typically be
| represented by disconnected sets of bits, as extracted by your
| abstractfield_extract().
FWIW, some machines have a multi-words in little endian order and
big-endian word for floating point datatypes and "uniform" byte and
word ordering for integer types.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Thu, 5 Dec 2002 23:50:53 +0000 (UTC) Raw View
"James Kuyper Jr." wrote:
> Witless wrote:
> > "James Kuyper Jr." wrote:
> >
> >
> >>Witless wrote:
> >>
> >>>Gabriel Dos Reis wrote:
> >>>
> >>>
> >>>
> >>>>kuyper@wizard.net ("James Kuyper Jr.") writes:
> >>>>
> >>>>| Witless wrote:
> >>>>| > Gabriel Dos Reis wrote:
> >>>
> >>....
> >>
> >>>>| >>| That is what casting to unsigned char is for.
> >>>>| >>
> >>>>| >>which does not solve any problem, since there is no portable way to use it.
> >>>>| > Yet.
> >>>>| > Are you claiming that there cannot ever be a portable way to use it?
> >>>>|
> >>>>| Not as long as the C++ declines to define the actual layout used for
> >>>>| NaNs, including which order the bits are assigned to individual
> >>>>| bytes.
> >>>>
> >>>>Indeed. And I can't see any benefit of such a legislation.
> >>>
> >>>
> >>>Neither can I. But I doubt it it necessary. Why does portability require a single
> >>>layout of the bits? Couldn't multiple machines layout the bits differently and
> >>>still be abstractly defined?
> >>
> >>This was in response to the comment about "casting to unsigned char". In
> >> that context, portability does indeed require a single bit layout.
> >
> >
> > No it does not. As I explained previously, it requires a portable abstract description
> > of the layout.
>
> If "a portable abstract description of the layout" provides enough
> information to be of any use when "casting to unsigned char", I don't
> understand how such a description would differ from a precisely
> specified bit layout.
It wouldn't differ from "a precisely specified bit layout". In fact it would be exactly
that.
The missing concept is the source of the definition. If the definition is part of the
implementation, then we can have as many precisely defined bit layouts as there are
platforms. However, if the definition is part of the standard then we would have only one
precisely defined bit layout, which would be useless on many platforms.
>
>
> The only point to casting to unsigned char is to take advantage of the
> fact that such a cast lets you determine the precise contents of each
> bit. And if the standard doesn't specify precisely which bits contain
> which information about the floating point number, what use could such a
> cast be?
The standard is not the only source of information about floating point numbers. Should the
standard specify the exact value of FLT_RADIX? Of course not. The standard specifies that
the implementation must define FLT_RADIX, but the implementation defines the value of the
symbol.
> If there's anything in the description which justifies the term
> "abstract", it corresponds to NOT specifying the precise location or
> precise meaning of the information, in which case casting to unsigned
> char is useless. There's nothing in C++ which is less abstract than
> investigating individual bits.
The abstract adjective is appropriate for a description of floating point layout that makes
it irrelevant what the actual layout is, just as programming with <float.h> makes it
irrelevant what the actual value of FLT_RADIX is.
> Let's assume that C++ did indeed provide "a portable abstract
> description of the layout", whatever it is that you mean by that.
> Pretend that such a description has been provided; feel free to choose
> the nature of the description yourself. Could you show me an example of
> what code would look like that is based upon such a description which
> uses casts to unsigned char to check for NaN's?
OK, as a crude suggestion to demonstrate the possibilities, assume the existence of the
following symbols:
/*
The bit position of the exponent field within the floating point number
/*
#define DBL_EXP_OFFSET 1
#define DBL_EXP_LENGTH 15
/*
The value of the exponent of a NaN; -1 if not supported
*/
#define DBL_NAN_EXP 0x7FFF
/*
extracts a bitfield described by offset & length from the bits in src
Bit zero is the LSB of src[0].
Bit (CHAR_BIT-1) is the MSB of src[0]
Bit CHAR_BIT is the LSB of src[1]
etc.
The bitfield value is right justified within the returned value.
*/
unsigned long abstractfield_extract( unsigned char *src, unsigned int offset, unsigned
int length);
.... then isNaN could be portably (but crudely) written as:
bool isnan( double D )
{
#if DBL_NAN_EXP == -1
return false;
#else
unsigned long exponent;
exponent = abstractfield_extract( (unsigned char *) D, DBL_EXP_OFFSET, DBL_EXP_LENGTH
);
return exponent == DBL_NAN_EXP;
#endif
}
Of course these definitions should be represented in numeric_limits<> or something similar.
Perhaps numeric_layout<> would be appropriate.
>
> So far, the only idea I've come up with that technically meets this
> challenge would be to mandate an isnan() function which is overloaded
> for "unsigned char*", as well as for float and double. But that would be
> pointless.
And almost useless, given than NaN != NaN is supposed to be an adequate test for NaN values
already.
I think a more interesting example would be a mechanism to encode and decode arbitrary
information in the unused fields of a NaN. Clearly the standard cannot anticipate the needs
of the application. Nor can the implementation. But between them then can provide a
mechanism for the application designer to portably utilize the pass-through properties of
NaNs on any platform that supports them.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Fri, 6 Dec 2002 01:49:36 +0000 (UTC) Raw View
Witless wrote:
> "James Kuyper Jr." wrote:
>
>
>>Witless wrote:
>>
>>>"James Kuyper Jr." wrote:
....
>>>>This was in response to the comment about "casting to unsigned char". In
>>>> that context, portability does indeed require a single bit layout.
^^^^^^^^^^^
>>>
>>>
>>>No it does not. As I explained previously, it requires a portable abstract description
>>>of the layout.
>>
>>If "a portable abstract description of the layout" provides enough
>>information to be of any use when "casting to unsigned char", I don't
>>understand how such a description would differ from a precisely
>>specified bit layout.
>
>
> It wouldn't differ from "a precisely specified bit layout". In fact it would be exactly
> that.
>
> The missing concept is the source of the definition. If the definition is part of the
> implementation, then we can have as many precisely defined bit layouts as there are
> platforms. However, if the definition is part of the standard then we would have only one
> precisely defined bit layout, which would be useless on many platforms.
And how exactly could portable code make use of something that's
different on each platform? You can do that only by constraining the
range of possible representations more strongly than the C++ standard
currently does.
>>Let's assume that C++ did indeed provide "a portable abstract
>>description of the layout", whatever it is that you mean by that.
>>Pretend that such a description has been provided; feel free to choose
>>the nature of the description yourself. Could you show me an example of
>>what code would look like that is based upon such a description which
>>uses casts to unsigned char to check for NaN's?
>
>
> OK, as a crude suggestion to demonstrate the possibilities, assume the existence of the
> following symbols:
>
> /*
> The bit position of the exponent field within the floating point number
> /*
> #define DBL_EXP_OFFSET 1
> #define DBL_EXP_LENGTH 15
>
> /*
> The value of the exponent of a NaN; -1 if not supported
> */
> #define DBL_NAN_EXP 0x7FFF
>
> /*
> extracts a bitfield described by offset & length from the bits in src
> Bit zero is the LSB of src[0].
> Bit (CHAR_BIT-1) is the MSB of src[0]
> Bit CHAR_BIT is the LSB of src[1]
> etc.
> The bitfield value is right justified within the returned value.
> */
> unsigned long abstractfield_extract( unsigned char *src, unsigned int offset, unsigned
> int length);
I'm trying to figure out whether abstractfield_extract() is meant to be
used only on floating point values, or is meant to be a general purpose
function. If it's meant specifically for floating point values, it
should be overloaded to take "float*" and "double*" arguments, and
there's no point in it taking an "unsigned char*" argument, which is the
point I've been trying to make from the beginning.
If it's meant to be general purpose, making such an approach work
constrains floating point representations in ways that the C++ standard
currently does not. It requires that the mantissa and exponent be
encoded as consecutive bits with the same bit order as is implemented by
abstractfield_extract() (which would presumably be consistent with the
order used by unsigned int and unsigned long?).
I'm not sure this could be implemented in any useable form on machines
(and there are several) where 0x04030201 has the same binary
representation as "\004\002\003\001" or as "\001\003\002\004". The world
isn't just big-endian vs. little-endian There's 24 different ways in
which the bytes of a 4-byte integer can be ordered, and at least 6 of
those ways are actually in use. C++ is currently implementable on a
platform using any of those 24 possibilities.
You're also requiring that NaNs are identified by the value of their
exponent, and that there is only one value for that exponent which
identifies a NaN. The standard currently says absolutely nothing about
such details.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Fri, 6 Dec 2002 16:29:27 +0000 (UTC) Raw View
"James Kuyper Jr." wrote:
> Witless wrote:
> > "James Kuyper Jr." wrote:
> >
> >
> >>Witless wrote:
> >>
> >>>"James Kuyper Jr." wrote:
> ....
> >>>>This was in response to the comment about "casting to unsigned char". In
> >>>> that context, portability does indeed require a single bit layout.
> ^^^^^^^^^^^
> >>>
> >>>
> >>>No it does not. As I explained previously, it requires a portable abstract description
> >>>of the layout.
> >>
> >>If "a portable abstract description of the layout" provides enough
> >>information to be of any use when "casting to unsigned char", I don't
> >>understand how such a description would differ from a precisely
> >>specified bit layout.
> >
> >
> > It wouldn't differ from "a precisely specified bit layout". In fact it would be exactly
> > that.
> >
> > The missing concept is the source of the definition. If the definition is part of the
> > implementation, then we can have as many precisely defined bit layouts as there are
> > platforms. However, if the definition is part of the standard then we would have only one
> > precisely defined bit layout, which would be useless on many platforms.
>
> And how exactly could portable code make use of something that's
> different on each platform?
You mean like FLT_RADIX?
> You can do that only by constraining the
> range of possible representations more strongly than the C++ standard
> currently does.
> >>Let's assume that C++ did indeed provide "a portable abstract
> >>description of the layout", whatever it is that you mean by that.
> >>Pretend that such a description has been provided; feel free to choose
> >>the nature of the description yourself. Could you show me an example of
> >>what code would look like that is based upon such a description which
> >>uses casts to unsigned char to check for NaN's?
> >
> >
> > OK, as a crude suggestion to demonstrate the possibilities, assume the existence of the
> > following symbols:
> >
> > /*
> > The bit position of the exponent field within the floating point number
> > /*
> > #define DBL_EXP_OFFSET 1
> > #define DBL_EXP_LENGTH 15
> >
> > /*
> > The value of the exponent of a NaN; -1 if not supported
> > */
> > #define DBL_NAN_EXP 0x7FFF
> >
> > /*
> > extracts a bitfield described by offset & length from the bits in src
> > Bit zero is the LSB of src[0].
> > Bit (CHAR_BIT-1) is the MSB of src[0]
> > Bit CHAR_BIT is the LSB of src[1]
> > etc.
> > The bitfield value is right justified within the returned value.
> > */
> > unsigned long abstractfield_extract( unsigned char *src, unsigned int offset, unsigned
> > int length);
>
> I'm trying to figure out whether abstractfield_extract() is meant to be
> used only on floating point values, or is meant to be a general purpose
> function.
As above it's a general purpose function for extracting bitfields of arbitrary alignment. It
has nothing to do with floating point values.
> If it's meant specifically for floating point values, it
> should be overloaded to take "float*" and "double*" arguments, and
> there's no point in it taking an "unsigned char*" argument, which is the
> point I've been trying to make from the beginning.
>
> If it's meant to be general purpose, making such an approach work
> constrains floating point representations in ways that the C++ standard
> currently does not. It requires that the mantissa and exponent be
> encoded as consecutive bits with the same bit order as is implemented by
> abstractfield_extract()
As written above, yes. I didn't think that scatter/gather logic was necessary to make the point
that an abstract definition is possible.
> (which would presumably be consistent with the
> order used by unsigned int and unsigned long?).
Now that's an unreasonable assumption.
>
>
> I'm not sure this could be implemented in any useable form on machines
> (and there are several) where 0x04030201 has the same binary
> representation as "\004\002\003\001" or as "\001\003\002\004". The world
> isn't just big-endian vs. little-endian There's 24 different ways in
> which the bytes of a 4-byte integer can be ordered, and at least 6 of
> those ways are actually in use. C++ is currently implementable on a
> platform using any of those 24 possibilities.
I've only worked on machines of four distinct byte orderings. If we look hard enough we might
find versions of all 24 possibilities. But there are only 6 possible orderings over {sign,
exponent, mantissa}. And in my limited experience I know of no architecture in which the
subfields of a number are discontinuous when viewed in order of hardware address (uchar).
But this has nothing to do with the defining the layout of a floating point object in a
platform-independent manner, which you claimed requires a single universal layout specification
within the standard.
So it is your turn to be specific. Please pick a platform on which you believe an abstract
definition is impossible. Alternatively you could pick a pair of platforms that have such
inconsistent layouts that it would impossible to define both of them with the same property
list.
>
>
> You're also requiring that NaNs are identified by the value of their
> exponent, and that there is only one value for that exponent which identifies a NaN.
I think you are reading too much into the example. Standardizing the abstract property list of
floating point layouts would require an inventory of the layouts that need to be expressible.
Is it your opinion that that inventory effort is unreasonably large?
IMHO the worst part of the example I gave is that it assumes that the boundaries of the
subfields of floating point values are fixed, and that is not true on all architectures. But
even there we support DBL_MANT_DIG and the rest of <float.h>.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 00:29:44 +0000 (UTC) Raw View
Witless wrote:
> "James Kuyper Jr." wrote:
>
>
>>Witless wrote:
....
>>And how exactly could portable code make use of something that's
>>different on each platform?
>
>
> You mean like FLT_RADIX?
Yes, that's one approach to handling it. But the number of free
parameters in the C++ standard's current definition of floating point
representations is too large to be captured by any reasonable number of
such macros. You'll have to either constrain representations far more
tightly than the current standard does, or take what I consider the far
more sensible approach used by C99 for these purposes (see details
farther down).
....
>>If it's meant to be general purpose, making such an approach work
>>constrains floating point representations in ways that the C++ standard
>>currently does not. It requires that the mantissa and exponent be
>>encoded as consecutive bits with the same bit order as is implemented by
>>abstractfield_extract()
....
>>(which would presumably be consistent with the
>>order used by unsigned int and unsigned long?).
>
>
> Now that's an unreasonable assumption.
Actually, it's directly to my point. Unsigned long does have several
different byte orderings on different platforms. There's two
possibilities: abstractfield_extract() takes those byte orderings into
consideration when determining which bits to extract, or it doesn't.
There's problems with either approach, but given your comments, I'll
assume the second option. The problem with the first option is simply
the reverse of the problem I'm about to describe:
If unsigned long uses a re-arranged byte ordering, it doesn't seem
implausible to me that a floating-point representation would do the
same. This is particularly true if the floating point operations are
emulated in software, rather than implemented in hardware. 'float' might
actually BE unsigned long, with bit masks use in the software emulation
to pull out the exponent and mantissa.
In that case, if unsigned long has anything other than a pure
little-endian or pure big-endian byte ordering, then either the exponent
or the mantissa, and possible both, will typically be represented by
disconnected sets of bits, as extracted by your abstractfield_extract().
....
> But this has nothing to do with the defining the layout of a floating point object in a
> platform-independent manner, which you claimed requires a single universal layout specification
> within the standard.
Incorrect; I'm merely claiming that a user-code cast to "unsigned char*"
has no proper place in the interface for such an abstract layout
mechanism. The relevant functions should be overloaded for float,
double, and long double arguments; the bit-extraction should be
controlled by the standard library code, and be invisible to the user.
> So it is your turn to be specific. Please pick a platform on which you believe an abstract
> definition is impossible.
There aren't any; I never claimed that there were. But there are
platforms with features that make it fairly complicated; and there are
possible platforms that haven't actually been built yet, where the
current standard is easily implementable, which would add enormous
complexity to your idea.
>>You're also requiring that NaNs are identified by the value of their
>>exponent, and that there is only one value for that exponent which identifies a NaN.
>
>
> I think you are reading too much into the example. Standardizing the abstract property list of
> floating point layouts would require an inventory of the layouts that need to be expressible.
> Is it your opinion that that inventory effort is unreasonably large?
Yes. Currently, the standard allows a great deal of freedom to
implementations in their floating point representations, and I see no
point in constraining those more than they currently are. To do what
you're talking about without adding constraints would require a very
large inventory; you'd need thousands of macros to cover all the
possibilities.
That's particularly a problem since there's a far more appropriate way
of gaining access to the same information, which does not constrain the
representations any more than the current standard already does. This
way has the additional advantage of already having been implemented as
part of C99. It's just a matter of borrowing and adapting the concepts
to the C++ environment; most notably by using overloading to reduce the
number of different function names needed.
C99 includes the following features:
1. classification macros such as isnan() and isinf() for classifying
floating point numbers.
2. The signbit() macro for extracting the sign bit.
3. The frexp() function for breaking a floating point number into its
mantissa and exponent parts.
4. The ldexp() function for efficient putting a mantissa and exponent
back together to form a floating point value.
5. The scalbn() family of functions for computing x*FLT_RADIX^n efficiently.
6. The copysign(x,y) function for creating a value with the same sign as
x and the same magnitude as y.
7. The nextafter() and nexttoward() functions for creating new floating
point numbers that are just 1 ulp away from the specified values.
8. The comparison functions like isgreater(x,y) for comparing floating
point values quietly; without raising the "invalid" floating point
except that is normally allowed for x>y if one of the two values is a NaN.
9. The nan() function and the NAN and INFINITY macros.
What could you possibly want to do with your "portable abstract
description" that you couldn't do in a far more convenient way using
these functions and macros? And, since all the details of the actual
representation are hidden inside standard library functions, none of
these functions impose any new constraints on the representation of
floating point numbers. It might seem otherwise with some of those
functions, but for instance, nan() is defined as returning 0.0 on
platforms that don't support quiet NaNs. isinf() isn't required to ever
be true, if the floating point representation doesn't support infinities.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Mon, 9 Dec 2002 22:14:22 +0000 (UTC) Raw View
witless@attbi.com (Witless) wrote
> "James Kuyper Jr." wrote:
> > I'm not sure this could be implemented in any useable form on machines
> > (and there are several) where 0x04030201 has the same binary
> > representation as "\004\002\003\001" or as "\001\003\002\004". The world
> > isn't just big-endian vs. little-endian There's 24 different ways in
> > which the bytes of a 4-byte integer can be ordered, and at least 6 of
> > those ways are actually in use. C++ is currently implementable on a
> > platform using any of those 24 possibilities.
>
> I've only worked on machines of four distinct byte orderings. If
> we look hard enough we might find versions of all 24 possibilities.
> But there are only 6 possible orderings over {sign, exponent,
> mantissa}.
There are only 6 possible orderings over (sign, exponent, mantissa),
that's true. Furthermore, I suspect (but have no proof) that the order
(sign, exponent, mantissa) was overwhelmingly popular -- other encodings
certainly were not popular. But those orderings are not neccesarily
byte-aligned, which means that you might have to multiply it by the 24
possible orderings of bytes -- and even that assumes that float is
always 4 bytes, which is not always true.
> And in my limited experience I know of no architecture
> in which the subfields of a number are discontinuous when viewed
> in order of hardware address (uchar).
Then you must not be omniscient! :-) Please consider the
PDP-11 architechture, which used least-significant byte first for
16-bit "word" integers:
0x1234 was 34,12 or (00110100)(00010010)
The RSX-11 Operating System had a convention for 32-bit integers:
most-significant word first.
0x12345678 was 34, 12, 78, 56 or (00110100)(00010010)(01111000)(01010110)
You could argue that the RSX-11 32-bit integers were designed incorrectly;
since the hardware recognized the first byte as the low byte, the OS
should have done so too. You might have a point; but when RSX was first
created, the designers probably assumed that the order would never matter
to the hardware. If so, they were wrong -- the difference caused difficulty
when porting code to the VAX-11, where it was true least-significant-byte
first ordering:
0x12345678 was 78, 56, 34, 12 or (01111000)(01010110)(00110100)(00010010)
At any rate, saying that the OS did it wrong wouldn't help. If the C
compiler for that system had changed the byte order to pure "little-endian"
order, then it would have been impossible to pass long values to the OS.
I don't remember the exact layout of floating point bits, but it was
something like this: 1 bit of sign, 8 bits of excess-128 exponent,
23 bits of mantissa (leading "1" bit removed unless exponent was 0).
Bitwise, that looks like this:
SEEEEEEE eMMMMMMM mmmmmmmm nnnnnnnn
(S=Sign, E=high bits of exponent, e=low bit of exponent,
M=High bits of mantissa, m=middle bits of mantissa,
n=lowest bits of mantissa)
Bytewise, that would look like this when converted to unsigned char's:
eMMMMMMM SEEEEEEE nnnnnnnn mmmmmmmm
(The machine probably had NAN's too, but I don't remember how that was
stored.)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Mon, 9 Dec 2002 23:35:44 +0000 (UTC) Raw View
Allan W wrote:
> witless@attbi.com (Witless) wrote
> > I've only worked on machines of four distinct byte orderings. If
> > we look hard enough we might find versions of all 24 possibilities.
> > But there are only 6 possible orderings over {sign, exponent,
> > mantissa}.
>
> There are only 6 possible orderings over (sign, exponent, mantissa),
> that's true. Furthermore, I suspect (but have no proof) that the order
> (sign, exponent, mantissa) was overwhelmingly popular -- other encodings
> certainly were not popular. But those orderings are not neccesarily
> byte-aligned, which means that you might have to multiply it by the 24
> possible orderings of bytes -- and even that assumes that float is
> always 4 bytes, which is not always true.
No, we don't have to enumerate all possible bit layouts. We only have to
enumerate the cases that cannot be distinguished by adjusting a descriptor such
as a field width.
>
> > And in my limited experience I know of no architecture
> > in which the subfields of a number are discontinuous when viewed
> > in order of hardware address (uchar).
>
> Then you must not be omniscient! :-) Please consider the
> PDP-11 architechture, which used least-significant byte first for
> 16-bit "word" integers:
> 0x1234 was 34,12 or (00110100)(00010010)
> The RSX-11 Operating System had a convention for 32-bit integers:
> most-significant word first.
> 0x12345678 was 34, 12, 78, 56 or (00110100)(00010010)(01111000)(01010110)
I wrote that badly. Worse than that. I "grew up" on '-11s and don't need to
quote other platforms to produce evidence of strange layouts.
What I intended to say was that, when viewed in its canonical representation,
numbers have continuous subfields. By "number" I meant floating point. By
hardware address I meant within the layout defined by the floating point
hardware. Thus I would be extremely surprised to find a layout on any platform
within which there was a byte containing two discontinuous regions of the same
subfield.
As an example, using s, e, and m to represent bits of a byte, within a byte we
could find arbitrary mixtures of S, E, and M bits, but no groups of M bits is
separated by S or E bits and no groups of E bits is separated by S or M bits. By
S bits i mean to include all forms of flag bits that might be used to encode
special properties of a number.
All of these could be expected:
seeeeeee, eeeemmmm, smmmmmmm, seeeeemm,
but all of these would surprise me:
eeeeseeee, eemmmmee, mmemmsmm, etc.
> You could argue that the RSX-11 32-bit integers were designed incorrectly;
> since the hardware recognized the first byte as the low byte, the OS
> should have done so too.
I could, but I won't. Learning to read hex dumps of arbitrary byte order is a
necessary skill for any serious programmer. Good ones can read the ASCII columns
too. And VAXen didn't eliminate the need for the skill.
In my experience there are far more dump orders in use than there are possible
byte orders for the hardware. ;-)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Wed, 4 Dec 2002 21:03:53 +0000 (UTC) Raw View
Witless wrote:
> Gabriel Dos Reis wrote:
>
>
>>kuyper@wizard.net ("James Kuyper Jr.") writes:
>>
>>| Witless wrote:
>>| > Gabriel Dos Reis wrote:
....
>>| >>| That is what casting to unsigned char is for.
>>| >>
>>| >>which does not solve any problem, since there is no portable way to use it.
>>| > Yet.
>>| > Are you claiming that there cannot ever be a portable way to use it?
>>|
>>| Not as long as the C++ declines to define the actual layout used for
>>| NaNs, including which order the bits are assigned to individual
>>| bytes.
>>
>>Indeed. And I can't see any benefit of such a legislation.
>
>
> Neither can I. But I doubt it it necessary. Why does portability require a single
> layout of the bits? Couldn't multiple machines layout the bits differently and
> still be abstractly defined?
This was in response to the comment about "casting to unsigned char". In
that context, portability does indeed require a single bit layout.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Thu, 5 Dec 2002 07:07:57 +0000 (UTC) Raw View
"James Kuyper Jr." wrote:
> Witless wrote:
> > Gabriel Dos Reis wrote:
> >
> >
> >>kuyper@wizard.net ("James Kuyper Jr.") writes:
> >>
> >>| Witless wrote:
> >>| > Gabriel Dos Reis wrote:
> ....
> >>| >>| That is what casting to unsigned char is for.
> >>| >>
> >>| >>which does not solve any problem, since there is no portable way to use it.
> >>| > Yet.
> >>| > Are you claiming that there cannot ever be a portable way to use it?
> >>|
> >>| Not as long as the C++ declines to define the actual layout used for
> >>| NaNs, including which order the bits are assigned to individual
> >>| bytes.
> >>
> >>Indeed. And I can't see any benefit of such a legislation.
> >
> >
> > Neither can I. But I doubt it it necessary. Why does portability require a single
> > layout of the bits? Couldn't multiple machines layout the bits differently and
> > still be abstractly defined?
>
> This was in response to the comment about "casting to unsigned char". In
> that context, portability does indeed require a single bit layout.
No it does not. As I explained previously, it requires a portable abstract description
of the layout.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Thu, 5 Dec 2002 18:10:31 +0000 (UTC) Raw View
Witless wrote:
> "James Kuyper Jr." wrote:
>
>
>>Witless wrote:
>>
>>>Gabriel Dos Reis wrote:
>>>
>>>
>>>
>>>>kuyper@wizard.net ("James Kuyper Jr.") writes:
>>>>
>>>>| Witless wrote:
>>>>| > Gabriel Dos Reis wrote:
>>>
>>....
>>
>>>>| >>| That is what casting to unsigned char is for.
>>>>| >>
>>>>| >>which does not solve any problem, since there is no portable way to use it.
>>>>| > Yet.
>>>>| > Are you claiming that there cannot ever be a portable way to use it?
>>>>|
>>>>| Not as long as the C++ declines to define the actual layout used for
>>>>| NaNs, including which order the bits are assigned to individual
>>>>| bytes.
>>>>
>>>>Indeed. And I can't see any benefit of such a legislation.
>>>
>>>
>>>Neither can I. But I doubt it it necessary. Why does portability require a single
>>>layout of the bits? Couldn't multiple machines layout the bits differently and
>>>still be abstractly defined?
>>
>>This was in response to the comment about "casting to unsigned char". In
>> that context, portability does indeed require a single bit layout.
>
>
> No it does not. As I explained previously, it requires a portable abstract description
> of the layout.
If "a portable abstract description of the layout" provides enough
information to be of any use when "casting to unsigned char", I don't
understand how such a description would differ from a precisely
specified bit layout.
The only point to casting to unsigned char is to take advantage of the
fact that such a cast lets you determine the precise contents of each
bit. And if the standard doesn't specify precisely which bits contain
which information about the floating point number, what use could such a
cast be? If there's anything in the description which justifies the term
"abstract", it corresponds to NOT specifying the precise location or
precise meaning of the information, in which case casting to unsigned
char is useless. There's nothing in C++ which is less abstract than
investigating individual bits.
Let's assume that C++ did indeed provide "a portable abstract
description of the layout", whatever it is that you mean by that.
Pretend that such a description has been provided; feel free to choose
the nature of the description yourself. Could you show me an example of
what code would look like that is based upon such a description which
uses casts to unsigned char to check for NaN's?
So far, the only idea I've come up with that technically meets this
challenge would be to mandate an isnan() function which is overloaded
for "unsigned char*", as well as for float and double. But that would be
pointless.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Sun, 1 Dec 2002 18:13:51 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> Witless <witless@attbi.com> writes:
>
> [...]
>
> | > | > Are you claiming that there cannot ever be a portable way to use it?
> | > |
> | > | Not as long as the C++ declines to define the actual layout used for
> | > | NaNs, including which order the bits are assigned to individual
> | > | bytes.
> | >
> | > Indeed. And I can't see any benefit of such a legislation.
> |
> | Neither can I. But I doubt it it necessary. Why does portability require a single
> | layout of the bits? Couldn't multiple machines layout the bits differently and
> | still be abstractly defined?
>
> Certainly. That is the point of having the bindings for appropriate
> standards (LIA, IEEE-754, ...).
>
> [...]
>
> | > C99 tries to legislate about negative zero (following IEEE-754) and
> | > messes up. Let's learn about it :-)
> |
> | Learn what?
>
> http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_218.htm
This indicates that there are architectures incapable of supporting the IEEE standards.
This is not news.
>
>
> | That we need +und, zero, and -und instead of +zero and -zero?
>
> What is "und"?
Sorry. UNDerflow. The IEEE standards compromised the full requirements for consistent
handling of floating point values by merging the concepts of zero and underflow. They
expressed a need to support the legacy practice of graceful underflow. To achieve this
they merged underflow, which is, of course, signed, and zero, which is, of course, not
signed. The result, signed zeros, do make interval arithmetic and a few esoteric uses
practicable, but they are completely inadequate for rigorous numeric handling. Any time
you overload a result with both valid values and error values you complicate the value
consumer's life. If you do so with indistinguishable values, you make the value
consumer's life impossible,
The IEEE standards also merged the concepts of overflow and infinity. Overflow is an
error indicator. Infinity, while properly a kind of NaN, is useful enough that it might
merit its own encoding. Certainly the sign of infinity is a meaningful concept whereas
the sign of NaN is less so.
Note that the inclusion of distinct under and overflows would have permitted more
graceful error handling than is possible with the current standards. Given a program
that produces an infinity, one is not sure how far off the result might have been.
Would changing from double to float allow the program to complete? Similar issues attend
underflow, with the added problem of deciding whether zero is a correct result or an
error.
A distinct exponent encoding of overflow and underflow would leave the mantissa available
to provide a hint of the exponent magnitude required to represent the desired value.
This possibility was lost when zero ate underflow and infinity ate overflow.
I realize that at the time the standard was adopted the general attitude toward special
numeric values was very negative. But the evolution of computer architecture, both
hardware and software, suggests that they should relieve the user of the requirement to
determine the sanity of the results produced. That requires the capability to express
all of the possible annotations that might be used to label a result value be
representable within the machine. And, of course, all representable values have to be
consistently handled by the extended algebra over those values.
I have spent a lot of time programming over, under, around, and through the IEEE
standards in an attempt to produce software that handles numbers consistently and
reliably. It is extremely difficult given the present standards. However, without the
IEEE standards or similarly capable hardware, it is impossible. So attempting to solve
the problem of missing signs on special values does not belong in a language standard.
It belongs in a minimum standard for language support.
There is a conflict between the desire to support languages on as many architectures as
possible and the desire to provide language users with as good a platform as is
possible. For decades now we have been pursuing the former at the expense of the
latter. IMHO that is a mistake.
We don't need one size (standard) fits all. But we do need all the shoes to have some
form of closure whether laces, buckles, or hook-and-loop. Loafers will never make good
running shoes. So we do need all machines to have a minimum set of capabilities, even if
those capabilities are not organized in a single, standard way.
Machines that do not meet the minimum capabilities should have relaxed conformance
requirements. The difference would provide the "Hyre Be Dragyns" signs that would warn
of the machines where promises of conformance come at a great price.
Moral: we do not write software to tell machines what to do. We build machines to
execute our software. So, rather than describe languages as fitting on as many
architectures as possible, we should describe architectures as supporting as many
languages as possible. Unless and until we start imposing minimum requirements on
machines we will remain mired in the edges effects of legacy systems. We tend to let
those considerations dominate our standards in the same way that outliers dominate a
least-squares fit. And that can be a grave error.
Sorry for the rant.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@students.cs.mu.OZ.AU (Fergus Henderson)
Date: Sun, 1 Dec 2002 18:45:59 +0000 (UTC) Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) writes:
>C99 tries to legislate about negative zero (following IEEE-754) and
>messes up. Let's learn from it :-)
What's wrong with C99's treatment of negative zeros?
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 2 Dec 2002 06:57:30 +0000 (UTC) Raw View
Witless wrote:
> "James Kuyper Jr." wrote:
>
>
>>Witless wrote:
>> > Gabriel Dos Reis wrote:
>> >
>> >
>> >>kuyper@wizard.net ("James Kuyper Jr.") writes:
>> >>
>> >>| Witless wrote:
>> >>| > Gabriel Dos Reis wrote:
>>....
>> >>| >>| That is what casting to unsigned char is for.
>> >>| >>
>> >>| >>which does not solve any problem, since there is no portable way
>>to use it.
>> >>| > Yet.
>> >>| > Are you claiming that there cannot ever be a portable way to use it?
>> >>|
>> >>| Not as long as the C++ declines to define the actual layout used for
>> >>| NaNs, including which order the bits are assigned to individual
>> >>| bytes.
>> >>
>> >>Indeed. And I can't see any benefit of such a legislation.
>> >
>> >
>> > Neither can I. But I doubt it it necessary. Why does portability
>>require a single
>> > layout of the bits? Couldn't multiple machines layout the bits
>>differently and
>> > still be abstractly defined?
>>
>>This was in response to the comment about "casting to unsigned char". In
>> that context, portability does indeed require a single bit layout.
>
>
> Why?
>
> The only necessary assumption appears to be that casting to an array of
> unsigned character renders all the interesting bits accessible. Given that
> assumption and the fact that we can number the bits within the uchar array, it
> is possible to express the layout of an object in purely abstract terms
> consisting of offset/length/direction tuples expressed as numbers of bits.
> This would be a natural extension of <float.h>, although not a trivial one.
Yes, that would be perfectly feasible. And how would you portably use
that information to identify a NaN? Keep in mind that the C++ standard
does NOT specify the the bit patterns that identify a NaN. There are
IEEE/IEC floating point standards DO identify those bit patterns, but
C++ does not mandate IEEE/IEC format (though it does a way to test for
IEC 559 support). In my opinion, C++ shouldn't be changed to mandate
that format - C++ should be implementable on platforms that don't have
native support for IEEE/IEC floating point.
The right approach is to adopt an approach similar to the one used by
C99. It provides isnan(), isfinite(), isnormal(), and nan() functions.
How a NaN can be detected is left up to the implementation, as is the
question of whether they're even allowed. The C++ equivalents should
probably be added to std::numeric_limits<>, or some other similar traits
class.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 2 Dec 2002 07:01:28 +0000 (UTC) Raw View
witless@attbi.com (Witless) writes:
| > | > C99 tries to legislate about negative zero (following IEEE-754) and
| > | > messes up. Let's learn about it :-)
| > |
| > | Learn what?
| >
| > http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_218.htm
|
| This indicates that there are architectures incapable of supporting the IEEE standards.
| This is not news.
Nobody said it was news that there are plateforms where IEEE-754
inventions don't make any sense. Please reread what you quoted (above)
from my earlier message.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 2 Dec 2002 07:01:50 +0000 (UTC) Raw View
witless@attbi.com (Witless) writes:
| We don't need one size (standard) fits all.
This is precisely one of the reasons why I'm not a fan of IEEE-754
and C99 legislation. Especially when there are better alternatives.
--
Gabriel Dos Reis, gdr@integrables-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 2 Dec 2002 07:01:51 +0000 (UTC) Raw View
fjh@students.cs.mu.OZ.AU (Fergus Henderson) writes:
| gdr@integrable-solutions.net (Gabriel Dos Reis) writes:
|
| >C99 tries to legislate about negative zero (following IEEE-754) and
| >messes up. Let's learn from it :-)
|
| What's wrong with C99's treatment of negative zeros?
See the TC link I posted earlier in this thread.
--
Gabriel Dos Reis, gdr@integrable-solitions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 2 Dec 2002 16:50:58 +0000 (UTC) Raw View
kuyper@wizard.net ("James Kuyper Jr.") writes:
| The right approach is to adopt an approach similar to the one used by
| C99. It provides isnan(), isfinite(), isnormal(), and nan()
| functions.
Agreed in principle. But, I would like to see C++ use the abstractions
there to implement a superior model, i.e. LIA.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Mon, 2 Dec 2002 19:12:39 +0000 (UTC) Raw View
"James Kuyper Jr." wrote:
> Witless wrote:
> > "James Kuyper Jr." wrote:
> >
> >
> >>Witless wrote:
> >> > Gabriel Dos Reis wrote:
> >> >
> >> >
> >> >>kuyper@wizard.net ("James Kuyper Jr.") writes:
> >> >>
> >> >>| Witless wrote:
> >> >>| > Gabriel Dos Reis wrote:
> >>....
> >> >>| >>| That is what casting to unsigned char is for.
> >> >>| >>
> >> >>| >>which does not solve any problem, since there is no portable way
> >>to use it.
> >> >>| > Yet.
> >> >>| > Are you claiming that there cannot ever be a portable way to use it?
> >> >>|
> >> >>| Not as long as the C++ declines to define the actual layout used for
> >> >>| NaNs, including which order the bits are assigned to individual
> >> >>| bytes.
> >> >>
> >> >>Indeed. And I can't see any benefit of such a legislation.
> >> >
> >> >
> >> > Neither can I. But I doubt it it necessary. Why does portability
> >>require a single
> >> > layout of the bits? Couldn't multiple machines layout the bits
> >>differently and
> >> > still be abstractly defined?
> >>
> >>This was in response to the comment about "casting to unsigned char". In
> >> that context, portability does indeed require a single bit layout.
> >
> >
> > Why?
> >
> > The only necessary assumption appears to be that casting to an array of
> > unsigned character renders all the interesting bits accessible. Given that
> > assumption and the fact that we can number the bits within the uchar array, it
> > is possible to express the layout of an object in purely abstract terms
> > consisting of offset/length/direction tuples expressed as numbers of bits.
> > This would be a natural extension of <float.h>, although not a trivial one.
>
> Yes, that would be perfectly feasible. And how would you portably use
> that information to identify a NaN?
I wouldn't. I'd prefer to use a set of portable functions such as isNaN. But, for
no good reason AFAICT, we don't have them.
As a minimum substitute I'd like to see:
#define NAN_EXP (/* integer expression*/)
> Keep in mind that the C++ standard
> does NOT specify the the bit patterns that identify a NaN. There are
> IEEE/IEC floating point standards DO identify those bit patterns, but
> C++ does not mandate IEEE/IEC format (though it does a way to test for
> IEC 559 support). In my opinion, C++ shouldn't be changed to mandate
> that format - C++ should be implementable on platforms that don't have
> native support for IEEE/IEC floating point.
Of course. This issue isn't about IEEE. It is about extended floating point.
>
>
> The right approach is to adopt an approach similar to the one used by
> C99. It provides isnan(), isfinite(), isnormal(), and nan() functions.
> How a NaN can be detected is left up to the implementation, as is the
> question of whether they're even allowed. The C++ equivalents should
> probably be added to std::numeric_limits<>, or some other similar traits
> class.
Yes, but the simple predicates are insufficient. We need to be able to compose and
decompose NaNs in order to provide and handle diagnostic information. That cannot
be left to the implementation.
We aren't arguing about the best answer, we are arguing about having _any_ solution
at all. The case I am making is that it just isn't that difficult to do an adequate
job of providing the capabilities in a portable way. All the crap about esoteric
architectures is irrelevant.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Mon, 2 Dec 2002 19:12:53 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> kuyper@wizard.net ("James Kuyper Jr.") writes:
>
> | The right approach is to adopt an approach similar to the one used by
> | C99. It provides isnan(), isfinite(), isnormal(), and nan()
> | functions.
>
> Agreed in principle. But, I would like to see C++ use the abstractions
> there to implement a superior model, i.e. LIA.
Yes!
We should adopt the most robust and comprehensive model possible. The C99
solution is a start, but it is incomplete.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Mon, 2 Dec 2002 19:13:00 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> witless@attbi.com (Witless) writes:
>
> | We don't need one size (standard) fits all.
>
> This is precisely one of the reasons why I'm not a fan of IEEE-754
> and C99 legislation. Especially when there are better alternatives.
The superiority of the alternatieves is a red herring. It distracts from the
fundamental issue which is the ability to represent extended floating point
attributes in a portable way. The standard should not be choosing a single
best answer. It should simply provide a mechanism to portably express the
properties of what ever system the platform offers.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 2 Dec 2002 19:26:44 +0000 (UTC) Raw View
witless@attbi.com (Witless) writes:
| Gabriel Dos Reis wrote:
|
| > witless@attbi.com (Witless) writes:
| >
| > | We don't need one size (standard) fits all.
| >
| > This is precisely one of the reasons why I'm not a fan of IEEE-754
| > and C99 legislation. Especially when there are better alternatives.
|
| The superiority of the alternatieves is a red herring.
Saying it is red herring does not make it so.
| attributes in a portable way. The standard should not be choosing a single
| best answer.
LIA is a *not* a single answer: it is a _framework_.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Mon, 2 Dec 2002 20:33:32 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> witless@attbi.com (Witless) writes:
>
> | Gabriel Dos Reis wrote:
> |
> | > witless@attbi.com (Witless) writes:
> | >
> | > | We don't need one size (standard) fits all.
> | >
> | > This is precisely one of the reasons why I'm not a fan of IEEE-754
> | > and C99 legislation. Especially when there are better alternatives.
> |
> | The superiority of the alternatieves is a red herring.
>
> Saying it is red herring does not make it so.
>
> | attributes in a portable way. The standard should not be choosing a single
> | best answer.
>
> LIA is a *not* a single answer: it is a _framework_.
I'll have to look at it again. Last time I looked they were adopting ideas like
defining the result of tan2(inf,inf) as 1.0 in order to preserve the identity
tan2(x,x) == 1.0, which is ridiculous. Hopefully things have improved since
then.
But I maintain that it is still irrelevant. The issue is whether extended
floating point properties can be expressed both abstractly and portably. You
appeared to be arguing that this was (i) not possible or very difficult, (ii) not
worth doing since a single standard is superior to a variety of diverse
standards, or (iii) both.
Can you clarify the position you have taken on the issue of abstract, portable
expressions of extended floating point properties?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 2 Dec 2002 22:58:48 +0000 (UTC) Raw View
witless@attbi.com (Witless) writes:
| I'll have to look at it again. Last time I looked they were adopting ideas like
| defining the result of tan2(inf,inf) as 1.0 in order to preserve the identity
| tan2(x,x) == 1.0, which is ridiculous.
LIA-2 defines no function named tan2().
LIA-1 makes it very unambiguous:
A.5.2.0.4 Infinity and NaNs
[...] Therefore, LIA-1 makes no provision for infinity or NaNs. The
behavior of operations with infinity or a NaN asinput is not defined
by LIA-1.
However, because LIA-1 does not exclude IEEE-{7, 8}54, LIA-2 has the
following disposition:
The following symbols represent floating point values defined in IEC
60559 and used in this Part:
-0, +inf, -inf, qNaN, and sNsN.
These floating point values are not part of the set F, but if
iec_559_F is true, then these values are included in the floating
point datatype corresponding to F.
But places where LIA-2 defines results with both input being inf, are
usually following by editorial comments :-/
| But I maintain that it is still irrelevant. The issue is whether extended
| floating point properties can be expressed both abstractly and portably. You
| appeared to be arguing that this was (i) not possible or very difficult, (ii) not
| worth doing since a single standard is superior to a variety of diverse
| standards, or (iii) both.
None of the above.
| Can you clarify the position you have taken on the issue of
| abstract, portable expressions of extended floating point properties?
Quite simple. I strive for portable ways to handle floating point
data types (I cited LIA-1 as an example of sucn an abstract and
portable expression). But I do not see any value in legislating about
the bit patterns of floating point object representation.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 4 Dec 2002 04:01:21 +0000 (UTC) Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote
> I strive for portable ways to handle floating point
> data types (I cited LIA-1 as an example of sucn an abstract and
> portable expression). But I do not see any value in legislating about
> the bit patterns of floating point object representation.
I would like to have one floating-point type where the bit values are
mandated. It doesn't have to be the "native" floating-point type, nor
does the implementation have to be particularly efficient -- perhaps
just a library class that stores floating-point values with a specific
layout.
My goal isn't to mandate any particular implementation of floating-point
values internally. I just want a way to write floating-point data in
non-printable format into a file that can be processed on some other
system -- even if we have to require that the other system is also
running C++.
struct ExternalFloat {
explicit ExternalFloat(double d);
double to_double();
float to_float();
private:
// ...
};
Usage:
void Customer::write(FILE*outfile) const {
ExternalFloat ext[3];
const int size = sizeof(ext) / sizeof(ext[0]);
ext[0] = balance;
ext[1] = cred_limit;
ext[2] = last_pay_amt;
fwrite(&ext, sizeof(ext), size, outfile);
fwrite... (other stuff) ...
}
void Customer::read(FILE*infile) {
ExternalFloat ext[3];
if (size > fread(&ext, sizeof(ext), size, infile)) {
... handle error ...
}
balance = ext[0];
cred_limit = ext[1];
last_pay_amt = ext[2];
fread... (other stuff) ...
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Wed, 4 Dec 2002 16:51:50 +0000 (UTC) Raw View
allan_w@my-dejanews.com (Allan W) writes:
| gdr@integrable-solutions.net (Gabriel Dos Reis) wrote
| > I strive for portable ways to handle floating point
| > data types (I cited LIA-1 as an example of sucn an abstract and
| > portable expression). But I do not see any value in legislating about
| > the bit patterns of floating point object representation.
|
| I would like to have one floating-point type where the bit values are
| mandated. It doesn't have to be the "native" floating-point type, nor
| does the implementation have to be particularly efficient -- perhaps
| just a library class that stores floating-point values with a specific
| layout.
|
| My goal isn't to mandate any particular implementation of floating-point
| values internally. I just want a way to write floating-point data in
| non-printable format into a file that can be processed on some other
| system -- even if we have to require that the other system is also
| running C++.
I can understand the needs for such library. I bet such needs aren't
just limited to floating-point datatypes.
--
Gabriel Dos Reis, gdr@integrable-soolutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Tue, 26 Nov 2002 18:32:09 +0000 (UTC) Raw View
On Tue, 26 Nov 2002 17:52:48 +0000 (UTC), witless@attbi.com (Witless) wrote:
>"Alf P. Steinbach" wrote:
>
>> On Fri, 22 Nov 2002 00:06:28 +0000 (UTC), andersjm@inbound.dk ("Anders J. Munch") wrote:
>> >...
>> >With this in mind, can you give me a practical example of how
>> >(NaN!=NaN)==(NaN==NaN)==false will save the day for the unwary
>> >...
>>
>> Is not the situation for quiet NaNs that, contrary to the above,
>> according to the IEEE standard (NaN!=NaN) === true?
>>
>> At least it is so with MSVC 7.0.
>
>No it isn't. MSVC does not perform the additional test to handle incomparable values
>correctly. They aren't even trying to use the hardware correctly.
Could you please elaborate on what you mean?
I've failed to make MSVC 7.0 produce the incorrect result (NaN!=NaN)===false.
Perhaps you could show some code that does that?
Cheers,
- Alf
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Wed, 27 Nov 2002 16:46:47 +0000 (UTC) Raw View
Witless wrote:
> Gabriel Dos Reis wrote:
>
>
>>kuyper@wizard.net ("James Kuyper Jr.") writes:
>>
>>| Witless wrote:
>>| > Gabriel Dos Reis wrote:
....
>>| >>| That is what casting to unsigned char is for.
>>| >>
>>| >>which does not solve any problem, since there is no portable way
to use it.
>>| > Yet.
>>| > Are you claiming that there cannot ever be a portable way to use it?
>>|
>>| Not as long as the C++ declines to define the actual layout used for
>>| NaNs, including which order the bits are assigned to individual
>>| bytes.
>>
>>Indeed. And I can't see any benefit of such a legislation.
>
>
> Neither can I. But I doubt it it necessary. Why does portability
require a single
> layout of the bits? Couldn't multiple machines layout the bits
differently and
> still be abstractly defined?
This was in response to the comment about "casting to unsigned char". In
that context, portability does indeed require a single bit layout.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Wed, 27 Nov 2002 17:48:48 +0000 (UTC) Raw View
Witless <witless@attbi.com> writes:
[...]
| > | > Are you claiming that there cannot ever be a portable way to use it?
| > |
| > | Not as long as the C++ declines to define the actual layout used for
| > | NaNs, including which order the bits are assigned to individual
| > | bytes.
| >
| > Indeed. And I can't see any benefit of such a legislation.
|
| Neither can I. But I doubt it it necessary. Why does portability require a single
| layout of the bits? Couldn't multiple machines layout the bits differently and
| still be abstractly defined?
Certainly. That is the point of having the bindings for appropriate
standards (LIA, IEEE-754, ...).
[...]
| > C99 tries to legislate about negative zero (following IEEE-754) and
| > messes up. Let's learn about it :-)
|
| Learn what?
http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_218.htm
| That we need +und, zero, and -und instead of +zero and -zero?
What is "und"?
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Thu, 28 Nov 2002 03:08:37 +0000 (UTC) Raw View
"James Kuyper Jr." wrote:
> Witless wrote:
> > Gabriel Dos Reis wrote:
> >
> >
> >>kuyper@wizard.net ("James Kuyper Jr.") writes:
> >>
> >>| Witless wrote:
> >>| > Gabriel Dos Reis wrote:
> ....
> >>| >>| That is what casting to unsigned char is for.
> >>| >>
> >>| >>which does not solve any problem, since there is no portable way
> to use it.
> >>| > Yet.
> >>| > Are you claiming that there cannot ever be a portable way to use it?
> >>|
> >>| Not as long as the C++ declines to define the actual layout used for
> >>| NaNs, including which order the bits are assigned to individual
> >>| bytes.
> >>
> >>Indeed. And I can't see any benefit of such a legislation.
> >
> >
> > Neither can I. But I doubt it it necessary. Why does portability
> require a single
> > layout of the bits? Couldn't multiple machines layout the bits
> differently and
> > still be abstractly defined?
>
> This was in response to the comment about "casting to unsigned char". In
> that context, portability does indeed require a single bit layout.
Why?
The only necessary assumption appears to be that casting to an array of
unsigned character renders all the interesting bits accessible. Given that
assumption and the fact that we can number the bits within the uchar array, it
is possible to express the layout of an object in purely abstract terms
consisting of offset/length/direction tuples expressed as numbers of bits.
This would be a natural extension of <float.h>, although not a trivial one.
What makes this impossible or unacceptable?
As a related note, if zero-length bit fields were allowed it would be very easy
to provide a portable set of alternative access functions for floating point
objects. Please consider this statement a plea to regularize bitfield
limitations.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Mon, 25 Nov 2002 19:21:36 +0000 (UTC) Raw View
Alf P. Steinbach wrote:
> Is not the situation for quiet NaNs that, contrary to the above,
> according to the IEEE standard (NaN!=NaN) === true?
Yes, (NaN != NaN) returns true. Here's one reference, for example:
<http://msdn.microsoft.com/library/en-us/vjref98/html/15_20_1.asp>.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: news@evo6.com (Andy Sawyer)
Date: Tue, 26 Nov 2002 00:36:08 +0000 (UTC) Raw View
In article <1037995145.133953@master.nyc.kbcfp.com>,
on Mon, 25 Nov 2002 12:10:41 CST,
Hyman Rosen <hyrosen@mail.com> wrote:
> I notice that no one has answered my very simple question.
> Would one of the decimal arithmetic advocates demonstrate
> its advantages in computing that employee's pay schedule?
> ($100,000 per annum, in weekly payments.)
2000 bucks a week, and 2 weeks unpaid leave... :-)
(I'm not a "decimal arithmetic advocate" - at least, I don't think I
am. Since that's your description, I'll leave it up to you to decide.)
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Tue, 26 Nov 2002 03:51:36 +0000 (UTC) Raw View
"Ian McCulloch" <ianmcc@lorentz.leidenuniv.nl> wrote:
> I cannot think of such an example where (NaN!=NaN)==(NaN==NaN)==false
> will be useful. Fortunately, (NaN!=NaN) is true in IEEE754 so its not
> a situation that I've ever had to deal with.
D'oh! I got NaN and SQL NULL semantics mixed up. Sorry about that.
NaN!=NaN it is, then: Examples where that may help the unwary
programmer wanted.
>
> My apologies but I cannot find your example on 'Detecting a
> configuration change'; the only example I can find in this thread is
> std::map<float, T>, and a google search for 'configuration' reports
> the second-most recent use as 26th October.
I can't find it either, so perhaps I never got around to writing it
down and posting it :-/ Quickly recreated, though:
for(;;)
{
x = read_parameter_from_configuration_file();
if(x != last_x)
send_notification_email(
"Hi! Someone changed parameter x -- just thought you'd like to
know");
last_x = x;
process_step();
}
Imagine your mailbox size if somehow a NaN gets read from the
configuration file.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Tue, 26 Nov 2002 03:52:02 +0000 (UTC) Raw View
Hyman Rosen wrote:
> Ken Shaw wrote:
>
>> Making 10 dimes add up to a dollar can be quite important and when
>> bankers
>> find out that floating point math guarantees that that won't be true they
>> get very nervous. Banks are required to keep accurate accounts based
>> on base
>> 10 math not base 2. The differences between the 2 bases introduce
>> significant errors into almost any financial calculation.
>
>
> No, they introduce *insignificant* errors. Ten dimes will add
Accountants get to define what counts as significant for their purposes,
and they've found that there's a lot of diagnostic benefit in treating a
discrepancy of even a single penny as significant, even though the penny
itself isn't very important.
> up to a dollar once you round the result to the nearest penny.
> As I said, you need to know what you're doing before you can
> do it correctly.
Yes, that might work. Or, in the more general case, it might not.
Consider, for instance, calculating 10 different quantities as specified
percentages of a specified total. The specified percentages add up to
precisely 100%. The individual amounts won't, in general, add up to that
total if you round them to the nearest penny. And the individual amounts
won't, in general, be correct if you adjust them to make their total
match the pre-specified amount.
Decimal arithmetic, (or integer arithmetic on amounts in pennies) won't
get you out of this problem, but it does make it easier to control it.
You'll have a well-controlled last decimal place, which you don't when
using binary floating point arithmetic.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Tue, 26 Nov 2002 15:33:24 +0000 (UTC) Raw View
witless@attbi.com (Witless) writes:
| Gabriel Dos Reis wrote:
|
| > witless@attbi.com (Witless) writes:
| >
| > | > choose to ignore them in comparisons, and you will have lost nothing
| > | > compared to IEEE semantics. However, if they _are_ used, then you
| > | > would probably want to be able to compare them, to answer questions
| > | > such as "has a diagnostic message been emitted for this error bit
| > | > pattern yet?".
| > |
| > | That is what casting to unsigned char is for.
| >
| > which does not solve any problem, since there is no portable way to use it.
|
| Yet.
|
| Are you claiming that there cannot ever be a portable way to use it?
As long as the language eludes the issue.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Tue, 26 Nov 2002 15:33:50 +0000 (UTC) Raw View
kuyper@wizard.net ("James Kuyper Jr.") writes:
| Witless wrote:
| > Gabriel Dos Reis wrote:
| >
| >>witless@attbi.com (Witless) writes:
| >>
| >>| > choose to ignore them in comparisons, and you will have lost nothing
| >>| > compared to IEEE semantics. However, if they _are_ used, then you
| >>| > would probably want to be able to compare them, to answer questions
| >>| > such as "has a diagnostic message been emitted for this error bit
| >>| > pattern yet?".
| >>|
| >>| That is what casting to unsigned char is for.
| >>
| >>which does not solve any problem, since there is no portable way to use it.
| > Yet.
| > Are you claiming that there cannot ever be a portable way to use it?
|
| Not as long as the C++ declines to define the actual layout used for
| NaNs, including which order the bits are assigned to individual
| bytes.
Indeed. And I can't see any benefit of such a legislation.
Some plateforms, although providing some support for IEEE-754 floating
points, just get the bit pattern *wrong*. Which means, you can't just
use bit pattern comparaison to decide _portably_ whether something is
a QNaN or a SNaN.
And, there are alternative, useful, well-defined, floating-point
models beside IEEE-754 ones. I would rather see C++ adopt a more
general useful framework like LIA. Some plateforms don't have the
abominable notion of negative zero, yet they are useful for
computations with floating-points.
C99 tries to legislate about negative zero (following IEEE-754) and
messes up. Let's learn about it :-)
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Tue, 26 Nov 2002 15:34:56 +0000 (UTC) Raw View
witless@attbi.com (Witless) writes:
| Gabriel Dos Reis wrote:
|
| > witless@attbi.com (Witless) writes:
| >
| > | > "rarely used" doesn't mean "never used" and "political reasons" is *his*
| > | > ways of describing a situation where there were no unanimity not to
| > | > have them. And also, please, do bear in mind that IEEE-754 was designed
| > | > ages ago with the technology of the time.
| > |
| > | Not quite. The spec was considerably in advance of what was
| > | considered current when it was published.
| >
| > Untrue; at the time there were proof of concepts
|
| Not publicly.
While the technology wasn't in the hand of everyday user, it still was
avalaible to manufacturers in the sense of scientific knowledge.
| In context (NaNs), your original statement is approximately
| correct. However, your statement covered all of the standard, not just NaN usage.
| In that larger context your statement is false (completely if you are feeling
| fuzzy).
I'm primarily concerned about the invention of:
1) NaNs and the relational operators perversion,
2) negative zero, with accompanying complications
| Many of the manufacturers, notably DEC, took prestige hits when they claimed things
| were impossible that turned out to me not so hard. NaN handling was one of them.
Indeed. And, ironically, they even hired people to conduct
assessments, which just denied their claims.
| By "the technology of the time" you might have been referring to the bleeding edge
| of technology or the current "state of the art".
But they were designing a _long term_ standard!
[...]
| > The NaNs invention wasn't
| > in advance on the tehchnology available at the time.
|
| As described above, that depends upon your definition of "the technology available
| at the time". Available in the sense of a scientific advance is quite a bit ahead
| of what is considered available in the engineering sense.
Well, maybe my background is showing up ;-). Yes, I'm using the
"scientific advance" meaning.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Tue, 26 Nov 2002 15:34:58 +0000 (UTC) Raw View
alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach) writes:
| Is not the situation for quiet NaNs that, contrary to the above,
| according to the IEEE standard (NaN!=NaN) === true?
NaN != NaN is true.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Tue, 26 Nov 2002 15:45:38 +0000 (UTC) Raw View
kuyper@wizard.net ("James Kuyper Jr.") writes:
| Witless wrote:
| > Gabriel Dos Reis wrote:
| >
| >>witless@attbi.com (Witless) writes:
| >>
| >>| > choose to ignore them in comparisons, and you will have lost nothing
| >>| > compared to IEEE semantics. However, if they _are_ used, then you
| >>| > would probably want to be able to compare them, to answer questions
| >>| > such as "has a diagnostic message been emitted for this error bit
| >>| > pattern yet?".
| >>|
| >>| That is what casting to unsigned char is for.
| >>
| >>which does not solve any problem, since there is no portable way to use it.
| > Yet.
| > Are you claiming that there cannot ever be a portable way to use it?
|
| Not as long as the C++ declines to define the actual layout used for
| NaNs, including which order the bits are assigned to individual
| bytes.
Indeed. And I can't see any benefit of such a legislation.
Some plateforms, although providing some support for IEEE-754 floating
points, just get the bit pattern *wrong*. Which means, you can't just
use bit pattern comparaison to decide _portably_ whether something is
a QNaN or a SNaN.
And, there are alternative, useful, well-defined, floating-point
models beside IEEE-754 ones. I would rather see C++ adopt a more
general useful framework like LIA. Some plateforms don't have the
abominable notion of negative zero, yet they are useful for
computations with floating-points.
C99 tries to legislate about negative zero (following IEEE-754) and
messes up. Let's learn from it :-)
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 26 Nov 2002 15:47:34 +0000 (UTC) Raw View
James Kuyper Jr. wrote:
> You'll have a well-controlled last decimal place, which you don't when
> using binary floating point arithmetic.
Do you have an example? I don't understand why you think
binary floating point gives you a not well-controlled
last decimal place, or what that even means.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Witless <witless@attbi.com>
Date: Tue, 26 Nov 2002 10:09:47 CST Raw View
Gabriel Dos Reis wrote:
> kuyper@wizard.net ("James Kuyper Jr.") writes:
>
> | Witless wrote:
> | > Gabriel Dos Reis wrote:
> | >
> | >>witless@attbi.com (Witless) writes:
> | >>
> | >>| > choose to ignore them in comparisons, and you will have lost nothing
> | >>| > compared to IEEE semantics. However, if they _are_ used, then you
> | >>| > would probably want to be able to compare them, to answer questions
> | >>| > such as "has a diagnostic message been emitted for this error bit
> | >>| > pattern yet?".
> | >>|
> | >>| That is what casting to unsigned char is for.
> | >>
> | >>which does not solve any problem, since there is no portable way to use it.
> | > Yet.
> | > Are you claiming that there cannot ever be a portable way to use it?
> |
> | Not as long as the C++ declines to define the actual layout used for
> | NaNs, including which order the bits are assigned to individual
> | bytes.
>
> Indeed. And I can't see any benefit of such a legislation.
Neither can I. But I doubt it it necessary. Why does portability require a single
layout of the bits? Couldn't multiple machines layout the bits differently and
still be abstractly defined?
[snip]
> And, there are alternative, useful, well-defined, floating-point
> models beside IEEE-754 ones. I would rather see C++ adopt a more
> general useful framework like LIA. Some plateforms don't have the
> abominable notion of negative zero, yet they are useful for
> computations with floating-points.
>
> C99 tries to legislate about negative zero (following IEEE-754) and
> messes up. Let's learn about it :-)
Learn what? That we need +und, zero, and -und instead of +zero and -zero? Redoing
the floating point standards "the right way" is a much larger task than defining
access mechanisms for the properties of a floating point object.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Tue, 26 Nov 2002 17:52:48 +0000 (UTC) Raw View
"Alf P. Steinbach" wrote:
> On Fri, 22 Nov 2002 00:06:28 +0000 (UTC), andersjm@inbound.dk ("Anders J. Munch") wrote:
> >...
> >With this in mind, can you give me a practical example of how
> >(NaN!=NaN)==(NaN==NaN)==false will save the day for the unwary
> >...
>
> Is not the situation for quiet NaNs that, contrary to the above,
> according to the IEEE standard (NaN!=NaN) === true?
>
> At least it is so with MSVC 7.0.
No it isn't. MSVC does not perform the additional test to handle incomparable values
correctly. They aren't even trying to use the hardware correctly.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Ken Shaw" <ken@DIESPAMDIEcompinnovations.com>
Date: Fri, 22 Nov 2002 12:27:29 CST Raw View
"Hyman Rosen" <hyrosen@mail.com> wrote in message
news:1037907815.404331@master.nyc.kbcfp.com...
> Ken Shaw wrote:
> > That is exactly what I've done for some financial applications. Bankers
> > don't like rounding schemes they can't control and most have been pretty
> > dubious of using any floating point numbers once they were made aware of
the
> > true lack of precision of floats and doubles.
> >
> > What C++ needs is an arbitrary precision real number type that is base
10
> > not base 2 with a trait based rounding model. Float and double should
really
> > only be used in scientific and graphics programming.
>
> This is a complete fallacy, unless your financial applications don't deal
> with things even as simple as interest rates. In my company, the financial
> applications solve differential equations to model values of securities. I
> don't think they want to use decimal arithmetic.
>
> Or here's an even simpler problem. An employee gets a salary of $100,000
> a year. Employees are paid weekly. Compute the gross pay for each of the
> employee's paychecks.
>
> Making the pennies add up may be a reasonable goal, and even a legal
> requirement, but making them do so requires an understanding of the
> problem, not a different base of arithmetic.
>
Making 10 dimes add up to a dollar can be quite important and when bankers
find out that floating point math guarantees that that won't be true they
get very nervous. Banks are required to keep accurate accounts based on base
10 math not base 2. The differences between the 2 bases introduce
significant errors into almost any financial calculation.
Ken Shaw
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 22 Nov 2002 19:26:41 +0000 (UTC) Raw View
witless@attbi.com (Witless) writes:
| > choose to ignore them in comparisons, and you will have lost nothing
| > compared to IEEE semantics. However, if they _are_ used, then you
| > would probably want to be able to compare them, to answer questions
| > such as "has a diagnostic message been emitted for this error bit
| > pattern yet?".
|
| That is what casting to unsigned char is for.
which does not solve any problem, since there is no portable way to
use it.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ianmcc@lorentz.leidenuniv.nl (Ian McCulloch)
Date: Fri, 22 Nov 2002 19:26:52 +0000 (UTC) Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message news:<m3d6oy4vby.fsf@uniton.integrable-solutions.net>...
> ianmcc@lorentz.leidenuniv.nl (Ian McCulloch) writes:
>
> | hyrosen@mail.com (Hyman Rosen) wrote in message news:<4YYC9.35574$aB1.28934@nwrddc02.gnilink.net>...
> | > Allan W wrote:
> | > > hyrosen@mail.com (Hyman Rosen) wrote
> | > >
> | > >>And how many times have you
> | > >>seen people define "close equality" using
> | > >> bool equals(a, b) { return abs(a - b) < epsilon; }
> | > >>which can result in equals(a, b) == true, equals(b, c) == true,
> | > >>but equals(a, c) == false?
> | > >
> | > > What's the alternative?
> |
> | bool equals(a, b) { return abs(a-b) < epsilon * abs(a+b); }
> |
> | This is scale-invariant.
>
> It is not.
>
> 1) intermediate results may (over|under)flow
> 2) fails for a = b = 0
Sorry, I cut & pasted too much, it should of course be <=, not <.
Fixing all the underflow problems is a bit harder, I guess you can do
a comparison to see if underflow is going to occur and, in that case,
divide the left hand side by epsilon instead of multiplying on the
right.
I should have qualified my statement: it is scale-invariant for _most_
floating point values ;-)
>
> [...]
>
> | Some people put max(abs(a), abs(b)) on the right hand side, but I
> | figure if you need to fine-tune epsilon to within a factor 2 then
> | you're probably in trouble anyway.
>
> Did you try it? If you adhere to the general IEEE-754 floating-point
> model you might get surprise with your proposed solution.
>
> | Floating point arithmetic is non-associative, and inexact, why is
> | exact transitivity of equals such an important criteria?
>
> The issue, at least, a I raised it is about the pervertion of
> operations on boolean expressions.
This issue is certainly raised in other posts on this thread, the one
I replied to was specifically about how to define 'equals' for
floating point values.
Cheers,
Ian McCulloch
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ianmcc@lorentz.leidenuniv.nl (Ian McCulloch)
Date: Fri, 22 Nov 2002 19:27:31 +0000 (UTC) Raw View
andersjm@inbound.dk ("Anders J. Munch") wrote in message news:<009601c291ba$3b466950$a24536d4@maxine>...
> "Ian McCulloch" wrote in
> news:bac6d750.0211210826.623d5070@posting.google.com:
> >
> > In some statistical programs NaNs are used to represent missing input
> > data and they simply propogate through to be NaNs on output.
>
> Very clever. Of course that stops NaNs from being used for their
> intended purpose, because how would you distinguish between NaNs
> caused by missing input and NaNs caused by invalid operations?
If you needed to, you could use some of the extra bits in NaNs which
are reserved for such purposes. The one program where I have seen
this used on large data sets didn't need to do this because it didn't
generate its own NaNs.
>
> >In this
> > case having a NaN throwing an exception actually complicates the code;
> > there may not actually be a sensible place to catch the exception.
>
> Clever hacks are fragile.
Well, I wouldn't deny that is a misuse of NaNs, but in that particular
application it works fine.
>
> >
> > IEEE NaNs have some unspecified bits which were intended to be used to
> > indicate, for example, how or where the NaN arose. Not much software
> > takes advantage of this though. NaNs can arise from many different
> > sources, eg the correct result could not be obtained, or there is no
> > correct result, or there was a missing data sample etc. I find it
> > hard to see why you would want two of these NaNs to compare equal,
> > unless they arose from the same calculation and represent the same
> > 'unobtainable result'. Without keeping track of this information, the
> > only sensible choice is NaN == NaN is always false.
>
> Do you often write:
> if(! (a != b)) { ... }
> ?
>
> I don't - I simplify to
> if(a == b) { ... }
>
> without giving it a second thought. Which is fully correct so long as
> == and != are each other's negation. I contend that any programmer,
> who is not paying particular attention to the possibility of NaNs,
> will do the same. The choice between:
>
> if(a == b) { foo(); } else { bar(); }
> and if(a != b) { bar(); } else { foo(); }
>
> is usually quite arbitrary: In fact, if either foo() or bar() are
> no-ops, most likely the variant that allows the else clause to be
> elided will be chosen.
>
> With this in mind, can you give me a practical example of how
> (NaN!=NaN)==(NaN==NaN)==false will save the day for the unwary
> programmer, one that doesn't rely on such arbitrary choices? Or even
> one that _does_ rely on an arbitrary choice. Elsewhere I have
> presented an example to the contrary: Detecting a configuration
> change. Your turn.
I cannot think of such an example where (NaN!=NaN)==(NaN==NaN)==false
will be useful. Fortunately, (NaN!=NaN) is true in IEEE754 so its not
a situation that I've ever had to deal with.
My apologies but I cannot find your example on 'Detecting a
configuration change'; the only example I can find in this thread is
std::map<float, T>, and a google search for 'configuration' reports
the second-most recent use as 26th October.
>
> And those unspecified bits? If nothing else then you can always
> choose to ignore them in comparisons, and you will have lost nothing
> compared to IEEE semantics. However, if they _are_ used, then you
> would probably want to be able to compare them, to answer questions
> such as "has a diagnostic message been emitted for this error bit
> pattern yet?".
Yes, IEEE semantics is to ignore the bits in comparisons. If you want
to do something with them you have to do your own bit twiddling.
Can't say I've ever been tempted myself.
Cheers,
Ian McCulloch
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ianmcc@lorentz.leidenuniv.nl (Ian McCulloch)
Date: Fri, 22 Nov 2002 19:29:32 +0000 (UTC) Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
[snip]
> Propogating NAN's makes sense in general. Consider the expression
>
> a + b * (c / (d-e))
>
> If d==e then the division results in NAN. Multiplying it by b and then
> adding a shouldn't change that -- because it's a lot simpler to check the
> final result for validity than to check each sub step.
Minor point, but d==e should produce INF rather than a NaN (unless b
or c are zero as well). This will also propogate through the
calculation, and it might even give the correct answer at the end (but
maybe not!).
Cheers,
Ian McCulloch
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Fri, 22 Nov 2002 21:54:13 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> witless@attbi.com (Witless) writes:
>
> | > choose to ignore them in comparisons, and you will have lost nothing
> | > compared to IEEE semantics. However, if they _are_ used, then you
> | > would probably want to be able to compare them, to answer questions
> | > such as "has a diagnostic message been emitted for this error bit
> | > pattern yet?".
> |
> | That is what casting to unsigned char is for.
>
> which does not solve any problem, since there is no portable way to use it.
Yet.
Are you claiming that there cannot ever be a portable way to use it?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Fri, 22 Nov 2002 22:28:51 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> witless@attbi.com (Witless) writes:
>
> | > "rarely used" doesn't mean "never used" and "political reasons" is *his*
> | > ways of describing a situation where there were no unanimity not to
> | > have them. And also, please, do bear in mind that IEEE-754 was designed
> | > ages ago with the technology of the time.
> |
> | Not quite. The spec was considerably in advance of what was
> | considered current when it was published.
>
> Untrue; at the time there were proof of concepts
Not publicly. In context (NaNs), your original statement is approximately
correct. However, your statement covered all of the standard, not just NaN usage.
In that larger context your statement is false (completely if you are feeling
fuzzy).
Many of the manufacturers, notably DEC, took prestige hits when they claimed things
were impossible that turned out to me not so hard. NaN handling was one of them.
By "the technology of the time" you might have been referring to the bleeding edge
of technology or the current "state of the art". The standard did not reflect the
state of the art at all. It advanced the state of the art considerably.
> -- the "wholy war"
> between the IEEE-754 committee members was partly caused by each one
> (more or less sponsored by manufacturers) having its own
> implementations of what should be The Truth.
Absolutely.
> The NaNs invention wasn't
> in advance on the tehchnology available at the time.
As described above, that depends upon your definition of "the technology available
at the time". Available in the sense of a scientific advance is quite a bit ahead
of what is considered available in the engineering sense. And both are leagues
ahead of what is available, meaning viable, in a business sense. Thus the
existence of the standard had little effect on the advance of the science, a
significant effect on the attitude of engineers, and a dramatic effect on the
business interests of the companies involved -- which is exactly why they resisted
advanced that would obsolete their investments. Had their technology been superior
to that of the standard, we might still be using it. (Yes, I know, some of us
are).
>
>
> | > Technologies have evolved
> | > and it is far from clear that solutions deigned for a set of
> | > assumptions years ago are still relevant (with *no change*) for
> | > devices and technologies avaliable today.
> |
> | Yes, it is far from clear. We still have not managed to get the
> | spec widely implemented correctly.
>
> Because the spec does miss important points (even though it was a
> progress in some sense). That is of the reasons why the LIA standards
> are aiming at rebalacing the matter.
LIA has a lot more issues to wrestle with than the defects in the IEEE standards.
The languages themselves contain implicit (bad) assumptions that restrict the
availability of good answers.
>
>
> | As for problems with the
> | standard, only the confusion of inf==ovr and lack of a true zero are serious.
>
> The abominable concepts of NaNs with the relational operators
> pervertion certainly constitute major parts to the confusion. Wit
> this discussion for example, and existing (albeit deplorable)
> implementations in compilers.
Yes, and I expect this debate to continue. The cost of revisiting all FP code in
order to eliminate the possibility of relationals applied to NaNs is, shall we say,
large. Since the "right" answer is unavailable, what other (wrong) answer would
you find acceptable?
>
> | > | That is, the whole point of NaNs is that they propogate through the
> | > | calculation until such a point that it is convenient to check for
> | > | them. Certainly, this pre-dates C++ exceptions, but then floating
> | > | point operations are often asynchronous anyway so it is problematic to
> | > | map them directly onto C++ exeptions at the point of occurance.
> | >
> | > I don't think there are more problematic than setting a floating-point
> | > status flag or throwing exceptions from threads.
> |
> | Yes it is. Much. If you want any kind of error handling other than
> | abort() you have to be able to untangle the heavily
> | pipelined FPU operations and synchronize them with the (typically
> | scalar) test-and-branch operation(s).
>
> But the same is true for a multithreaded program.
I think not. I've done multi-threaded FP-intensive development. Task switching
involves saving and restoring the state of the machine, which is a fairly simple
operation. More important than simplicity is the fact that the correctness of the
save/load operation can be verified fairly easily.
Adding branching within the FP pipeline complicates it tremendously. Given the
order independence of the sub-operations, how would you test to determine that
you've done it correctly? Would you like to see an entire matrix inversion handled
as a form of speculative execution (i.e., flushed if a NaN appears in the input or
intermediate values?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Mon, 25 Nov 2002 17:25:55 +0000 (UTC) Raw View
On Fri, 22 Nov 2002 00:06:28 +0000 (UTC), andersjm@inbound.dk ("Anders J. Munch") wrote:
>...
>With this in mind, can you give me a practical example of how
>(NaN!=NaN)==(NaN==NaN)==false will save the day for the unwary
>...
Is not the situation for quiet NaNs that, contrary to the above,
according to the IEEE standard (NaN!=NaN) === true?
At least it is so with MSVC 7.0. The other compiler I have on this
machine, g++ 3.2, doesn't support IEEE (IEC) floating point. But it's
also that way in all refs I found about this via a Google search.
I've asked that question a number of times now, but still haven't
got a satisfying answer. Although one person tried, the discussion
has then just sidestepped into the land of SNaNs. So it almost seems
as if it's a kind of misconception wilfully left to "propagate"...
- Alf
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Hyman Rosen <hyrosen@mail.com>
Date: Mon, 25 Nov 2002 12:10:41 CST Raw View
Ken Shaw wrote:
> Making 10 dimes add up to a dollar can be quite important and when bankers
> find out that floating point math guarantees that that won't be true they
> get very nervous. Banks are required to keep accurate accounts based on base
> 10 math not base 2. The differences between the 2 bases introduce
> significant errors into almost any financial calculation.
No, they introduce *insignificant* errors. Ten dimes will add
up to a dollar once you round the result to the nearest penny.
As I said, you need to know what you're doing before you can
do it correctly.
I notice that no one has answered my very simple question.
Would one of the decimal arithmetic advocates demonstrate
its advantages in computing that employee's pay schedule?
($100,000 per annum, in weekly payments.)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 25 Nov 2002 18:37:57 +0000 (UTC) Raw View
Witless wrote:
> Gabriel Dos Reis wrote:
>
>
>>witless@attbi.com (Witless) writes:
>>
>>| > choose to ignore them in comparisons, and you will have lost nothing
>>| > compared to IEEE semantics. However, if they _are_ used, then you
>>| > would probably want to be able to compare them, to answer questions
>>| > such as "has a diagnostic message been emitted for this error bit
>>| > pattern yet?".
>>|
>>| That is what casting to unsigned char is for.
>>
>>which does not solve any problem, since there is no portable way to use it.
>
>
> Yet.
>
> Are you claiming that there cannot ever be a portable way to use it?
Not as long as the C++ declines to define the actual layout used for
NaNs, including which order the bits are assigned to individual bytes.
It would be contrary to the traditions of C++ to be that specific, for
it would preclude efficient implementation on systems where the native
floating point format doesn't match the specification.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 21 Nov 2002 02:16:10 +0000 (UTC) Raw View
> "John Nagle" <nagle@animats.com> wrote:
> > Those aren't always meaningful comparisons.
> >
> > The idea behind IEEE floating point comparisons is
> > that some operations are invalid; you can't do them at all.
> > Comparisons are three-valued, with the possible results being
> > "true", "false", and "invalid". For example,
> > "INF+ > INF+" is "invalid". All comparisons with NaNs
> > are also "invalid".
andersjm@dancontrol.dk ("Anders J. Munch") wrote
> Ok, the right thing to do when encountering a NaN is to throw an
> exception. But then, if you don't throw an exception, returning false
> is every bit as wrong as returning true. There is no good reason for
> NaN==NaN to return false[1], but there is a good reason to return
> true: the integrity of the equivalence relation.
>
> INFs are ordered in IEEE, hence "INF+ > INF+" is not "invalid", it is
> just plain old false. AFAIK.
Maybe we need three-valued booleans? NAN==NAN returns NAB (Not a Boolean)?
Propogating NAN's makes sense in general. Consider the expression
a + b * (c / (d-e))
If d==e then the division results in NAN. Multiplying it by b and then
adding a shouldn't change that -- because it's a lot simpler to check the
final result for validity than to check each sub step.
T x = d-e;
if (isNAN(x)) goto error;
x = c / x;
if (isNAN(x)) goto error;
x *= b; // x*b == b*x
if (isNAN(x)) goto error;
x += a; // a+x == x+a
if (isNAN(x)) {
error:
/* Handle error */
} else {
/* Success */
}
Much bigger pain than
T x = a + b * (c / (d-e));
if (isNAN(x)) {
/* Handle error */
} else {
/* Success */
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 21 Nov 2002 02:16:13 +0000 (UTC) Raw View
hyrosen@mail.com (Hyman Rosen) wrote
> It's no more perverted than the fact that ordinary < and >
> don't apply to complex numbers. And how many times have you
> seen people define "close equality" using
> bool equals(a, b) { return abs(a - b) < epsilon; }
> which can result in equals(a, b) == true, equals(b, c) == true,
> but equals(a, c) == false?
What's the alternative?
I suppose you could use
bool equals(double a, double b) { return
long(a*factor)==long(b*factor); }
where factor gives you enough digits after the decimal point (say 1000
for 3 digits).
Unfortunately, the maximum value of double exceeds the maximum value
of long, on most systems (probably all, due to the very nature of
floating-point calculations). Perhaps what you really want is: "Same
magnatude, and first 3 digits equal". But this doesn't work well
either -- 1.234 * 2.0 might not equal 2.468 because of rounding.
Ideally, we would model the world to avoid floating point altogether,
or at least to avoid it's problems. In the US, we could count money in
pennies instead of dollars (banks would need millidollars or something
like it) so we would never need a fraction. But there's no getting
around some strange-looking currency conversion rates -- so you're
still going to have to deal with it somehow.
I think the easiest thing to do is to write your application so that
if equals(a,b) && equals(b,c) doesn't imply equals(a,c), that nobody
will be harmed by it. (Note I said "easiest" -- not "easy." Think of
climbing a tall mountain being easier than moving the mountain.)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 21 Nov 2002 04:25:59 +0000 (UTC) Raw View
Allan W wrote:
> hyrosen@mail.com (Hyman Rosen) wrote
>
>>And how many times have you
>>seen people define "close equality" using
>> bool equals(a, b) { return abs(a - b) < epsilon; }
>>which can result in equals(a, b) == true, equals(b, c) == true,
>>but equals(a, c) == false?
>
> What's the alternative?
You divide the real number line into a set of disjoint intervals,
and define equals(a, b) to be true if and only if a and b fall
into the same interval. This should be easy to do by truncating
some number of trailing mantissa bits to zero and then using
ordinary equality. In fact, plain floating point numbers *already*
do this, since a machine number actually represents the interval
around it (the set of reals closer to that number than any other).
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Thu, 21 Nov 2002 17:07:33 +0000 (UTC) Raw View
On Thu, 21 Nov 2002 04:25:59 +0000 (UTC), Hyman Rosen zcribbled:
>Allan W wrote:
>> hyrosen@mail.com (Hyman Rosen) wrote
>>
>>>And how many times have you
>>>seen people define "close equality" using
>>> bool equals(a, b) { return abs(a - b) < epsilon; }
>>>which can result in equals(a, b) == true, equals(b, c) == true,
>>>but equals(a, c) == false?
>>
>> What's the alternative?
>
>You divide the real number line into a set of disjoint intervals,
>and define equals(a, b) to be true if and only if a and b fall
>into the same interval. This should be easy to do by truncating
>some number of trailing mantissa bits to zero and then using
>ordinary equality. In fact, plain floating point numbers *already*
>do this, since a machine number actually represents the interval
>around it (the set of reals closer to that number than any other).
The above iz a *very* important point.
It meance that truncating zome number of trailing mantizza bitz will
end up with the very ZAME problemz that floating point numberz have
(wrt. comparizionz) without thiz added procezzing.
The queztion then iz, to what DEGREE are thoze problemz prezent?
Can thiz difference (if any) be quantified?
Iz the difference large enough to not care about quantification?
For example, if a computation iz zuch that x and y converge, we can
check for difference of lezz than zome number epzilon, or we can remove
trailing bitz and check for equality, which iz pozzibly a more efficient
operation. But the epzilon technique doez not care about direction or
absolute placement of the interval. With truncation one muzt allow for
x and y lying on each zide of an interval divizion, and zo one muzt (I
prezume) remove one more bit than one would want, i.e. not nearezt power
of 2 above epzilon, but twice that.
But then, x and y might ztill lie on each zide of an interval divizion,
and zo one muzt remove one more bit (before comparizion) to be zure.
And zo on.
Obviouzly (?) there iz zome point of diminizhing return on "inveztment"
here, but unfortunately, perhapz a divizion liez exactly at, e.g., ZERO.
Cheerz,
- Alf
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 21 Nov 2002 17:54:12 +0000 (UTC) Raw View
Alf P. Steinbach wrote:
> Obviouzly (?) there iz zome point of diminizhing return on "inveztment"
> here, but unfortunately, perhapz a divizion liez exactly at, e.g., ZERO.
Your 's' key is broken? :-)
Anyway, I already replied to myself that rounding rather than truncation
is preferable, exactly because most of the time you want .999 and 1.001
to be "equal". But giving up the transitivity of equals is a poor idea.
As a strictly practical matter, I can tell you that last year, my wife
spent days tracking down a bug that was caused by exactly this - in a
list of numbers, there were three of which the first two were within
epsilon, as were the second two, but the first and third were not. The
code was implicitly assuming transitivity, and absolute havoc ensued,
with the usual problems of weird effects appearing far from their cause.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Thu, 21 Nov 2002 18:13:16 +0000 (UTC) Raw View
"Allan W" <allan_w@my-dejanews.com> wrote:
> Maybe we need three-valued booleans? NAN==NAN returns NAB (Not a Boolean)?
Ah, but we have three-valued booleans ;-) The three values being true,
false and throw.
>
> Propogating NAN's makes sense in general.
I hope you don't think I've said anything to the contrary.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ianmcc@lorentz.leidenuniv.nl (Ian McCulloch)
Date: Thu, 21 Nov 2002 18:13:23 +0000 (UTC) Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message news:<4YYC9.35574$aB1.28934@nwrddc02.gnilink.net>...
> Allan W wrote:
> > hyrosen@mail.com (Hyman Rosen) wrote
> >
> >>And how many times have you
> >>seen people define "close equality" using
> >> bool equals(a, b) { return abs(a - b) < epsilon; }
> >>which can result in equals(a, b) == true, equals(b, c) == true,
> >>but equals(a, c) == false?
> >
> > What's the alternative?
bool equals(a, b) { return abs(a-b) < epsilon * abs(a+b); }
This is scale-invariant. With the original definition, numbers larger
than 1/epsilon always compare false (unless they really are
identical), and numbers smaller then epsilon always compare true.
Some people put max(abs(a), abs(b)) on the right hand side, but I
figure if you need to fine-tune epsilon to within a factor 2 then
you're probably in trouble anyway.
>
> You divide the real number line into a set of disjoint intervals,
> and define equals(a, b) to be true if and only if a and b fall
> into the same interval. This should be easy to do by truncating
> some number of trailing mantissa bits to zero and then using
> ordinary equality. In fact, plain floating point numbers *already*
> do this, since a machine number actually represents the interval
> around it (the set of reals closer to that number than any other).
NO! A floating point number does not represent an interval. It
represents one and only one number. Floating point arithmetic (IEEE
anyway) works by taking the operands to be exactly represented,
calculating the result *as if* it had infinite precision and then,
only at the end, rounding.
In interval arithmetic, the width of the final interval depends on the
width of the initial invervals. ie, you cannot end up with a number
more precise than what you started with.
If you really want to use intervals you can do it with a structure
that contains the number and (say) the standard deviation,
struct measurement
{
measurement(double x_, double sigma_);
double x, sigma; // sigma is the (positive) standard deviation of
x
};
(I named this "measurement" since that is most likely where such a
number would come from). The usual arithmetic operators can be easily
defined, for example
measurement operator+(measurement a, measurement b)
{
return measurement(a.x + b.x, sqrt(a.sigma * a.sigma + b.sigma *
b.sigma));
}
The equality operator defined above is just a "coarse graining" of the
usual floating point equality, and I suspect for most applications the
problems it inherits are not worth it just to get transitivity. With
the above definition, if equals(a,b) it doesn't follow that
equals(a+c, b+c). This might not be satisfied with the first equals
anyway because of rounding, but the range of possible numbers a,b,c
where that occurs would be tiny. No so with the above definition.
Floating point arithmetic is non-associative, and inexact, why is
exact transitivity of equals such an important criteria?
Cheers,
Ian McCulloch
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 21 Nov 2002 18:13:54 +0000 (UTC) Raw View
Hyman Rosen wrote:
> This should be easy to do by truncating some number of trailing
> mantissa bits to zero and then using ordinary equality.
You would probably want to round instead, now that I think about
it, and that could require some fiddling with the exponents as
well, but the principle is the same - associate each number with
a representative, and then compare those.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ianmcc@lorentz.leidenuniv.nl (Ian McCulloch)
Date: Thu, 21 Nov 2002 18:13:55 +0000 (UTC) Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message news:<m3bs4sf2cs.fsf@uniton.integrable-solutions.net>...
> hyrosen@mail.com (Hyman Rosen) writes:
>
> | Anders J. Munch wrote:
> | > Ok, the right thing to do when encountering a NaN is to throw an
> | > exception.
> |
> | NaNs come in signaling and non-signaling forms, so you get your
> | choice of behavior.
>
> However what does "signaling NaN" means for a *C++* program is still not
> well defined.
A quote from the Man Himself (W. Kahan):
"NaNs do not trap (unless they are "Signaling" SNaNs, which exist
mainly for political reasons and are rarely used); NaNs propagate
through most computations."
That is, the whole point of NaNs is that they propogate through the
calculation until such a point that it is convenient to check for
them. Certainly, this pre-dates C++ exceptions, but then floating
point operations are often asynchronous anyway so it is problematic to
map them directly onto C++ exeptions at the point of occurance.
In some statistical programs NaNs are used to represent missing input
data and they simply propogate through to be NaNs on output. In this
case having a NaN throwing an exception actually complicates the code;
there may not actually be a sensible place to catch the exception.
The rules for NaNs are not arbitrary, but they result from practical
experience in how to sensibly propagate them though a wide variety of
calculations. If the rules for NaNs are not sensible for a given
comparison then the simple answer is detect them and turn it into a
C++ exception before the comparison occurs!
>
> [...]
>
> | > the integrity of the equivalence relation.
> |
> | Is meaningless when the things being compared are garbage.
>
> Then, rather throw something to indicate garbage are being
> manipulated instead of perverting meaning of operations on boolean
> expressions.
IEEE NaNs have some unspecified bits which were intended to be used to
indicate, for example, how or where the NaN arose. Not much software
takes advantage of this though. NaNs can arise from many different
sources, eg the correct result could not be obtained, or there is no
correct result, or there was a missing data sample etc. I find it
hard to see why you would want two of these NaNs to compare equal,
unless they arose from the same calculation and represent the same
'unobtainable result'. Without keeping track of this information, the
only sensible choice is NaN == NaN is always false.
Cheers,
Ian McCulloch
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ken@DIESPAMDIEcompinnovations.com ("Ken Shaw")
Date: Thu, 21 Nov 2002 18:14:01 +0000 (UTC) Raw View
"Allan W" <allan_w@my-dejanews.com> wrote in message
news:7f2735a5.0211201717.1235bb9f@posting.google.com...
> hyrosen@mail.com (Hyman Rosen) wrote
> > It's no more perverted than the fact that ordinary < and >
> > don't apply to complex numbers. And how many times have you
> > seen people define "close equality" using
> > bool equals(a, b) { return abs(a - b) < epsilon; }
> > which can result in equals(a, b) == true, equals(b, c) == true,
> > but equals(a, c) == false?
>
> What's the alternative?
>
> I suppose you could use
> bool equals(double a, double b) { return
> long(a*factor)==long(b*factor); }
> where factor gives you enough digits after the decimal point (say 1000
> for 3 digits).
>
> Unfortunately, the maximum value of double exceeds the maximum value
> of long, on most systems (probably all, due to the very nature of
> floating-point calculations). Perhaps what you really want is: "Same
> magnatude, and first 3 digits equal". But this doesn't work well
> either -- 1.234 * 2.0 might not equal 2.468 because of rounding.
>
> Ideally, we would model the world to avoid floating point altogether,
> or at least to avoid it's problems. In the US, we could count money in
> pennies instead of dollars (banks would need millidollars or something
> like it) so we would never need a fraction. But there's no getting
> around some strange-looking currency conversion rates -- so you're
> still going to have to deal with it somehow.
>
That is exactly what I've done for some financial applications. Bankers
don't like rounding schemes they can't control and most have been pretty
dubious of using any floating point numbers once they were made aware of the
true lack of precision of floats and doubles.
What C++ needs is an arbitrary precision real number type that is base 10
not base 2 with a trait based rounding model. Float and double should really
only be used in scientific and graphics programming.
Ken Shaw
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 21 Nov 2002 18:57:02 +0000 (UTC) Raw View
hyrosen@mail.com (Hyman Rosen) writes:
| Gabriel Dos Reis wrote:
| > Then, rather throw something to indicate garbage are being
| > manipulated instead of perverting meaning of operations on boolean
| > expressions.
|
| It's no more perverted than the fact that ordinary < and >
| don't apply to complex numbers.
I disagree. There have well defined reasons why there is no ordering
on complex numbers *compatible with the field structure*. That does
not mean there is no ordering on complex numbers.
I can't see how that relates to perverting the meaning of well defined
operations on *boolean values*.
| And how many times have you
| seen people define "close equality" using
| bool equals(a, b) { return abs(a - b) < epsilon; }
| which can result in equals(a, b) == true, equals(b, c) == true,
| but equals(a, c) == false?
So what?
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 21 Nov 2002 18:57:26 +0000 (UTC) Raw View
ianmcc@lorentz.leidenuniv.nl (Ian McCulloch) writes:
| hyrosen@mail.com (Hyman Rosen) wrote in message news:<4YYC9.35574$aB1.28934@nwrddc02.gnilink.net>...
| > Allan W wrote:
| > > hyrosen@mail.com (Hyman Rosen) wrote
| > >
| > >>And how many times have you
| > >>seen people define "close equality" using
| > >> bool equals(a, b) { return abs(a - b) < epsilon; }
| > >>which can result in equals(a, b) == true, equals(b, c) == true,
| > >>but equals(a, c) == false?
| > >
| > > What's the alternative?
|
| bool equals(a, b) { return abs(a-b) < epsilon * abs(a+b); }
|
| This is scale-invariant.
It is not.
1) intermediate results may (over|under)flow
2) fails for a = b = 0
[...]
| Some people put max(abs(a), abs(b)) on the right hand side, but I
| figure if you need to fine-tune epsilon to within a factor 2 then
| you're probably in trouble anyway.
Did you try it? If you adhere to the general IEEE-754 floating-point
model you might get surprise with your proposed solution.
| Floating point arithmetic is non-associative, and inexact, why is
| exact transitivity of equals such an important criteria?
The issue, at least, a I raised it is about the pervertion of
operations on boolean expressions.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Thu, 21 Nov 2002 19:57:49 +0000 (UTC) Raw View
On Thu, 21 Nov 2002 18:13:54 +0000 (UTC), hyrosen@mail.com (Hyman Rosen) wrote:
>Hyman Rosen wrote:
> > This should be easy to do by truncating some number of trailing
> > mantissa bits to zero and then using ordinary equality.
>
>You would probably want to round instead, now that I think about
>it, and that could require some fiddling with the exponents as
>well, but the principle is the same - associate each number with
>a representative, and then compare those.
Hm, about the Z key, no it workz all right!
About the above zcheme: *any* zcheme that aimz to provide tranzitive
equality for floating point numberz muzt of necezzity uze dizjoint
(non-overlapping) intervalz, or elze treat all numberz az equal.
Thuz, you have and muzt have the zame problem az with truncation (to
zee an example, zimply conzider two floatz RoundedA and RoundedB that
in thiz zcheme are conzidered different and differ by minimal amount,
then conzider two numberz A and B that round to RoundedA and RoundedB,
rezpectively, where RoundedB < B < A < RoundedA; there iz then an
interval divizion between A and B; thiz divizion can be arbitrarily
"high" in termz of the number of bitz where A and B differ.).
But of courze, if nobody conzidered zuch zchemez and had the gutz
to throw their ideaz out in public for dizcuzzion, then very little
progrezz would be made...
Zo, juzt be careful about adopting zuch zcheme: it avoidz problem of
non-tranzitivity, but it makez zome number compare unequal even
though they're equal to any reazonable epzilon-limit.
Cheerz,
- Alf
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 21 Nov 2002 19:58:35 +0000 (UTC) Raw View
Ian McCulloch wrote:
> bool equals(a, b) { return abs(a-b) < epsilon * abs(a+b); }
As a simple example, lets take epsilon = 0.001. Then we have
equals(100.15, 100.00) true .15 < .20015
equals(100.00, 99.85) true .15 < .19985
equals(100.15, 99.85) false .30 > .20000
> NO! A floating point number does not represent an interval. It
> represents one and only one number. Floating point arithmetic (IEEE
> anyway) works by taking the operands to be exactly represented,
> calculating the result *as if* it had infinite precision and then,
> only at the end, rounding.
Thus, a floating point number represents the interval of real
numbers closer to it than to any other one. This has nothing
to do with interval arithmetic per se.
> Floating point arithmetic is non-associative, and inexact, why is
> exact transitivity of equals such an important criteria?
Because assumption of transitivity can creep in unexpectedly,
and cause problems if it fails.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 21 Nov 2002 20:09:21 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> I can't see how that relates to perverting the meaning of well defined
> operations on *boolean values*.
I can't see how we're talking about perverting the meaning of well-defined
operations on boolean values. The boolean value we're talking about is the
perfectly good value 'false'. The operations on it are the same as always.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Thu, 21 Nov 2002 23:32:05 +0000 (UTC) Raw View
Ken Shaw wrote:
(re numbers for money)
> What C++ needs is an arbitrary precision real number type that is base 10
> not base 2 with a trait based rounding model. Float and double should really
> only be used in scientific and graphics programming.
Oh, like COBOL:
PICTURE 999,999,999.00
You could write a C++ class for "money numbers". You could
probably do the arithmetic correctly in the FPU, too, if you could
keep Microsoft software from changing the FPU rounding
modes unexpectedly.
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 21 Nov 2002 23:32:52 +0000 (UTC) Raw View
ianmcc@lorentz.leidenuniv.nl (Ian McCulloch) writes:
| gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message news:<m3bs4sf2cs.fsf@uniton.integrable-solutions.net>...
| > hyrosen@mail.com (Hyman Rosen) writes:
| >
| > | Anders J. Munch wrote:
| > | > Ok, the right thing to do when encountering a NaN is to throw an
| > | > exception.
| > |
| > | NaNs come in signaling and non-signaling forms, so you get your
| > | choice of behavior.
| >
| > However what does "signaling NaN" means for a *C++* program is still not
| > well defined.
|
| A quote from the Man Himself (W. Kahan):
|
| "NaNs do not trap (unless they are "Signaling" SNaNs, which exist
| mainly for political reasons and are rarely used); NaNs propagate
| through most computations."
Thanks, but I do know this quote (just like the rest of his writings).
And it doesn't say anything about the behaviour of a *C++* program --
the content of my message.
"rarely used" doesn't mean "never used" and "political reasons" is *his*
ways of describing a situation where there were no unanimity not to
have them. And also, please, do bear in mind that IEEE-754 was designed
ages ago with the technology of the time. Technologies have evolved
and it is far from clear that solutions deigned for a set of
assumptions years ago are still relevant (with *no change*) for
devices and technologies avaliable today.
| That is, the whole point of NaNs is that they propogate through the
| calculation until such a point that it is convenient to check for
| them. Certainly, this pre-dates C++ exceptions, but then floating
| point operations are often asynchronous anyway so it is problematic to
| map them directly onto C++ exeptions at the point of occurance.
I don't think there are more problematic than setting a floating-point
status flag or throwing exceptions from threads.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 21 Nov 2002 23:34:41 +0000 (UTC) Raw View
Alf P. Steinbach wrote:
> Thuz, you have and muzt have the zame problem az with truncation
That depends on what you consider to be the problem.
WIth rounding, you get the effect of .99 === 1.01,
but 1.49 =!= 1.51, whereas with truncation you get
the opposite. But you are right that with disjoint
intervals, there will always be pairs of adjacent
machine floats which will fall on opposite sides.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 21 Nov 2002 23:44:12 +0000 (UTC) Raw View
Ken Shaw wrote:
> That is exactly what I've done for some financial applications. Bankers
> don't like rounding schemes they can't control and most have been pretty
> dubious of using any floating point numbers once they were made aware of the
> true lack of precision of floats and doubles.
>
> What C++ needs is an arbitrary precision real number type that is base 10
> not base 2 with a trait based rounding model. Float and double should really
> only be used in scientific and graphics programming.
This is a complete fallacy, unless your financial applications don't deal
with things even as simple as interest rates. In my company, the financial
applications solve differential equations to model values of securities. I
don't think they want to use decimal arithmetic.
Or here's an even simpler problem. An employee gets a salary of $100,000
a year. Employees are paid weekly. Compute the gross pay for each of the
employee's paychecks.
Making the pennies add up may be a reasonable goal, and even a legal
requirement, but making them do so requires an understanding of the
problem, not a different base of arithmetic.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@inbound.dk ("Anders J. Munch")
Date: Fri, 22 Nov 2002 00:06:11 +0000 (UTC) Raw View
"Hyman Rosen" <hyrosen@mail.com> skrev:
> Thus, a floating point number represents the interval of real
> numbers closer to it than to any other one.
Don't go there. Each floating point number represents a single real
value, and represents it accurately. That's the better
interpretation.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@inbound.dk ("Anders J. Munch")
Date: Fri, 22 Nov 2002 00:06:28 +0000 (UTC) Raw View
"Ian McCulloch" wrote in
news:bac6d750.0211210826.623d5070@posting.google.com:
>
> In some statistical programs NaNs are used to represent missing input
> data and they simply propogate through to be NaNs on output.
Very clever. Of course that stops NaNs from being used for their
intended purpose, because how would you distinguish between NaNs
caused by missing input and NaNs caused by invalid operations?
>In this
> case having a NaN throwing an exception actually complicates the code;
> there may not actually be a sensible place to catch the exception.
Clever hacks are fragile.
>
> IEEE NaNs have some unspecified bits which were intended to be used to
> indicate, for example, how or where the NaN arose. Not much software
> takes advantage of this though. NaNs can arise from many different
> sources, eg the correct result could not be obtained, or there is no
> correct result, or there was a missing data sample etc. I find it
> hard to see why you would want two of these NaNs to compare equal,
> unless they arose from the same calculation and represent the same
> 'unobtainable result'. Without keeping track of this information, the
> only sensible choice is NaN == NaN is always false.
Do you often write:
if(! (a != b)) { ... }
?
I don't - I simplify to
if(a == b) { ... }
without giving it a second thought. Which is fully correct so long as
== and != are each other's negation. I contend that any programmer,
who is not paying particular attention to the possibility of NaNs,
will do the same. The choice between:
if(a == b) { foo(); } else { bar(); }
and if(a != b) { bar(); } else { foo(); }
is usually quite arbitrary: In fact, if either foo() or bar() are
no-ops, most likely the variant that allows the else clause to be
elided will be chosen.
With this in mind, can you give me a practical example of how
(NaN!=NaN)==(NaN==NaN)==false will save the day for the unwary
programmer, one that doesn't rely on such arbitrary choices? Or even
one that _does_ rely on an arbitrary choice. Elsewhere I have
presented an example to the contrary: Detecting a configuration
change. Your turn.
And those unspecified bits? If nothing else then you can always
choose to ignore them in comparisons, and you will have lost nothing
compared to IEEE semantics. However, if they _are_ used, then you
would probably want to be able to compare them, to answer questions
such as "has a diagnostic message been emitted for this error bit
pattern yet?".
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 22 Nov 2002 01:49:38 +0000 (UTC) Raw View
andersjm@inbound.dk ("Anders J. Munch") writes:
| "Ian McCulloch" wrote in
| news:bac6d750.0211210826.623d5070@posting.google.com:
| >
| > In some statistical programs NaNs are used to represent missing input
| > data and they simply propogate through to be NaNs on output.
|
| Very clever. Of course that stops NaNs from being used for their
| intended purpose, because how would you distinguish between NaNs
| caused by missing input and NaNs caused by invalid operations?
The real world applications I've seen, playing with NaNs, use
signaling NaNs to represent unitialized data, not quiet NaN. The
situation described by Ian is what I would label a "misuse".
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Fri, 22 Nov 2002 03:45:59 +0000 (UTC) Raw View
alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach) wrote
> The above iz a *very* important point.
>
> It meance that truncating zome number of trailing mantizza bitz will
> end up with the very ZAME problemz that floating point numberz have
> (wrt. comparizionz) without thiz added procezzing.
...and so on.
Alf, you seem fairly intelligent, and I think you made a number of
very useful observations. I look forward to reading them, as soon
as your keyboard has been repaired.
Consider buying a new one -- even very good ones are very cheap now.
It's true that the new ones won't last 20 years, like the old IBM
models. But if you pay only 10% of the cost and the keyboard lasts
20% as long, you have a net gain...
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Fri, 22 Nov 2002 03:46:14 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> ianmcc@lorentz.leidenuniv.nl (Ian McCulloch) writes:
>
> | gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message news:<m3bs4sf2cs.fsf@uniton.integrable-solutions.net>...
> | > hyrosen@mail.com (Hyman Rosen) writes:
> | >
> | > | Anders J. Munch wrote:
> | > | > Ok, the right thing to do when encountering a NaN is to throw an
> | > | > exception.
> | > |
> | > | NaNs come in signaling and non-signaling forms, so you get your
> | > | choice of behavior.
> | >
> | > However what does "signaling NaN" means for a *C++* program is still not
> | > well defined.
> |
> | A quote from the Man Himself (W. Kahan):
> |
> | "NaNs do not trap (unless they are "Signaling" SNaNs, which exist
> | mainly for political reasons and are rarely used); NaNs propagate
> | through most computations."
>
> Thanks, but I do know this quote (just like the rest of his writings).
> And it doesn't say anything about the behaviour of a *C++* program --
> the content of my message.
>
> "rarely used" doesn't mean "never used" and "political reasons" is *his*
> ways of describing a situation where there were no unanimity not to
> have them. And also, please, do bear in mind that IEEE-754 was designed
> ages ago with the technology of the time.
Not quite. The spec was considerably in advance of what was considered current when it was published.
> Technologies have evolved
> and it is far from clear that solutions deigned for a set of
> assumptions years ago are still relevant (with *no change*) for
> devices and technologies avaliable today.
Yes, it is far from clear. We still have not managed to get the spec widely implemented correctly. As for problems with the
standard, only the confusion of inf==ovr and lack of a true zero are serious.
>
>
> | That is, the whole point of NaNs is that they propogate through the
> | calculation until such a point that it is convenient to check for
> | them. Certainly, this pre-dates C++ exceptions, but then floating
> | point operations are often asynchronous anyway so it is problematic to
> | map them directly onto C++ exeptions at the point of occurance.
>
> I don't think there are more problematic than setting a floating-point
> status flag or throwing exceptions from threads.
Yes it is. Much. If you want any kind of error handling other than abort() you have to be able to untangle the heavily
pipelined FPU operations and synchronize them with the (typically scalar) test-and-branch operation(s).
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Fri, 22 Nov 2002 09:45:24 +0000 (UTC) Raw View
"Anders J. Munch" wrote:
> I contend that any programmer,
> who is not paying particular attention to the possibility of NaNs,
.... is making a grave error. It is to save that thoughtless programmer from
the consequences of his neglect that NaN!=NaN was selected.And those
unspecified bits? If nothing else then you can always
> choose to ignore them in comparisons, and you will have lost nothing
> compared to IEEE semantics. However, if they _are_ used, then you
> would probably want to be able to compare them, to answer questions
> such as "has a diagnostic message been emitted for this error bit
> pattern yet?".
That is what casting to unsigned char is for.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 22 Nov 2002 09:45:54 +0000 (UTC) Raw View
witless@attbi.com (Witless) writes:
| > "rarely used" doesn't mean "never used" and "political reasons" is *his*
| > ways of describing a situation where there were no unanimity not to
| > have them. And also, please, do bear in mind that IEEE-754 was designed
| > ages ago with the technology of the time.
|
| Not quite. The spec was considerably in advance of what was
| considered current when it was published.
Untrue; at the time there were proof of concepts -- the "wholy war"
between the IEEE-754 committee members was partly caused by each one
(more or less sponsored by manufacturers) having its own
implementations of what should be The Truth. The NaNs invention wasn't
in advance on the tehchnology available at the time.
| > Technologies have evolved
| > and it is far from clear that solutions deigned for a set of
| > assumptions years ago are still relevant (with *no change*) for
| > devices and technologies avaliable today.
|
| Yes, it is far from clear. We still have not managed to get the
| spec widely implemented correctly.
Because the spec does miss important points (even though it was a
progress in some sense). That is of the reasons why the LIA standards
are aiming at rebalacing the matter.
| As for problems with the
| standard, only the confusion of inf==ovr and lack of a true zero are serious.
The abominable concepts of NaNs with the relational operators
pervertion certainly constitute major parts to the confusion. Wit
this discussion for example, and existing (albeit deplorable)
implementations in compilers.
| > | That is, the whole point of NaNs is that they propogate through the
| > | calculation until such a point that it is convenient to check for
| > | them. Certainly, this pre-dates C++ exceptions, but then floating
| > | point operations are often asynchronous anyway so it is problematic to
| > | map them directly onto C++ exeptions at the point of occurance.
| >
| > I don't think there are more problematic than setting a floating-point
| > status flag or throwing exceptions from threads.
|
| Yes it is. Much. If you want any kind of error handling other than
| abort() you have to be able to untangle the heavily
| pipelined FPU operations and synchronize them with the (typically
| scalar) test-and-branch operation(s).
But the same is true for a multithreaded program.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Anders J. Munch" <andersjm@dancontrol.dk>
Date: Fri, 22 Nov 2002 12:26:45 CST Raw View
"Witless" <witless@attbi.com> wrote:
> "Anders J. Munch" wrote:
>
> > I contend that any programmer,
> > who is not paying particular attention to the possibility of NaNs,
>
> .... is making a grave error. It is to save that thoughtless programmer
from
> the consequences of his neglect that NaN!=NaN was selected.
I have yet to see an example where (NaN==NaN)==false actually does
save that thoughtless programmer.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Thu, 14 Nov 2002 13:14:11 +0000 (UTC) Raw View
"John Nagle" <nagle@animats.com> wrote:
> > ""Anders J. Munch"" <andersjm@dancontrol.dk> wrote:
>
> >>I'd hate for an implementation to be 100% IEEE-compliant. The idea
> >>that there may exist values of x and y such that (x==x) == false and
> >>(x==y) != !(x!=y) is an abomination to me.
>
>
> Those aren't always meaningful comparisons.
>
> The idea behind IEEE floating point comparisons is
> that some operations are invalid; you can't do them at all.
> Comparisons are three-valued, with the possible results being
> "true", "false", and "invalid". For example,
> "INF+ > INF+" is "invalid". All comparisons with NaNs
> are also "invalid".
Ok, the right thing to do when encountering a NaN is to throw an
exception. But then, if you don't throw an exception, returning false
is every bit as wrong as returning true. There is no good reason for
NaN==NaN to return false[1], but there is a good reason to return
true: the integrity of the equivalence relation.
INFs are ordered in IEEE, hence "INF+ > INF+" is not "invalid", it is
just plain old false. AFAIK.
- Anders
[1] Other than for NaN detection purposes, but then I said no _good_
reason.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: news@evo6.com (Andy Sawyer)
Date: Thu, 14 Nov 2002 13:13:57 +0000 (UTC) Raw View
In article <3dd27163$0$35906$edfadb0f@dread13.news.tele.dk>,
andersjm@dancontrol.dk ("Anders J. Munch") wrote:
> std::map uses <= (or < or std::less, I forget),
std::map uses whatever ordering predicate is specified. If none is
explicitly specified, then std::less<KeyType> is used, which (by
default) is defined in terms of operator<
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 14 Nov 2002 17:27:35 +0000 (UTC) Raw View
andersjm@dancontrol.dk ("Anders J. Munch") wrote in message
news:<3dd27163$0$35906$edfadb0f@dread13.news.tele.dk>...
> ""Daniel Pfeffer"" <pfefferd@hotmail.co.il> wrote:
> > ""Anders J. Munch"" <andersjm@dancontrol.dk> wrote:
> > [snip]
> > > I'd hate for an implementation to be 100% IEEE-compliant. The idea
> > > that there may exist values of x and y such that (x==x) == false
> > > and (x==y) != !(x!=y) is an abomination to me. It's much easier to
> > > write algorithms if you can assume that all legal values form a
> > > total ordering. As an illustration, note that std::map<float,T>
> > > has undefined behaviour if float is IEEE-compliant.
> > You are technically correct that std::map<float,T> would have
> > undefined behaviour for IEEE NaNs. However, std::map<> uses exact
> > comparisons in order to find the key. As you are no doubt aware,
> > making exact comparisons between floating-point values is not a good
> > idea. I therefore doubt that this case would come up in well-written
> > production code.
> Examples where std::map<float,T> could be useful:
> - Caching the result of a lengthy calculation.
> - Sorting.
> std::map uses <= (or < or std::less, I forget), which *is* a good idea
> for floating point (otherwise you couldn't sort numbers);
Since std::map defines an ordering, it is essential that it use some
sort of ordering function. Regardless of the type.
> I assumed it had the same problem, but I checked and it seems that <
> and <= are required to raise some kind of exception; what exactly
> raising an IEC 561 exception means in a C++ program I don't know.
It means undefined behavior:-). Anything you do which can actually
result in an NaN (or even Inf) results in undefined behavior in C++.
And the requirements for std::map and std::set only apply to values
actually used, either by trying to put them into the container, or by
searching for them, and not to all possible values of the type. The
fact that IEEE double has a NaN which doesn't meet the ordering
requirements is not relevant if you never use this value.
> As for comparison for equality, although the general rule is to avoid
> it, there cases where it does make sense.
There are lots of cases where it makes sense. IMHO, the general rule
isn't to avoid comparing for equality; the general rule is to know what
you are doing. Admittedly, for floating point calculations, not an easy
rule. (I only know enough to know that I don't know enough.) Still,
it's the only rule that works -- machine floating points are NOT real
numbers, they don't obey the rules of real numbers, and if you don't
know the rules they do obey, you're better off avoiding them.
(Within limits, of course. I don't hesitate about using something like
"100.0 * x / y" to display a percentage (where x and y are integers),
even though I don't know enough about machine floating point to use it
for normal calculations.)
> Like seeing if something has changed:
> x = read_parameter_from_init_file("x");
> if(x != previous_x)
> {
> cout << "x parameter has changed; restarting calculation" << endl;
> Reset();
> previous_x = x;
> }
> > Personally, I find NaNs to be useful error indicators.
> Certainly, and I have no objections to 99.9% IEC-561 compliance. You
> can add all the special values you like and I won't complain, as long
> as you place them in a well-defined place in the ordering.
To which I would answer: if you need a complete ordering, avoid NaNs
(and Inf).
> Basically I just like for == to be an equivalence relation and <= to
> be a complete ordering.
I'd like world peace and the end of hunger in the world, too:-).
Seriously, machine floating point isn't real numbers, and nothing we can
do will make them such. It should be possible to avoid NaN's when they
would cause a problem (by e.g. constraining input values). And I
certainly prefer a NaN to some arbitrary, apparently correct value, when
the program or the data contains an error.
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 14 Nov 2002 17:31:32 +0000 (UTC) Raw View
Anders J. Munch wrote:
> Ok, the right thing to do when encountering a NaN is to throw an
> exception.
NaNs come in signaling and non-signaling forms, so you get your
choice of behavior.
> But then, if you don't throw an exception, returning false
> is every bit as wrong as returning true.
No. NaNs are not equal to any number, and that includes themselves.
Most comparisons will look like (x == y), not (x == x), and since
such equality is a special and unusual case, it's much better to
return false than true. After all, if both x and y are NaN, they
got that way as a result of erroneous calculation. What can it mean
for two erroneous results to compare as equal? This is precisely
the situation for which NaNs were designed.
> the integrity of the equivalence relation.
Is meaningless when the things being compared are garbage.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 14 Nov 2002 22:43:09 +0000 (UTC) Raw View
hyrosen@mail.com (Hyman Rosen) writes:
| Anders J. Munch wrote:
| > Ok, the right thing to do when encountering a NaN is to throw an
| > exception.
|
| NaNs come in signaling and non-signaling forms, so you get your
| choice of behavior.
However what does "signaling NaN" means for a *C++* program is still not
well defined.
[...]
| > the integrity of the equivalence relation.
|
| Is meaningless when the things being compared are garbage.
Then, rather throw something to indicate garbage are being
manipulated instead of perverting meaning of operations on boolean
expressions.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: news@evo6.com (Andy Sawyer)
Date: Thu, 14 Nov 2002 22:43:11 +0000 (UTC) Raw View
In article <aqstf6$8f3$1@news.inter.net.il>,
pfefferd@hotmail.co.il ("Daniel Pfeffer") wrote:
> ""Anders J. Munch"" <andersjm@dancontrol.dk> wrote in message
> news:3dd0ce82$0$2578$edfadb0f@dread12.news.tele.dk...
>
> [snip]
>
> > I'd hate for an implementation to be 100% IEEE-compliant. The idea
> > that there may exist values of x and y such that (x==x) == false and
> > (x==y) != !(x!=y) is an abomination to me. It's much easier to write
> > algorithms if you can assume that all legal values form a total
> > ordering. As an illustration, note that std::map<float,T> has
> > undefined behaviour if float is IEEE-compliant.
[snip]
> However, std::map<> uses exact comparisons in order to find the
> key.
That rather depends on what you mean by "exact comparisions". Given
the context, it would appear that you're referring to the equality
operator, which a conforming implementation of std::map certainly does
_not_ use, it uses whatever ordering predicate you speficy to locate
keys, and the default is std::less. Two keys are considered equivalent
if comp(k1,k2) == false and comp(k2,k1) == false.
> As you are no doubt aware, making exact comparisons between
> floating-point values is not a good idea. I therefore doubt that
> this case would come up in well-written production code.
But if you know enough about your key domain, it's possible to write an
ordering predicate such that std::map<float,T,predicate> works
perfectly well over that domain.
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 14 Nov 2002 23:29:27 +0000 (UTC) Raw View
Gabriel Dos Reis wrote:
> Then, rather throw something to indicate garbage are being
> manipulated instead of perverting meaning of operations on boolean
> expressions.
It's no more perverted than the fact that ordinary < and >
don't apply to complex numbers. And how many times have you
seen people define "close equality" using
bool equals(a, b) { return abs(a - b) < epsilon; }
which can result in equals(a, b) == true, equals(b, c) == true,
but equals(a, c) == false?
Computer operations mean whatever they are defined to do.
As long as everyone is told what that is, that's good enough.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rogero@howzatt.demon.co.uk (Roger Orr)
Date: Fri, 15 Nov 2002 00:25:27 +0000 (UTC) Raw View
andersjm@dancontrol.dk ("Anders J. Munch") wrote in message news:<3dd27163$0$35906$edfadb0f@dread13.news.tele.dk>...
>
> Examples where std::map<float,T> could be useful:
> - Caching the result of a lengthy calculation.
I'd be rather concerned if I found a cache of std::map<float,T>, since
the
presence of floating point rounding would typically cause the cache to
perform badly ...
Roger Orr
--
MVP in C++ at www.brainbench.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Fri, 15 Nov 2002 02:01:02 +0000 (UTC) Raw View
andersjm@dancontrol.dk ("Anders J. Munch") wrote
> "John Nagle" <nagle@animats.com> wrote:
> > The idea behind IEEE floating point comparisons is
> > that some operations are invalid; you can't do them at all.
> > Comparisons are three-valued, with the possible results being
> > "true", "false", and "invalid". For example,
> > "INF+ > INF+" is "invalid". All comparisons with NaNs
> > are also "invalid".
>
> Ok, the right thing to do when encountering a NaN is to throw an
> exception. But then, if you don't throw an exception, returning false
> is every bit as wrong as returning true. There is no good reason for
> NaN==NaN to return false[1], but there is a good reason to return
> true: the integrity of the equivalence relation.
The rationale for returning false is that the expression isn't true.
Similar logic applies to the SQL language when fields can be NULL;
select * from customers where balance>1000.00
won't return customers that have a NULL balance, because it isn't
greater than 1000. Similarly,
select * from customers where balance<=1000.00
also will not return those customers.
The same reasoning can be applied to comparing float values. NaN>0.0 will
return false, because it isn't greater than zero. As James Kanze pointed
out, machine floating point numbers are NOT the same thing as real numbers.
In real numbers, !(a>b) implies a<=b, but that doesn't apply to NaN. It
also doesn't apply to infinity! INF+/INF+ does not equal one.
If existing algorithms suddenly have to confront NaN or INF values, they
are going to break. That doesn't mean that changing the standard to allow
these new values is neccesarily a bad thing. As several people have
already pointed out, nothing you can portably do today will ever result in
NaN or INF, so your program won't have to change a bit unless you WANT to
deal with these values for some reason.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Fri, 15 Nov 2002 17:06:30 +0000 (UTC) Raw View
"Allan W" <allan_w@my-dejanews.com> wrote in message:
> andersjm@dancontrol.dk ("Anders J. Munch") wrote
> > "John Nagle" <nagle@animats.com> wrote:
> > > The idea behind IEEE floating point comparisons is
> > > that some operations are invalid; you can't do them at all.
> > > Comparisons are three-valued, with the possible results being
> > > "true", "false", and "invalid". For example,
> > > "INF+ > INF+" is "invalid". All comparisons with NaNs
> > > are also "invalid".
> >
> > Ok, the right thing to do when encountering a NaN is to throw an
> > exception. But then, if you don't throw an exception, returning false
> > is every bit as wrong as returning true. There is no good reason for
> > NaN==NaN to return false[1], but there is a good reason to return
> > true: the integrity of the equivalence relation.
>
> The rationale for returning false is that the expression isn't true.
And the rationale for returning true is that the expression isn't
false. There is a big difference between being undefined and being
'false'.
Besides, it *is* true. NaN and NaN *are* the same thing. That thing
is a trap floating-point value that doesn't model any mathematical
real number, but as a C++ object it is a well-defined (IEEE 754
defines it meticulously) object value that is certainly equal to
itself. That said object value probably stems from some ill-conceived
numerics doesn't make the value in itself ill-conceived.
(Oh, and for the record, when I write "well-defined", remember that
the premise for this subthread is that a desire for a more formalized
relationship between the C++ standard and IEEE floating-point was
expressed.)
> Similar logic applies to the SQL language when fields can be NULL;
Similar critique can be applied to the SQL language, and C.J. Date has
indeed done so.
> As James Kanze pointed
> out, machine floating point numbers are NOT the same thing as real
numbers.
Ironically, that's exactly my point as well.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Fri, 15 Nov 2002 17:07:27 +0000 (UTC) Raw View
"Hyman Rosen" <hyrosen@mail.com> wrote:
>
> > the integrity of the equivalence relation.
>
> Is meaningless when the things being compared are garbage.
NaNs are not garbage. They carry valuable information.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: vAbazarov@dAnai.com ("Victor Bazarov")
Date: Fri, 15 Nov 2002 17:53:31 +0000 (UTC) Raw View
"Allan W" <allan_w@my-dejanews.com> wrote...
> [...]
> The same reasoning can be applied to comparing float values. NaN>0.0 will
> return false, because it isn't greater than zero. As James Kanze pointed
> out, machine floating point numbers are NOT the same thing as real
numbers.
> In real numbers, !(a>b) implies a<=b, but that doesn't apply to NaN. It
> also doesn't apply to infinity! INF+/INF+ does not equal one.
I think the reason for this "inconsistency" is that neither NaN nor
INF should really be part of 'double' or 'float' set of numbers. They
got the same type due to the lack of anything better. IMHO, a better
way to handle it would be to have a type "result of an FP op", which
could be "Number" with value of type 'float' or 'double' or "Not a
Number" without any value. That indirection (for some reasons which
are not the issue here) was skipped. Now we have this thing that
doesn't fit anywhere...
As for infinity, in math INF+/INF+ is not necessarily 1. There
are different types of infinity (just like there are different
types of zeros). In the computer domain INF*INF would be the _same_
INF (if the operation would be allowed), whereas in math it isn't.
Inability to keep those different values in the computer is our
trouble, but it is correctable. We have UDTs and we could use them
to overcome problems with regular doubles and floats.
Just my $0.02...
Victor
--
Please remove capital A's from my address when replying by mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Fri, 15 Nov 2002 20:01:27 +0000 (UTC) Raw View
"Roger Orr" <rogero@howzatt.demon.co.uk> wrote:
> andersjm@dancontrol.dk ("Anders J. Munch") wrote:
> >
> > Examples where std::map<float,T> could be useful:
> > - Caching the result of a lengthy calculation.
>
> I'd be rather concerned if I found a cache of std::map<float,T>, since
> the
> presence of floating point rounding would typically cause the cache to
> perform badly ...
You could certainly devise uses where that would happen. But why would you?
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: esben@despammed.com (Esben Mose Hansen)
Date: Fri, 15 Nov 2002 21:25:32 +0000 (UTC) Raw View
Victor Bazarov wrote:
Just to set the mathematical record straight, which I think is important
if one is to decide how double (or float) should behave:
> I think the reason for this "inconsistency" is that neither NaN nor
> INF should really be part of 'double' or 'float' set of numbers. They
I assume that you hereby mean that double (and float) should represent a
(subset of) ]-INF;+INF[ (Americans, read: (-INF;+INF) ). This points
has a lot of merit and is essentially how it works today --- excepting
overflows and such.
[...]
> As for infinity, in math INF+/INF+ is not necessarily 1. There
I assume that you're now working in [-INF; +INF]. Actually, in this
space, +INF/+INF are usually not attributed the value 1. It is usually
comdemmed to the realm of "meaningless", which means that no reasonable
value can be assigned. Think of 0/0.
Note that while ]-INF;+INF[ is a fairly well-behaved space (only a few
pitfalls, such as division by zero), [-INF; +INF] is not. It is one of
those number spaces which are occasionally useful, but usually not worth
the bother.
> are different types of infinity (just like there are different
> types of zeros). In the computer domain INF*INF would be the _same_
Here, you're talking of, what? It seems to be a bit of cardinality mixed
with non-standard analysis. In none of the spaces above are there more
than one 0,
> INF (if the operation would be allowed), whereas in math it isn't.
and no definition of +INF yields other than +INF*+INF = +INF, that I
have seen. However, 2^(+INF) >= +INF do occur in some spaces, though
+INF is then usually called "Alef 0".
regards, Esben
--
A computer is a bicycle to the mind --- you still have to pedal. (Anonymous)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: vAbazarov@dAnai.com ("Victor Bazarov")
Date: Sat, 16 Nov 2002 00:56:14 +0000 (UTC) Raw View
"Esben Mose Hansen" <esben@despammed.com> wrote...
> Victor Bazarov wrote:
>
> Just to set the mathematical record straight, which I think is important
> if one is to decide how double (or float) should behave:
>
> > I think the reason for this "inconsistency" is that neither NaN nor
> > INF should really be part of 'double' or 'float' set of numbers. They
>
> I assume that you hereby mean that double (and float) should represent a
> (subset of) ]-INF;+INF[ (Americans, read: (-INF;+INF) ). This points
> has a lot of merit and is essentially how it works today --- excepting
> overflows and such.
>
> [...]
>
> > As for infinity, in math INF+/INF+ is not necessarily 1. There
>
> I assume that you're now working in [-INF; +INF]. Actually, in this
> space, +INF/+INF are usually not attributed the value 1. It is usually
> comdemmed to the realm of "meaningless", which means that no reasonable
> value can be assigned. Think of 0/0.
Think limits. (x*x)==+INF given x==INF, right? (x*x*x)==INF also
given x==INF. However (x*x)/(x*x*x) given x==INF in math is ZERO,
(x*x)/(x*x) in math is 1, and (x*x*x)/(x*x) in math is INF. No?
I am talking inability of 'double' type to represent different degrees
of infinity (just like different degrees of infinitely small values).
We could introduce UDTs for that if needed. Not that it's needed too
much...
> > are different types of infinity (just like there are different
> > types of zeros). In the computer domain INF*INF would be the _same_
>
> Here, you're talking of, what?
See above.
> It seems to be a bit of cardinality mixed
> with non-standard analysis. In none of the spaces above are there more
> than one 0,
>
> > INF (if the operation would be allowed), whereas in math it isn't.
>
> and no definition of +INF yields other than +INF*+INF = +INF, that I
> have seen.
Too bad. You must have not seen enough.
> However, 2^(+INF) >= +INF do occur in some spaces, though
> +INF is then usually called "Alef 0".
I have not heard Alef 0. But in our school we were taught that
(x^2 / x^3) is 0 if x==INF. That's all.
Victor
--
Please remove capital A's from my address when replying by mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Sat, 16 Nov 2002 02:28:55 +0000 (UTC) Raw View
"James Kanze" <kanze@gabi-soft.de> wrote in message:
> And the requirements for std::map and std::set only apply to values
> actually used, either by trying to put them into the container, or by
> searching for them, and not to all possible values of the type. The
> fact that IEEE double has a NaN which doesn't meet the ordering
> requirements is not relevant if you never use this value.
What you're saying makes a lot of sense. I don't see any support for
that point of view in the standard, though.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: esben@despammed.com (Esben Mose Hansen)
Date: Sun, 17 Nov 2002 08:16:06 +0000 (UTC) Raw View
Victor Bazarov wrote:
> "Esben Mose Hansen" <esben@despammed.com> wrote...
Ok, I'll try once more, after that interested parties who are still
confused should try a textbook. It's a rather fascinating topic, if
you're into this sort of thing :-D
[...]
>>I assume that you hereby mean that double (and float) should represent a
>> (subset of) ]-INF;+INF[ (Americans, read: (-INF;+INF) ). This points
>>has a lot of merit and is essentially how it works today --- excepting
>>overflows and such.
>>
>>[...]
>>
>>
>>>As for infinity, in math INF+/INF+ is not necessarily 1. There
>>
>>I assume that you're now working in [-INF; +INF]. Actually, in this
>>space, +INF/+INF are usually not attributed the value 1. It is usually
>>comdemmed to the realm of "meaningless", which means that no reasonable
>>value can be assigned. Think of 0/0.
>
>
> Think limits. (x*x)==+INF given x==INF, right? (x*x*x)==INF also
> given x==INF. However (x*x)/(x*x*x) given x==INF in math is ZERO,
> (x*x)/(x*x) in math is 1, and (x*x*x)/(x*x) in math is INF. No?
It doesn't work that way; you have to 1) decide if you're working in
]-INF;+INF[ or [-INF;+INF] 2) only use legal operations. In the above,
x*x*x/x*x does indeed tend towards infinity for x->+INF, and not
surprisingly, the reciproc (or is it inverse in english?) tends toward
zero. This is actually the reason why +INF/+INF is usually not
attributed a value. However, if you're working in the [-INF;+INF] space,
then (+INF)*(+INF)/+(INF) is meaningless, as is the above quotients.
You have to decide with yourself: is x a number (+INF), or are we
talking limits here?
>
> I am talking inability of 'double' type to represent different degrees
> of infinity (just like different degrees of infinitely small values).
You're talking non-sense. There is only one type of infinity, which is
the (two) compactifization (spelling?) points for the real numbers. In
the [-INF;+INF].
What you're talking about /is/ actually possible, by using (a lot) of
set theory. It's a field called non-standard analysis, which is
seductively intuitive, and fun to work with. It is, IMHO, not for the
weak of mind, however. Using set theory, you can construct a space which
behaves more or less as you outlined above. This space is usually called
R*. It does not satisfy the archimedes property, though, which states
that for any x>0, x+x > x. It's also an awfully big space, having more
numbers than the real numbers. (For interested parties, the latter mean
that there exists a bijective funtion f:R*->R*\R.)
> We could introduce UDTs for that if needed. Not that it's needed too
> much...
UDT = User defined types, I assume? Why use abbrevation for terms you
only use once? Unless you're american: I know they have a passion for
acronyms. It might be possible, however, I see little point. My
recommendation is to use doubles to simulate real numbers; or, if that
is not enough, use simulated real numbers and +/-INF. Already, doubles
can only represent a very limited sample of the real numbers. We don't
need an even bigger(!) space.
[...]
>>>INF (if the operation would be allowed), whereas in math it isn't.
>>
>>and no definition of +INF yields other than +INF*+INF = +INF, that I
>>have seen.
>
>
> Too bad. You must have not seen enough.
<G> I'm a master of mathematics, having specialized in an arena vaguely
related to this (Approximation of topological spaces.) If you can read
danish I have my thesis here
http://www.math.ku.dk/~eilers/specialer/hansen/speciale.ps
I think I know what I'm talking about :-) It is confusing though, that
you will not settle on the range of numbers you're working on. This can
and will bite you, you know.
>>However, 2^(+INF) >= +INF do occur in some spaces, though
>>+INF is then usually called "Alef 0".
>
>
> I have not heard Alef 0. But in our school we were taught that
> (x^2 / x^3) is 0 if x==INF. That's all.
You school probably didn't teach that; otherwise some teacher probably
got it wrong. What IS true is that (x^2 / x^3) -> 0 as x -> +INF. But
that's another statement altogether, though the laws of limits make it
look more similar than it is. This is in all probabilty what you school
taught, though some teacher may have got the wacko idea of introducing
non-standard mathamatics to school-children :-P
Alef 0 is the beginning of an (infinite) row of numbers corresponding to
different kinds of infinity. Thus, they are Alef 0 number of natural and
rational numbers, while they are Alef 1 subsets of natural numbers.
(According to one hypothesis, the continuum hypothesis, this number
corresponds to the number of real numbers.). But this is really
irrelevant to this topic.
regards, Esben
--
Furthermore, a good chunk of his theory is untestable metaphysics,
psychobabble and gobbledygook.
http://skepdic.com/backmess.html
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Sun, 17 Nov 2002 13:31:23 +0000 (UTC) Raw View
Hyman Rosen wrote:
> Anders J. Munch wrote:
>
>> Ok, the right thing to do when encountering a NaN is to throw an
>> exception.
>
> NaNs come in signaling and non-signaling forms, so you get your
> choice of behavior.
The problem is that there's no "not a Boolean". When
the result is a floating point number, non-signalling NaNs can
propagate, but when there's a comparison without meaning,
the only valid thing to do is raise an exception.
If you don't do this, you have to be really careful in the
compiler about applying optimizations to Boolean expressions.
None of the usual laws of Boolean algebra are valid.
In practice, no compilers get this right, which is why those
of us doing number crunching with huge dynamic range have to worry
about this problem.
I actually do get these situations in a useful program.
In my "Falling Bodies", a physics simulator for animation,
overflows happen all the time in the early stages of collision
simulation. They have to be caught and the timestep reduced.
Merely checking for NaNs at the end isn't good enough; I've
had cases where a bad branch due to an invalid comparison with
a NaN hid an overflow. So I have to handle floating
point exceptions during normal operation. Note that the result
is not error termination, but adjusting the simulation time step
to deal with the problem; the problem is handled gracefully.
The payoff for doing it right was when, in 1997, the program
was demoed at a major graphics conference, and someone tried
simulating a giant robot walker hitting the ground. They set up,
by mistake, initial conditions which sent it up by its own height in one
frame, launching it upwards at high speed. When it came back down,
hitting the ground at Mach 2, the overflows were all handled
right and, after a few seconds of crunching, the bounce and
fall were properly simulated.
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net (James Kuyper)
Date: Mon, 18 Nov 2002 19:38:00 +0000 (UTC) Raw View
"Anders J. Munch" wrote:
>
> "John Nagle" <nagle@animats.com> wrote:
> > For the next go-round of the standard, I'd suggest that
> > if the implementation's floating point complies with the
> > IEEE standard, the semantics of floating point, as seen
> > from C++, should be defined. This means talking about
> > NaN, INF, rounding modes, etc. in a standardized way.
> > Right now, access to those features is implementation
> > dependent, which is annoying for number-crunching work.
>
> I presume that you want something that goes beyond what
> std::numeric_limits has to offer. Could you be more specific as to
> what?
You might want to look at the IEEE support added to the C99. This
includes comparison functions that return a well-define value in
situations where the IEEE comparison operators are required to raise
floating point exceptions. There's also a lot of new features for
controlling how floating point exceptions are handled, querying the
floating point exception environment, and working with floating point
representations. I just recently had to write some code that uses the
new nan(), isnan(), and nextafter() functions.
Hopefully, the next release of C++ standard will borrow most of those
features, possibly with modifications. For instance, it would be nice to
query/control whether or not floating point exceptions get translated
into C++ exceptions.
...
> I'd hate for an implementation to be 100% IEEE-compliant. The idea
> that there may exist values of x and y such that (x==x) == false and
> (x==y) != !(x!=y) is an abomination to me. It's much easier to write
> algorithms if you can assume that all legal values form a total
> ordering. As an illustration, note that std::map<float,T> has
> undefined behaviour if float is IEEE-compliant.
You certainly wouldn't want to use map<float,T> if the keys are ever
likely to be NaNs. However, that's precisely why the standard allows you
to provide alternative comparison objects. NaNs, as their name implies,
don't
represent numbers, and therefore should not be in an ordered
relationship with
things that are numbers, or even with each other. However, as keys in a
map, you can choose to sort them any way you want, by using a suitably
defined comparison object.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rogero@howzatt.demon.co.uk ("Roger Orr")
Date: Tue, 19 Nov 2002 00:01:27 +0000 (UTC) Raw View
""Anders J. Munch"" <andersjm@dancontrol.dk> wrote in message
news:<3dd4bfb7$0$1514$edfadb0f@dread11.news.tele.dk>...
> "Roger Orr" <rogero@howzatt.demon.co.uk> wrote:
> > andersjm@dancontrol.dk ("Anders J. Munch") wrote:
> > >
> > > Examples where std::map<float,T> could be useful:
> > > - Caching the result of a lengthy calculation.
> >
> > I'd be rather concerned if I found a cache of std::map<float,T>, since
> > the
> > presence of floating point rounding would typically cause the cache to
> > perform badly ...
>
> You could certainly devise uses where that would happen. But why would
you?
Here is a simple example of the sort of potential problem I was thinking
of:-
#include <map>
#include <vector>
#include <iostream>
std::vector< float > floatVec;
int main()
{
std::map<float,bool> floatMap;
float f = 0.0;
// Set up the cache
for ( int i = 0; i < 10; ++i )
{
floatMap[ f ] = true;
f += 0.1;
}
// Check what's in the cache
for ( int j = 0; j < 10; ++j )
{
f = 0.1 * j;
std::cout << "floatMap[" << f << "] = " << floatMap[f] << std::endl;
}
return 0;
}
When executed you are unlikely to get a list of '1's
On an Intel box I get:-
floatMap[0] = 1
floatMap[0.1] = 1
floatMap[0.2] = 1
floatMap[0.3] = 1
floatMap[0.4] = 1
floatMap[0.5] = 1
floatMap[0.6] = 1
floatMap[0.7] = 0
floatMap[0.8] = 0
floatMap[0.9] = 0
Typically the naive user of map<float, XX> doesn't think about the issue of
rounding, and what a suitable epsilon value might be in the problem domain
to consider two points identical.
This example compares a key generated by simple addition with one generate
by simple multiplication.
The more complex the steps undergone to generate thr key the larger becomes
the potential for rounding errors.
Roger Orr
--
MVP in C++ at www.brainbench.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Tue, 19 Nov 2002 09:23:58 +0000 (UTC) Raw View
rogero@howzatt.demon.co.uk ("Roger Orr") writes:
[...]
| Typically the naive user of map<float, XX> doesn't think about the issue of
| rounding, and what a suitable epsilon value might be in the problem domain
| to consider two points identical.
Oh well, if we were to ban C++ features based on how easily a
hypothetical naive user could make fool of (him|her)self then I think
nearly every feature could be taken out...
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Tue, 19 Nov 2002 18:16:57 +0000 (UTC) Raw View
""Roger Orr"" <rogero@howzatt.demon.co.uk> wrote:
> ""Anders J. Munch"" <andersjm@dancontrol.dk> wrote:
> > "Roger Orr" <rogero@howzatt.demon.co.uk> wrote:
> > > andersjm@dancontrol.dk ("Anders J. Munch") wrote:
> > > >
> > > > Examples where std::map<float,T> could be useful:
> > > > - Caching the result of a lengthy calculation.
> > >
> > > I'd be rather concerned if I found a cache of std::map<float,T>, since
> > > the
> > > presence of floating point rounding would typically cause the cache to
> > > perform badly ...
> >
> > You could certainly devise uses where that would happen. But why would
> you?
>
> Here is a simple example of the sort of potential problem I was thinking
> of:-
That's nok a kn^H^Hcache. *This* is a cache.
#include <map>
using namespace std;
template<typename ArgT, typename ResT, ResT (*F)(ArgT)>
class Cache
{
typedef map<ArgT,ResT> cache_t;
mutable cache_t cache;
public:
ResT operator()(ArgT arg) const
{
cache_t::iterator it = cache.find(arg);
if(it == cache.end())
{
ResT res = F(arg);
cache[arg] = res;
return res;
}
else
{
return it->second;
}
}
};
This wraps a more-or-less arbitrary one-argument function, creating a
caching version of same. Not optimal, but shows the point. Should
work for anything that can be inserted into a map, not just
floating-point.
Notice how, characteristically for caching, the values being compared
come from the same source, namely the operator() argument. Which
means that odds are pretty good that input has been through the exact
same processing, incurring the exact same rounding errors, and thus
still compare equal.
Of course if the input is intrinsically random, then two values will
(almost) never match. But then in that case it wouldn't make sense to
use caching in any shape or form.
Non-random data sources that are likely to produce identical values
every once in a while are plentiful: Configuration files, user input,
internal timing measurements, measurements taken through an ADC etc.
Perhaps in your domain floating-point numbers are virtually never
equal, but rest assured that there are other domains where they often
are.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: scottm@toast.net ("Scott Mayo")
Date: Mon, 11 Nov 2002 17:57:53 +0000 (UTC) Raw View
Given fa and fb, 2 floating point values. If there was no hardware involved
and only the rules of mathematics were involved,
(fa * fb >= 0.)
should mean "true if the signs are the same" (in the sense of
negative and non-negative.)
If some hardware had a faster way to compare the signs of two
floating point numbers, would the compiler be allowed to use it? Or
does it have to do the multiply, risking overflow, underflow and whatever
else can go bump in the night?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Victor Bazarov" <vAbazarov@dAnai.com>
Date: Mon, 11 Nov 2002 17:00:09 CST Raw View
"Scott Mayo" <scottm@toast.net> wrote...
> Given fa and fb, 2 floating point values. If there was no hardware
involved
> and only the rules of mathematics were involved,
> (fa * fb >= 0.)
> should mean "true if the signs are the same" (in the sense of
> negative and non-negative.)
>
> If some hardware had a faster way to compare the signs of two
> floating point numbers, would the compiler be allowed to use it? Or
> does it have to do the multiply, risking overflow, underflow and whatever
> else can go bump in the night?
It has to do multiply. If the operation fa * fb causes overflow
which throws, then not doing multiply and comparing signs instead
would have different side effect than, say fa * fb >= 1. That
is unacceptable, I think.
Victor
--
Please remove capital A's from my address when replying by mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Tue, 12 Nov 2002 00:07:16 +0000 (UTC) Raw View
On Mon, 11 Nov 2002 17:00:09 CST, "Victor Bazarov" <vAbazarov@dAnai.com> wrote:
>"Scott Mayo" <scottm@toast.net> wrote...
>> Given fa and fb, 2 floating point values. If there was no hardware
>involved
>> and only the rules of mathematics were involved,
>> (fa * fb >= 0.)
>> should mean "true if the signs are the same" (in the sense of
>> negative and non-negative.)
>>
>> If some hardware had a faster way to compare the signs of two
>> floating point numbers, would the compiler be allowed to use it? Or
>> does it have to do the multiply, risking overflow, underflow and whatever
>> else can go bump in the night?
>
>
>It has to do multiply. If the operation fa * fb causes overflow
>which throws, then not doing multiply and comparing signs instead
>would have different side effect than, say fa * fb >= 1. That
>is unacceptable, I think.
Floating point error detection & error handling is not part of
the standard.
AFAICS the compiler is not constrained by the standard in this case.
Cheers,
- Alf
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Tue, 12 Nov 2002 07:48:06 +0000 (UTC) Raw View
Alf P. Steinbach wrote:
> On Mon, 11 Nov 2002 17:00:09 CST, "Victor Bazarov" <vAbazarov@dAnai.com> wrote:
>>"Scott Mayo" <scottm@toast.net> wrote...
.....
> Floating point error detection & error handling is not part of
> the standard.
>
> AFAICS the compiler is not constrained by the standard in this case.
I don't think it is, either.
For the next go-round of the standard, I'd suggest that
if the implementation's floating point complies with the
IEEE standard, the semantics of floating point, as seen
from C++, should be defined. This means talking about
NaN, INF, rounding modes, etc. in a standardized way.
Right now, access to those features is implementation
dependent, which is annoying for number-crunching work.
However, non-IEEE compliant floating point
should be allowed, for DSPs, graphics processors,
game machines, and older supercomputers. Presumably
there should be some way to tell whether the available
floating point is IEEE compliant. (Java takes the
position that floating point must be IEEE compliant,
but that's probably too restrictive for C++.)
This issue probably should be referred over to
the ANSI C numerics people, and C++ should follow
whatever they do.
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: pfefferd@hotmail.co.il ("Daniel Pfeffer")
Date: Tue, 12 Nov 2002 07:48:14 +0000 (UTC) Raw View
"Alf P. Steinbach" <alf_p_steinbach@yahoo.no.invalid> wrote in message
news:3dd0456f.870981343@news.bluecom.no...
> On Mon, 11 Nov 2002 17:00:09 CST, "Victor Bazarov" <vAbazarov@dAnai.com>
wrote:
>
> >"Scott Mayo" <scottm@toast.net> wrote...
> >> Given fa and fb, 2 floating point values. If there was no hardware
> >involved
> >> and only the rules of mathematics were involved,
> >> (fa * fb >= 0.)
> >> should mean "true if the signs are the same" (in the sense of
> >> negative and non-negative.)
> >>
> >> If some hardware had a faster way to compare the signs of two
> >> floating point numbers, would the compiler be allowed to use it? Or
> >> does it have to do the multiply, risking overflow, underflow and
whatever
> >> else can go bump in the night?
> >
> >
> >It has to do multiply. If the operation fa * fb causes overflow
> >which throws, then not doing multiply and comparing signs instead
> >would have different side effect than, say fa * fb >= 1. That
> >is unacceptable, I think.
>
> Floating point error detection & error handling is not part of
> the standard.
>
> AFAICS the compiler is not constrained by the standard in this case.
I think that this is more an issue of what the programmer would expect the
compiler to do. Given the test (fa * fb >= x), where x != 0, the compiler
must:
multiply fa and fb (may trigger an implementation-dependent trap)
compare the result to x (may trigger an implementation-dependent trap)
set the result of the test to either true or false
Can you see any reason why the compiler should behave differently in the
case x == 0?
Granted, the compiler may be able to behave "as if" the multiplication were
performed rather than actually performing the multiplication, but all of the
implementation-dependent side-effects should occur as well!
Daniel Pfeffer
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Tue, 12 Nov 2002 12:38:58 +0000 (UTC) Raw View
"John Nagle" <nagle@animats.com> wrote:
> For the next go-round of the standard, I'd suggest that
> if the implementation's floating point complies with the
> IEEE standard, the semantics of floating point, as seen
> from C++, should be defined. This means talking about
> NaN, INF, rounding modes, etc. in a standardized way.
> Right now, access to those features is implementation
> dependent, which is annoying for number-crunching work.
I presume that you want something that goes beyond what
std::numeric_limits has to offer. Could you be more specific as to
what?
>
> However, non-IEEE compliant floating point
> should be allowed, for DSPs, graphics processors,
> game machines, and older supercomputers. Presumably
> there should be some way to tell whether the available
> floating point is IEEE compliant. (Java takes the
> position that floating point must be IEEE compliant,
> but that's probably too restrictive for C++.)
I'd hate for an implementation to be 100% IEEE-compliant. The idea
that there may exist values of x and y such that (x==x) == false and
(x==y) != !(x!=y) is an abomination to me. It's much easier to write
algorithms if you can assume that all legal values form a total
ordering. As an illustration, note that std::map<float,T> has
undefined behaviour if float is IEEE-compliant.
- Anders
--
Anders Munch. Software Engineer, Dancontrol A/S, Haderslev, Denmark
Still confused but at a higher level.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Tue, 12 Nov 2002 18:11:03 +0000 (UTC) Raw View
On Tue, 12 Nov 2002 07:48:14 +0000 (UTC), pfefferd@hotmail.co.il ("Daniel Pfeffer")
wrote:
>"Alf P. Steinbach" <alf_p_steinbach@yahoo.no.invalid> wrote in message
>news:3dd0456f.870981343@news.bluecom.no...
>> On Mon, 11 Nov 2002 17:00:09 CST, "Victor Bazarov" <vAbazarov@dAnai.com>
>wrote:
>>
>> >"Scott Mayo" <scottm@toast.net> wrote...
>> >> Given fa and fb, 2 floating point values. If there was no hardware
>> >involved
>> >> and only the rules of mathematics were involved,
>> >> (fa * fb >= 0.)
>> >> should mean "true if the signs are the same" (in the sense of
>> >> negative and non-negative.)
>> >>
>> >> If some hardware had a faster way to compare the signs of two
>> >> floating point numbers, would the compiler be allowed to use it? Or
>> >> does it have to do the multiply, risking overflow, underflow and
>whatever
>> >> else can go bump in the night?
>> >
>> >
>> >It has to do multiply. If the operation fa * fb causes overflow
>> >which throws, then not doing multiply and comparing signs instead
>> >would have different side effect than, say fa * fb >= 1. That
>> >is unacceptable, I think.
>>
>> Floating point error detection & error handling is not part of
>> the standard.
>>
>> AFAICS the compiler is not constrained by the standard in this case.
>
>I think that this is more an issue of what the programmer would expect the
>compiler to do. Given the test (fa * fb >= x), where x != 0, the compiler
>must:
>
> multiply fa and fb (may trigger an implementation-dependent trap)
> compare the result to x (may trigger an implementation-dependent trap)
> set the result of the test to either true or false
>
>Can you see any reason why the compiler should behave differently in the
>case x == 0?
Yes.
The optimization in this discussion has been: instead of multipliying,
check the signs of fa and fb.
I think it's mostly a hypothetical issue, but as the OP said, *if*...
>Granted, the compiler may be able to behave "as if" the multiplication were
>performed rather than actually performing the multiplication, but all of the
>implementation-dependent side-effects should occur as well!
If by "should" you mean "should according to the standard", then no, all of the
implementation-dependent side-effect for the original expression need to
occur for an optimization, so far as the standard is concerned.
In particular, side-effects due to behavior (e.g., overflow) that is undefined
according to the standard, need not occur. Because with undefined behavior
the compiler is free to invoke *any* behavior. This includes fp traps.
It's another matter whether a new version of the standard should address
that issue in some way.
Cheers,
- Alf
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: agriff@tin.it (Andrea Griffini)
Date: Tue, 12 Nov 2002 21:25:24 +0000 (UTC) Raw View
On Tue, 12 Nov 2002 07:48:06 +0000 (UTC), nagle@animats.com (John
Nagle) wrote:
>For the next go-round of the standard, I'd suggest that
>if the implementation's floating point complies with the
>IEEE standard, the semantics of floating point, as seen
>from C++, should be defined. This means talking about
>NaN, INF, rounding modes, etc. in a standardized way.
>Right now, access to those features is implementation
>dependent, which is annoying for number-crunching work.
Please... don't make a*b slower just to make it
mathematically worse unless for who *specifically*
asks for that. Floating point operations and
representation IMO should be as natural as possible
for the underlying architecture. This is I think the
spirit of having "int" of being of unspecified size...
and I think it's a nice approach if you want C/C++
usable for most environments.
> This issue probably should be referred over to
>the ANSI C numerics people, and C++ should follow
>whatever they do.
I've the impression that in a committee the decisions
rarely tends being based on just the actual technical
merit. Before invoking a committee on something I think
one should always read ten times how the endian-ness
problem was "solved" for TIFF files (trying not to
laugh at it).
Andrea
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: pfefferd@hotmail.co.il ("Daniel Pfeffer")
Date: Wed, 13 Nov 2002 09:42:04 +0000 (UTC) Raw View
""Anders J. Munch"" <andersjm@dancontrol.dk> wrote in message
news:3dd0ce82$0$2578$edfadb0f@dread12.news.tele.dk...
[snip]
> I'd hate for an implementation to be 100% IEEE-compliant. The idea
> that there may exist values of x and y such that (x==x) == false and
> (x==y) != !(x!=y) is an abomination to me. It's much easier to write
> algorithms if you can assume that all legal values form a total
> ordering. As an illustration, note that std::map<float,T> has
> undefined behaviour if float is IEEE-compliant.
You are technically correct that std::map<float,T> would have undefined
behaviour for IEEE NaNs. However, std::map<> uses exact comparisons in order
to find the key. As you are no doubt aware, making exact comparisons between
floating-point values is not a good idea. I therefore doubt that this case
would come up in well-written production code.
Personally, I find NaNs to be useful error indicators. They help track down
many types of problems from uninitialised variables to invalid mathematical
operations such as sqrt(-1), giving an indication that all is not kosher
with the calculation. I am, in fact, adapting a software-only version of the
IEEE 754 Standard so that (with help from some typedefs) it will provide a
replacement for my compiler's 'float', 'double' and 'long double' types and
give me expanded diagnostic abilities.
Daniel Pfeffer
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Wed, 13 Nov 2002 17:20:46 +0000 (UTC) Raw View
""Daniel Pfeffer"" <pfefferd@hotmail.co.il> wrote:
> ""Anders J. Munch"" <andersjm@dancontrol.dk> wrote:
>
> [snip]
>
> > I'd hate for an implementation to be 100% IEEE-compliant. The idea
> > that there may exist values of x and y such that (x==x) == false and
> > (x==y) != !(x!=y) is an abomination to me. It's much easier to write
> > algorithms if you can assume that all legal values form a total
> > ordering. As an illustration, note that std::map<float,T> has
> > undefined behaviour if float is IEEE-compliant.
>
> You are technically correct that std::map<float,T> would have undefined
> behaviour for IEEE NaNs. However, std::map<> uses exact comparisons in
order
> to find the key. As you are no doubt aware, making exact comparisons
between
> floating-point values is not a good idea. I therefore doubt that this case
> would come up in well-written production code.
Examples where std::map<float,T> could be useful:
- Caching the result of a lengthy calculation.
- Sorting.
std::map uses <= (or < or std::less, I forget), which *is* a good idea
for floating point (otherwise you couldn't sort numbers); I assumed it
had the same problem, but I checked and it seems that < and <= are
required to raise some kind of exception; what exactly raising an IEC
561 exception means in a C++ program I don't know.
As for comparison for equality, although the general rule is to avoid
it, there cases where it does make sense. Like seeing if something
has changed:
x = read_parameter_from_init_file("x");
if(x != previous_x)
{
cout << "x parameter has changed; restarting calculation" << endl;
Reset();
previous_x = x;
}
>
> Personally, I find NaNs to be useful error indicators.
Certainly, and I have no objections to 99.9% IEC-561 compliance. You
can add all the special values you like and I won't complain, as long
as you place them in a well-defined place in the ordering.
Basically I just like for == to be an equivalence relation and <= to
be a complete ordering.
- Anders
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Wed, 13 Nov 2002 17:23:29 +0000 (UTC) Raw View
> ""Anders J. Munch"" <andersjm@dancontrol.dk> wrote in message
> news:3dd0ce82$0$2578$edfadb0f@dread12.news.tele.dk...
>>I'd hate for an implementation to be 100% IEEE-compliant. The idea
>>that there may exist values of x and y such that (x==x) == false and
>>(x==y) != !(x!=y) is an abomination to me.
Those aren't always meaningful comparisons.
The idea behind IEEE floating point comparisons is
that some operations are invalid; you can't do them at all.
Comparisons are three-valued, with the possible results being
"true", "false", and "invalid". For example,
"INF+ > INF+" is "invalid". All comparisons with NaNs
are also "invalid".
Unrepresentable numeric results can be handled
with NaN values. But since you can't express
"not a boolean", exceptions are the proper way
to handle invalid comparison results.
The proper mapping of this to C++ is that invalid
comparisons should throw an exception. Interestingly,
this can be made to work on Microsoft x86 platforms; the
CPU makes exceptions look synchronous, and the code
generated is consistent enough about stack management
that a machine-level exception can be turned into a
C++ exception. I use this successfully in a product.
But that's hopeless for machines with non-synchronous
exceptions (MIPS, Alpha, SPARC?).
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Wed, 13 Nov 2002 18:35:07 +0000 (UTC) Raw View
pfefferd@hotmail.co.il ("Daniel Pfeffer") writes:
| ""Anders J. Munch"" <andersjm@dancontrol.dk> wrote in message
| news:3dd0ce82$0$2578$edfadb0f@dread12.news.tele.dk...
|
| [snip]
|
| > I'd hate for an implementation to be 100% IEEE-compliant. The idea
| > that there may exist values of x and y such that (x==x) == false and
| > (x==y) != !(x!=y) is an abomination to me. It's much easier to write
| > algorithms if you can assume that all legal values form a total
| > ordering. As an illustration, note that std::map<float,T> has
| > undefined behaviour if float is IEEE-compliant.
|
| You are technically correct that std::map<float,T> would have undefined
| behaviour for IEEE NaNs. However, std::map<> uses exact comparisons in order
| to find the key. As you are no doubt aware, making exact comparisons between
| floating-point values is not a good idea.
There is a difference between not being a "good idea" according to
someelse's own idea of what "good" should mean and invoking an
undefined behaviour.
And == on floating point does make sense for the *intended* use. And
when the sampling points are sufficently isolated, it does make sense
to use == to key values, depending on the application.
--
Gabriel Dos Reis, gdr@integrable-solutions.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]