473,405 Members | 2,282 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

max(NaN,0) should be NaN

After tracking down a bug in my Fortran program, I found that it
assumed
max(NaN,0.) = 0.

This makes no sense, as the outcome of the operation is undefined and
should be NaN.
max(NaN,0.) = NaN

After researching, it appears the first outcome is accepted behavior,
and might be included in the revised IEEE 754 standard, which affects
not only Fortran. The discussion posted at
http://www.cs.berkeley.edu/~ejr/Proj...21.html#minmax
suggests that "There is no mathematical reason to prefer one reason to
another."

But I think otherwise, for the following reason. Suppose the NaN is
produced by x/y, where x=0 came from an underflow and y=0 came from an
underflow. Then x/y would be a well-defined number that could be
postive or negative. The convetion max(NaN,0.) = 0. is wrong at least
half the time.

Aug 28 '06 #1
61 8564
<no***@yahoo.comwrote in message
news:11*********************@m73g2000cwd.googlegro ups.com...
After tracking down a bug in my Fortran program, I found that it
assumed
max(NaN,0.) = 0.

This makes no sense, as the outcome of the operation is undefined and
should be NaN.
max(NaN,0.) = NaN

After researching, it appears the first outcome is accepted behavior,
and might be included in the revised IEEE 754 standard, which affects
not only Fortran. The discussion posted at
http://www.cs.berkeley.edu/~ejr/Proj...21.html#minmax
suggests that "There is no mathematical reason to prefer one reason to
another."

But I think otherwise, for the following reason. Suppose the NaN is
produced by x/y, where x=0 came from an underflow and y=0 came from an
underflow. Then x/y would be a well-defined number that could be
postive or negative. The convetion max(NaN,0.) = 0. is wrong at least
half the time.
I agree with you, but unfortunately there's a school of thought that
*sometimes* NaN means "no candidate value". By this logic, the maximum
of two or more values simply omits NaNs as contenders. Yuk.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Aug 28 '06 #2
In article <11*********************@m73g2000cwd.googlegroups. com>,
no***@yahoo.com writes:
This makes no sense, as the outcome of the operation is undefined and
should be NaN.
max(NaN,0.) = NaN
Why?
After researching, it appears the first outcome is accepted behavior,
and might be included in the revised IEEE 754 standard, which affects
not only Fortran. The discussion posted at
http://www.cs.berkeley.edu/~ejr/Proj...21.html#minmax
suggests that "There is no mathematical reason to prefer one reason to
another."
Don't take this the wrong way. But, the members of the IEEE754
committee probably have much more experience than you (and
many of the people here in c.l.f) in floating point mathematics.
If they came to the conclusion that

"There is no mathematical reason to prefer one reason to another."

then you may want to pay attention to them, and guard against
suspect comparisons.
But I think otherwise, for the following reason. Suppose the NaN is
produced by x/y, where x=0 came from an underflow and y=0 came from an
underflow. Then x/y would be a well-defined number that could be
postive or negative. The convetion max(NaN,0.) = 0. is wrong at least
half the time.
AFAIK, Fortran does not have hysteresis. It does not know
or care how you got to x = 0 and y = 0. All it tries to
do is evaluate x/y. This is a NaN.

--
Steve
http://troutmask.apl.washington.edu/~kargl/
Aug 28 '06 #3
Hello,

Steven G. Kargl wrote:

<snip>
AFAIK, Fortran does not have hysteresis. It does not know
or care how you got to x = 0 and y = 0. All it tries to
do is evaluate x/y. This is a NaN.
Note that this is true, *even if the x/y were an argument
of the max()*.

The compiler must evaluate the values of the arguments,
next associate the values with the dummy arguments,
next call the function.

"History is just one damn thing after another." :-)

--
Cheers!

Dan Nagle
Purple Sage Computing Solutions, Inc.
Aug 28 '06 #4

no***@yahoo.com wrote:
After tracking down a bug in my Fortran program, I found that it
assumed
max(NaN,0.) = 0.

This makes no sense, as the outcome of the operation is undefined and
should be NaN.
max(NaN,0.) = NaN
A standard-conforming Fortran processor is allowed to evaluate
max(x,y) as

if(x y) then
max = x
else
max = y
endif

If x is NaN, then x y is unordered (i.e., it is not true in IEEE
arithmetic).
The ELSE branch is taken, so max(NaN,0.0) = 0.0.

--Eric

Aug 28 '06 #5
no***@yahoo.com wrote:
After tracking down a bug in my Fortran program, I found that it
assumed
max(NaN,0.) = 0.

This makes no sense, as the outcome of the operation is undefined and
should be NaN.
max(NaN,0.) = NaN

After researching, it appears the first outcome is accepted behavior,
and might be included in the revised IEEE 754 standard, which affects
not only Fortran. The discussion posted at
http://www.cs.berkeley.edu/~ejr/Proj...21.html#minmax
suggests that "There is no mathematical reason to prefer one reason to
another."
On a somewhat related question, a colleague and I have observed
evaluation of MAXVAL() or MINVAL() where certain versions of certain
compiler libraries ignore all array elements up to and including the
last NaN, while other libraries simply ignore all NaN values. We have
never observed NaN as a result. We haven't gathered visible support for
our request that a consistent position should be taken.
Aug 28 '06 #6
In article <11*********************@m73g2000cwd.googlegroups. com>,
no***@yahoo.com wrote:
The convetion max(NaN,0.) = 0. is wrong at least
half the time.
But by your argument, the convention Max(NaN,0.)=NaN would be wrong
the other half. That is probably why they concluded

"There is no mathematical reason to prefer one reason to another."

$.02 -Ron Shepard
Aug 28 '06 #7
Ron Shepard wrote:
In article <11*********************@m73g2000cwd.googlegroups. com>,
no***@yahoo.com wrote:
The convetion max(NaN,0.) = 0. is wrong at least
half the time.

But by your argument, the convention Max(NaN,0.)=NaN would be wrong
the other half.
Of course, NaN could always be a well-defined value, just as Inf can be
produced by an overflow of a finite number. Inf can represent a finite
number too large to fit in the exponent field (an inexact infinity so
to speak); NaN can represent any value, only the computer wasn't able
to figure out which one (an inexact NaN). Its meaning is not
restricted to being "not a real number", because it often results from
a combination of underflows and overflows that do not necessarily
correspond to exact zeros and exact infinities. In this sense,
max(NaN,0.) = NaN is always correct. Indeed, max(NaN,0.) is
occasionally correct. On the same basis one could suggest the sign of
NaN be negative, because this is occasionally correct.

Aug 28 '06 #8
After researching, it appears the first outcome is accepted behavior,
and might be included in the revised IEEE 754 standard, which affects
not only Fortran. The discussion posted at
http://www.cs.berkeley.edu/~ejr/Proj...21.html#minmax
suggests that "There is no mathematical reason to prefer one reason to
another."
From the above minutes:
--------------------------------------------
Kahan proposed two mathematical characterizations for max over the
reals plus points at +/-inf which can be extended to NaNs:

1. z := Max{x, y} iff z <= x or z <= y
2. z := Max{x, y} iff z >= x and z >= y

Using the first definition, Max{5, NaN} = 5. Under the second
definition, Max{5, NaN} = NaN. There is no mathematical reason to
prefer one reason to another.
---------------------------------------------
I don't understand 1. - doesn't look like a correct Max definition to
me (even if the missing "z belongs to {x,y}" is added).

Jaroslav

Aug 28 '06 #9
In article <11*********************@m79g2000cwm.googlegroups. com>,
ej*****@yahoo.com says...
[...]
A standard-conforming Fortran processor is allowed to evaluate
max(x,y) as

if(x y) then
max = x
else
max = y
endif

If x is NaN, then x y is unordered (i.e., it is not true in IEEE
arithmetic).
The ELSE branch is taken, so max(NaN,0.0) = 0.0.
Is that how max is defined by the standard? if not, if your
processor instead evaluates max(x,y) as

if(x < y) then
max = y
else
max = x
endif

the else-branch is still taken and now max(NaN,0.0) = NaN.
In this case your argument is in support of both results,
rendering the argument void.

--
Christer Ericson
http://realtimecollisiondetection.net/
Aug 28 '06 #10
>>A standard-conforming Fortran processor is allowed to evaluate
>>max(x,y) as

if(x y) then
max = x
else
max = y
endif

If x is NaN, then x y is unordered (i.e., it is not true in IEEE
arithmetic).
The ELSE branch is taken, so max(NaN,0.0) = 0.0.

Is that how max is defined by the standard? if not, if your
processor instead evaluates max(x,y) as

if(x < y) then
max = y
else
max = x
endif

the else-branch is still taken and now max(NaN,0.0) = NaN.
In this case your argument is in support of both results,
rendering the argument void.
And in any case, changing the order of the arguments would change the
result, in both cases. I do think it's imperative that max(a,b)==max(b,a).

Jan

Aug 28 '06 #11
And in any case, changing the order of the arguments would change the
result, in both cases. I do think it's imperative that max(a,b)==max(b,a).
Why? Other operations that are mathematically commutative lose this
property in floating point.

Aug 28 '06 #12
>>And in any case, changing the order of the arguments would change the
>>result, in both cases. I do think it's imperative that max(a,b)==max(b,a).

Why? Other operations that are mathematically commutative lose this
property in floating point.
Which ones do? Associativity - yes, I see that. But commutation?

Jan
Aug 28 '06 #13
no***@yahoo.com wrote:
After tracking down a bug in my Fortran program, I found that it
assumed
max(NaN,0.) = 0.

This makes no sense, as the outcome of the operation is undefined and
should be NaN.
max(NaN,0.) = NaN

After researching, it appears the first outcome is accepted behavior,
and might be included in the revised IEEE 754 standard, which affects
not only Fortran. The discussion posted at
http://www.cs.berkeley.edu/~ejr/Proj...21.html#minmax
suggests that "There is no mathematical reason to prefer one reason to
another."

But I think otherwise, for the following reason. Suppose the NaN is
produced by x/y, where x=0 came from an underflow and y=0 came from an
underflow. Then x/y would be a well-defined number that could be
postive or negative. The convetion max(NaN,0.) = 0. is wrong at least
half the time.
For what it's worth, the C standard makes it clear that fmax should
produce 0 in this case.

In the footnote to 7.12.12.2:
"NaN arguments are treated as missing data: if one argument is a NaN and
the other numeric, then the fmax functions choose the numeric value. See
F.9.9.2."

Normative appendix F.9.9.2 says, of implementations that define
__STDC_IEC_559__,
"If just one argument is a NaN, the fmax functions return the other
argument (if both arguments are NaNs, the functions return a NaN)."

--
Simon.

--
Posted via a free Usenet account from http://www.teranews.com

Aug 28 '06 #14
Which ones do? Associativity - yes, I see that. But commutation?
OK, I cannot state this for sure, as I don't have access to the IEEE
standard,
but I was under the impression (perhaps until now you correct me) that,
if _mathematically_
a+b == (c + nearest(c,+1.))/2,
then you can have in FP
a+b == c
b+a == nearest(c,+1.)

and that more possibilities are allowed with more complex expressions
as a*b + c*d /= c*d + a*b

Jaroslav

Aug 28 '06 #15
Jan Vorbrüggen wrote:
And in any case, changing the order of the arguments would change the
result, in both cases. I do think it's imperative that max(a,b)==max(b,a).
I agree that this is a good idea, acording to 'the principle of least
astonishment', but the problem here is that NaNs already break this in
various ways. I.e. they are defined (afair) to compare false against any
real number, which does mean that _both_

if (a NaN) {}

and

if (a <= NaN) {}

should be false, i.e. as soon as you allow NaNs the normal rules for
logical operations break down completely. :-(

At least on x86/x87 hardware any comparison against NaN will return
'UNORDERED', which is distinct from the set of 'greater_than', 'equal',
'less_than'.

Terje
--
- <Te************@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"
Aug 28 '06 #16
I agree that this is a good idea, acording to 'the principle of least
astonishment', but the problem here is that NaNs already break this in
various ways. I.e. they are defined (afair) to compare false against any
real number, which does mean that _both_

if (a NaN) {}

and

if (a <= NaN) {}

should be false, i.e. as soon as you allow NaNs the normal rules for
logical operations break down completely. :-(
No, no - you forgot to check for orderability beforehand. You wouldn't
expect this to work for, e.g., spinors (not to mention complex numbers),
would you?
At least on x86/x87 hardware any comparison against NaN will return
'UNORDERED', which is distinct from the set of 'greater_than', 'equal',
'less_than'.
And that is as it should be!

Jan
Aug 28 '06 #17
OK, I cannot state this for sure, as I don't have access to the IEEE
standard,
but I was under the impression (perhaps until now you correct me) that,
if _mathematically_
a+b == (c + nearest(c,+1.))/2,
then you can have in FP
a+b == c
b+a == nearest(c,+1.)
I don't see anything in the algorithmic description of floating-point addition
that allows this kind of asymmetry. You shift the mantissas based on the
difference in exponent towards the larger value, add, and renormalize. All
of these operations are symmetrical in the operands.

Jan
Aug 28 '06 #18
In article <4l************@individual.net=?ISO-8859-1?Q?Jan_Vorbr=FCggen?= <jv**********@not-mediasec.dewrites:
....
I don't see anything in the algorithmic description of floating-point
addition that allows this kind of asymmetry. You shift the mantissas
based on the difference in exponent towards the larger value, add, and
renormalize. All of these operations are symmetrical in the operands.
On the CDC Cyber 205, in a vector add the second operand was shifted
so that the exponents became equal. If a right shift, the shifted off
bits were lost, on a left shift everything was retained. And if the
left shift was too large, a short-cut was made. On tht machine, with
those operations, addition was not commutative.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Aug 28 '06 #19
Dik T. Winter <Di********@cwi.nlwrote:
On the CDC Cyber 205,... On tht machine, with
those operations, addition was not commutative.
Though I'd personally characterize the philosophy of the CDC machines of
that era as being that speed was more important than the last few bits
of accuracy. They counted on the 60-bit word to be enough to make up for
being "sloppy" about the last few bits.

I can't tell precisely what environment some posters in the thread are
talking about. I suspect different posters are talking about different
things without specifying so, which gets confusing. Some posters have
mentioned the IEEE standard, while others appear to be talking in more
general terms about any floating point implementation or about the
requirements of the Fortran (or C?) standard. I'm afraid that I can't
follow the result because I'm unsure what unstated assumptions apply to
each post. I can make guesses, but it is easy to guess incorrectly in
some cases. I'm occasionally left with the impression that some posters
might be a bit vague on the distinction, which might explain why I have
trouble telling exactly what they meant.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Aug 28 '06 #20

In article <ec**********@gnus01.u.washington.edu>,
ka***@troutmask.apl.washington.edu (Steven G. Kargl) writes:
|In article <11*********************@m73g2000cwd.googlegroups. com>,
| no***@yahoo.com writes:
|>
| This makes no sense, as the outcome of the operation is undefined and
| should be NaN.
| max(NaN,0.) = NaN
|>
|Why?
|>
| After researching, it appears the first outcome is accepted behavior,
| and might be included in the revised IEEE 754 standard, which affects
| not only Fortran. The discussion posted at
| http://www.cs.berkeley.edu/~ejr/Proj...21.html#minmax
| suggests that "There is no mathematical reason to prefer one reason to
| another."
|>
|Don't take this the wrong way. But, the members of the IEEE754
|committee probably have much more experience than you (and
|many of the people here in c.l.f) in floating point mathematics.
|If they came to the conclusion that
|>
| "There is no mathematical reason to prefer one reason to another."
|>
|then you may want to pay attention to them, and guard against
|suspect comparisons.

Well, it is unlikely that any of them have more experience than me in
practical numerical software engineering, though I am less than 1% of
the numerical analyst that Kahan is, to give just one example. Note
that I am not saying that some of them don't have comparable experience,
though I can't think of any offhand.

They are quite simply wrong. There IS a very strong mathematical
argument, and the reasons for making that statement are dogmatism, not
science. I give the reasons for the DECISION below, but that is a
consequent matter. It is the reason for making that STATEMENT I am
talking about above.
The background is that traditional design started by creating a fairly
precise mathematical model, and then deriving the operations to fit in
with that model. This maximises the possibilities of reasoning about
the behaviour of the program (e.g. validation, program proving, software
engineering, etc. etc.) at the expense of restricting flexibility.

The alternative approach is to start with the facilities, maximise
them for flexibility, and let the overall model lie where it falls.
This maximises the flexibility of the design, at the cost of making
static validation somewhere between harder and impossible.

One of Kahan's papers points out that IEEE 754 did the latter, and that
it was a deliberate deviation from the traditional approach.
Jumping aside, the need for missing values occurs almost entirely in
vector or other composite operations, and EVERY language that has
supported them needs BOTH semantics. In particular, the requirement
order for the operations in statistics is:

Count non-missing values in vector
Sum non-missing values in vector
Take mininum/maximum of non-missing values in vector
Take product of non-missing values in vector
Derived operations and more esoteric ones

Also, EVERY language needs BOTH semantics, according to context. For
example, in the following:

top = max(max(vector_A,vector_B))

sum should be the maximum of the elements of vector_A and vector_B
where BOTH of a pair are non-missing. Look at any decent book on
statistics or good statistical package for ample evidence.
IEEE 754 NaNs are VERY clearly indications of 'invalid' values (though
even that has several interpretations, but the subtleties are irrelevant
to this). If they were to be treated as missing values, then it is
immediately clear that NaN+1.23 should be 1.23. No ifs or buts.

I have a paper on this somewhere, which I have circulated but not
published, if anyone is interested.
Regards,
Nick Maclaren.
Aug 28 '06 #21

Nick Maclaren wrote:
Jumping aside, the need for missing values occurs almost entirely in
vector or other composite operations, and EVERY language that has
supported them needs BOTH semantics.
Both Fortran 2003 (and C99 and F95 with TR 15581)
provide standard ways to do what you want, assuming that
NaN indicates a missing value. In Fortran's case,
since IEEE_IS_NAN is elemental, you can simply say for
a vector declared REAL X(N):
Count non-missing values in vector
non_missing = count(.not.ieee_is_nan(x))
Sum non-missing values in vector
total = sum(x, mask=.not.ieee_is_nan(x))
(and similarly for PRODUCT)
Take mininum/maximum of non-missing values in vector
biggest = maxval(x, mask=.not.ieee_is_nan(x))
(and similarly for MINVAL)

You're always free to special-case things, as in

if(any(ieee_is_nan(x))) then
result = NaN
else
result = f(x) ! all non-NaN elements in X
endif

You can do the same thing (albeit more verbosely) in C99 with the
analogous library functions.

Some applications will want to silently ignore NaN elements, and
in other cases NaNs indicate serious errors that can be indicated
by NaN result values. Seems to me that the current C and Fortran
language standards offer basic support for both alternatives,
but the onus is on the programmer to anticipate the cases where
NaNs are possible and to take the appropriate action.

Things might get tricky if you're also testing/setting the various IEEE
exception flags or if X contains signaling NaNs. I don't know,
for example, whether using the mask functions above can change
the state of the INVALID flag or if the language standards even
address this issue.

--Eric

Aug 28 '06 #22

In article <11**********************@75g2000cwc.googlegroups. com>,
ej*****@yahoo.com writes:
|>
|Both Fortran 2003 (and C99 and F95 with TR 15581)
|provide standard ways to do what you want, ...
|>
|You can do the same thing (albeit more verbosely) in C99 with the
|analogous library functions.

Don't bet on it :-( Even Fortran doesn't specify what you imply,
and C99's facilities are so badly specified as to be effectively
useless (and even actively harmful).

|Some applications will want to silently ignore NaN elements, and
|in other cases NaNs indicate serious errors that can be indicated
|by NaN result values. Seems to me that the current C and Fortran
|language standards offer basic support for both alternatives,
|but the onus is on the programmer to anticipate the cases where
|NaNs are possible and to take the appropriate action.

Which is precisely what writing robust, portable code (a.k.a. software
engineering) is NOT about!
Regards,
Nick Maclaren.
Aug 29 '06 #23
"Nick Maclaren" <nm**@cus.cam.ac.ukwrote in message
news:ed**********@gemini.csx.cam.ac.uk...
In article <11**********************@75g2000cwc.googlegroups. com>,
ej*****@yahoo.com writes:
|>
|Both Fortran 2003 (and C99 and F95 with TR 15581)
|provide standard ways to do what you want, ...
|>
|You can do the same thing (albeit more verbosely) in C99 with the
|analogous library functions.

Don't bet on it :-( Even Fortran doesn't specify what you imply,
and C99's facilities are so badly specified as to be effectively
useless (and even actively harmful).
Easy on the hyperbole. C99 spells out quite clearly, in F.9.9.2,
that fmax must effectively ignore NaNs. I don't like it, but out
C99 implementation does exactly what's specified in the 1999
C Standard. And our test suite looks for that behavior too.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Aug 29 '06 #24

In article <oK******************************@giganews.com>,
"P.J. Plauger" <pj*@dinkumware.comwrites:
| |>
| |Both Fortran 2003 (and C99 and F95 with TR 15581)
| |provide standard ways to do what you want, ...
| |>
| |You can do the same thing (albeit more verbosely) in C99 with the
| |analogous library functions.
|
| Don't bet on it :-( Even Fortran doesn't specify what you imply,
| and C99's facilities are so badly specified as to be effectively
| useless (and even actively harmful).
|>
|Easy on the hyperbole. C99 spells out quite clearly, in F.9.9.2,
|that fmax must effectively ignore NaNs. I don't like it, but out
|C99 implementation does exactly what's specified in the 1999
|C Standard. And our test suite looks for that behavior too.

No, that's not my point. I agree that THAT is clear.

NaN support and fmax/fmin are in the 'open' (mandatory) sections of the
standard, but footnotes 204/205 refer forward to Annex F. However,
Annex F applies only if an implementation sets __STDC_IEC_559__, and
makes little or no sense on many architectures and with many compiler
options (e.g. VAX/Alpha, zOS, ones with IEEE 754 representation but only
partial semantics, etc.).

And then there is the question of exactly how the "as if" rule and
pragma STDC FP_CONTRACT apply (and the default for THAT may be anything).
The only compiler that I have used that supported C99 Annex F continued
to set __STDC_IEC_559__ even when I specified optimisation options that
affect the numeric results (which is forbidden by IEEE 754). So a lot
of code will have __STDC_IEC_559__, but NOT the semantics it expects.

If, however, the compiler DIDN'T do that, things would be no better.
There is almost nothing in the C99 standard that says what the "IEEE 754"
parts of the standard that are not shielded by __STDC_IEC_559__ (e.g.
<fenv.h>, chunks of <math.hand some others) mean if __STDC_IEC_559__
is not set. As you recall, this issue was raised repeatedly during the
standardisation process.

And, of course, fmax/fmin are among the most clearly specified parts of
C99's IEEE 754 support - many of the other aspects are MUCH less clear,
and the flag handling is unbelievable. But let's skip that, on the grounds
of good taste and public decency.
Regards,
Nick Maclaren.
Aug 30 '06 #25
nm**@cus.cam.ac.uk (Nick Maclaren) wrote:
The background is that traditional design started by creating a fairly
precise mathematical model, and then deriving the operations to fit in
with that model. This maximises the possibilities of reasoning about
the behaviour of the program (e.g. validation, program proving, software
engineering, etc. etc.) at the expense of restricting flexibility.

The alternative approach is to start with the facilities, maximise
them for flexibility, and let the overall model lie where it falls.
This maximises the flexibility of the design, at the cost of making
static validation somewhere between harder and impossible.

One of Kahan's papers points out that IEEE 754 did the latter, and that
it was a deliberate deviation from the traditional approach.
And yet, it was IEEE 754 which gained whitespread usage, and was
officially adopted in at least one, and if I understand this thread
correctly at least two, programming language standards. IYAM, this
demonstrates the gap between computing science in academe and the
practical art of writing programs that are supposed to be used by
humans.

Richard
Aug 30 '06 #26

In article <44****************@news.xs4all.nl>,
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
|nm**@cus.cam.ac.uk (Nick Maclaren) wrote:
|>
| The background is that traditional design started by creating a fairly
| precise mathematical model, and then deriving the operations to fit in
| with that model. This maximises the possibilities of reasoning about
| the behaviour of the program (e.g. validation, program proving, software
| engineering, etc. etc.) at the expense of restricting flexibility.
|
| The alternative approach is to start with the facilities, maximise
| them for flexibility, and let the overall model lie where it falls.
| This maximises the flexibility of the design, at the cost of making
| static validation somewhere between harder and impossible.
|
| One of Kahan's papers points out that IEEE 754 did the latter, and that
| it was a deliberate deviation from the traditional approach.
|>
|And yet, it was IEEE 754 which gained whitespread usage, and was
|officially adopted in at least one, and if I understand this thread
|correctly at least two, programming language standards. IYAM, this
|demonstrates the gap between computing science in academe and the
|practical art of writing programs that are supposed to be used by
|humans.

You have made at least three major errors in that, I am afraid.

Firstly, I am older and more experienced than that, and am referring
to the days before the rise of computing science in academia. The
traditional design I referred to was and is used by practical software
engineers (though we weren't called that, then). Yeah, I know that
we are now an engandered species :-(

Secondly, IEEE 754 has NOT gained widespread acceptance, and almost all
"IEEE 754" systems use its format and not its semantics, or go in for
some simplification or variant of it. Many or most don't support
denormalised numbers or exceptions (as it specifies them) in some of
their modes (often their defaults), and some older and embedded systems
didn't/don't support NaNs or infinities.

Thirdly, only Java has attempted to include it as part of its specification,
and Kahan has written a diatribe against Java. C99 has some support, but
words fail me when describing how unusable it is. Fortran makes gestures,
but the 'support' is minimal, to put it mildly.

IEEE 754R is still in denial about the reasons for the near-total uptake
in programming languages (after 22 years!) and the people STILL believe
that it is due to inertia. No way, Jose.
Regards,
Nick Maclaren.
Aug 30 '06 #27
"Nick Maclaren" <nm**@cus.cam.ac.ukwrote in message
news:ed**********@gemini.csx.cam.ac.uk...
Secondly, IEEE 754 has NOT gained widespread acceptance, and almost all
"IEEE 754" systems use its format and not its semantics, or go in for
some simplification or variant of it.
You could say the same thing about Standard C, if you're sufficiently
vague about degree of conformance. The fact is that *most* architectures
in widespread use support a pretty good approximation to IEEE 754. If
you want to savor all the small ways they don't quite conform, then ask
Fred Tydeman to give you his list of grievances. But in real life they
hardly matter to the practicing programmer.
Many or most don't support
denormalised numbers
I called you on this in Berlin and you temporized. The statement
IME is simply untrue. And ME involves supporting Standard C99 and
C++ libraries on about a dozen popular architectures, with about
as many floating-point processors.
or exceptions (as it specifies them)
I guess the parenthetic quibble gives you some wiggle room, but
I still have trouble with it. Our fenv.h tests seem to indicate
that the popular architectures *do* meet the requirements of
IEEE 754 in this area.
in some of
their modes (often their defaults),
Another potential quibble, which I still have trouble believing,
from direct experience.
and some older and embedded systems
didn't/don't support NaNs or infinities.
Now that's true. My former company Whitesmiths, Ltd. provided software
floating-point packages that blew off denormals, infinities, and NaNs,
with no complaints from our customers. But the last packages we shipped
went out the door in 1988. Since then, both hardware and software have
learned to take IEEE 754 a bit more seriously. My book "The Standard C
Library" worried considerably about infinities and NaNs back in 1992.
It looks pretty naive to me now, in many ways, but it got things mostly
right. And IMO it reflected the spirit of the times.
Thirdly, only Java has attempted to include it as part of its
specification,
and Kahan has written a diatribe against Java.
IIRC, the diatribe did *not* complain that Java slavishly followed
IEEE 754 to its detriment. There was this little thing about favoring
Sun architecture over Intel, then patching thing up in a half-assed
manner...
C99 has some support, but
words fail me when describing how unusable it is.
The detailed words always seem to fail you, but you're consistently
quick with the poisonous adjectives. In fact, C99 has two extensive
annexes (F and G) describing in exquisite detail how IEEE 754 and
Standard C should play together. My current company Dinkumware, Ltd.
has endeavored to conform completely to those annexes, and aside
from a few aggressively perverse tests in Tydeman's floating-point
suite we do just fine. While I don't always agree with some of the
more creative choices made in those annexes (particularly G), I had
little trouble following their guidance. Hence, I have to disagree
that C99 support for IEEE 754 is unusable, either to us or our
customers.
Fortran makes gestures,
but the 'support' is minimal, to put it mildly.
I'm glad you're capable of putting something mildly, from time to
time. Now if only you could put some of your jeremiads a bit more
accurately. Or even more precisely, so they're easier to criticize
in detail.
IEEE 754R is still in denial about the reasons for the near-total uptake
in programming languages (after 22 years!) and the people STILL believe
that it is due to inertia. No way, Jose.
From out here, IEEE 754R seems to be suffering more from internecine
warfare than from any denial about their effects on programming
languages. But I'm always willing to cut slack for any war
correspondent. YMMV.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Aug 30 '06 #28
"P.J. Plauger" <pj*@dinkumware.comwrites:
Since then, both hardware and software have learned to take
IEEE 754 a bit more seriously. My book "The Standard C Library"
worried considerably about infinities and NaNs back in 1992.
It looks pretty naive to me now, in many ways, but it got
things mostly right. And IMO it reflected the spirit of the
times.
I'd be gratified if you'd say a few more words about how the
discussion in "The Standard C Library" treats floating-point
arithmetic (or just infinities and NaNs) naively. An important
part of my own understanding of floating-point and IEEE 754 has
come from reading that book, so I'm now wondering how naive I am
;-)
--
"This is a wonderful answer.
It's off-topic, it's incorrect, and it doesn't answer the question."
--Richard Heathfield
Aug 30 '06 #29
"Ben Pfaff" <bl*@cs.stanford.eduwrote in message
news:87************@benpfaff.org...
"P.J. Plauger" <pj*@dinkumware.comwrites:
>Since then, both hardware and software have learned to take
IEEE 754 a bit more seriously. My book "The Standard C Library"
worried considerably about infinities and NaNs back in 1992.
It looks pretty naive to me now, in many ways, but it got
things mostly right. And IMO it reflected the spirit of the
times.

I'd be gratified if you'd say a few more words about how the
discussion in "The Standard C Library" treats floating-point
arithmetic (or just infinities and NaNs) naively. An important
part of my own understanding of floating-point and IEEE 754 has
come from reading that book, so I'm now wondering how naive I am
;-)
Well, the topic of this thread is one example. I assumed that NaN
always meant, "Abandon hope, all meaning is lost." The idea never
occurred to me that it might simply mean, "Pay no attention to me,
just go compute a useful value from other arguments." (And I still
have trouble with that viewpoint.)

Similarly, I always took Inf to mean "unbounded". But C99 actually
expects you to compute many different angles for atan2, as if two
Inf values were usefully taken as equal sides of a triangle. (And
I still have trouble with that viewpoint.)

I was unaware of several of the subtle requirements of IEEE 754,
particularly regarding domain vs. range errors and Inf vs. NaN
return values at mathematical singularities.

The code I presented in that book often botched denormal arguments.
It's all too easy to blow away those tiny values by mixing them
unnecessarily with other values.

The code was also intentionally cavailer about preserving, and
generating, -0 results. (And I still think that -0 is of dubious
value.)

All I had back then were the Elefunt tests, which I translated
painfully from Fortran. With the much better testing technology
we've developed in Dinkumware, we've cleaned up quite a few
spots where we lost accuracy. We also eliminated a few spots
where we were trying too hard, to no avail.

Finally, our work in Dinkumware on the special math functions
drove home the importance of sensitivity, both in determining
how hard an implementer should try to get exactly the right
result and in how much a user should trust numeric
approximations to functions in their sensitive regions.

That's all.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Aug 30 '06 #30
In comp.lang.fortran P.J. Plauger <pj*@dinkumware.comwrote:
(snip)
Well, the topic of this thread is one example. I assumed that NaN
always meant, "Abandon hope, all meaning is lost." The idea never
occurred to me that it might simply mean, "Pay no attention to me,
just go compute a useful value from other arguments." (And I still
have trouble with that viewpoint.)
The R language, mostly used for statistics work, has both NA and NaN.
NA when you don't know anything about the value, often used
in input data where no data exists. NaN usually as the result
of computations.

I believe the distiction could also make sense in other languages,
though I don't expect it to appear anytime soon.

-- glen

Aug 30 '06 #31
P.J. Plauger wrote:
"Nick Maclaren" <nm**@cus.cam.ac.ukwrote in message
news:ed**********@gemini.csx.cam.ac.uk...
....
> or exceptions (as it specifies them)

I guess the parenthetic quibble gives you some wiggle room, but
I still have trouble with it. Our fenv.h tests seem to indicate
that the popular architectures *do* meet the requirements of
IEEE 754 in this area.
I suppose you could regard trap handlers as part of "IEEE exceptions".
I've never seen an implementation of IEEE traps.

--
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare
Aug 31 '06 #32
P.J. Plauger wrote:
[...]

The code was also intentionally cavailer about preserving, and
generating, -0 results. (And I still think that -0 is of dubious
value.)
I hesitate to stick my head up in such august company, being so
nonaugust, but I was impressed by how easy it was to replicate
Kahan's Borda's mouthpiece example in C99-based ANS Forth
implementations (pfe and gforth) of complex mathematics:

http://www-personal.umich.edu/~willi...lex/borda.html

And furthermore how easy it was to get the right answers
generally for the complex elementary functions above and below
their principal value branch cuts:

http://www-personal.umich.edu/~willi...x-ieee-test.fs

The link just above is not comprehensible outside of a niche of
a niche. :-)

-- David
Aug 31 '06 #33

In article <cI*****************@newssvr13.news.prodigy.com> ,
"David N. Williams" <wi******@umich.eduwrites:
|P.J. Plauger wrote:
| >
| The code was also intentionally cavailer about preserving, and
| generating, -0 results. (And I still think that -0 is of dubious
| value.)
|>
|I hesitate to stick my head up in such august company, being so
|nonaugust, ...

Don't worry - as in politics, it is often the least august people who
see most clearly.

|but I was impressed by how easy it was to replicate
|Kahan's Borda's mouthpiece example in C99-based ANS Forth
|implementations (pfe and gforth) of complex mathematics:
|>
|http://www-personal.umich.edu/~willi...lex/borda.html
|>
|And furthermore how easy it was to get the right answers
|generally for the complex elementary functions above and below
|their principal value branch cuts:
|>
|http://www-personal.umich.edu/~willi...x-ieee-test.fs

Well, yes, but one of the questions is whether that is useful. Now, I
quite agree that a numerical analyst as good as Kahan can use branch
cut information directly in real applications, and I date from the days
when we were taught to do so (though I doubt that I still can), but I
know of nobody under 45 who can.

My experience is that Bill Plauger is understating the case - the IEEE 754
handling of zeroes (and hence infinities) causes a huge number of errors
that would not have occurred in older arithmetics. People REALLY don't
expect the "gotchas" it introduces - and C99 makes that a lot worse.

|The link just above is not comprehensible outside of a niche of
|a niche. :-)

Very true. In a related niche, I have a simple test that shows up the
chaos with C99's complex division and overflow. It really is VERY
nasty :-(
Regards,
Nick Maclaren.
Aug 31 '06 #34

In article <Q9******************@bgtnsc04-news.ops.worldnet.att.net>,
"James Giles" <ja********@worldnet.att.netwrites:
|>
|I suppose you could regard trap handlers as part of "IEEE exceptions".
|I've never seen an implementation of IEEE traps.

I have. I have even tested them. They didn't work, because few (if
any) modern systems support interrupt recovery by user code properly.
However, Plauger has mangled what I said so appallingly that I hope
that you don't think that I said what he implied I said.

What I said was:

Many or most don't support denormalised numbers or exceptions
(as it specifies them) in some of their modes (often their defaults),
and some older and embedded systems didn't/don't support NaNs or
infinities.

That statement is true and I stand by it. I did not say that any
modern general-purpose desktop and server systems don't support
IEEE 754 at all[*], though many do not support C99 - for good reasons,
including customer demand.

[*] zOS supports only a subset - see:

http://www-306.ibm.com/software/awdtools/czos/features/
Regards,
Nick Maclaren.
Aug 31 '06 #35

In article <hO******************************@giganews.com>,
"P.J. Plauger" <pj*@dinkumware.comwrites:
|>
| Secondly, IEEE 754 has NOT gained widespread acceptance, and almost all
| "IEEE 754" systems use its format and not its semantics, or go in for
| some simplification or variant of it.
|>
|You could say the same thing about Standard C, if you're sufficiently
|vague about degree of conformance. The fact is that *most* architectures
|in widespread use support a pretty good approximation to IEEE 754. If
|you want to savor all the small ways they don't quite conform, then ask
|Fred Tydeman to give you his list of grievances. But in real life they
|hardly matter to the practicing programmer.

You cannot now say the same about C90, though you could up to about 1995.
You can, indeed, say the same about C99 - and a large part of the reason
for that is customer demand for C90 (for very good reasons).

Unfortunately, they do matter very much to anyone who is attempting to
write robust, portable code or is in the position of assisting users
who develop on one system and then find that their code doesn't work
on another. I have considerable experience with both.

| Many or most don't support
| denormalised numbers
|>
|I called you on this in Berlin and you temporized. The statement
|IME is simply untrue. And ME involves supporting Standard C99 and
|C++ libraries on about a dozen popular architectures, with about
|as many floating-point processors.

That is a falsehood. As you have done here, you quoted me out of
context, completely changing the meaning of what I said to something
that I did not say and was false, and I was not given a chance to
respond by the chairman. I wondered whether to object on a point
of order, but that seemed excessive.

| or exceptions (as it specifies them)
|>
|I guess the parenthetic quibble gives you some wiggle room, but
|I still have trouble with it. Our fenv.h tests seem to indicate
|that the popular architectures *do* meet the requirements of
|IEEE 754 in this area.
|>
| in some of
| their modes (often their defaults),
|>
|Another potential quibble, which I still have trouble believing,
|from direct experience.

For heaven's sake! Quoting individual phrases (not even clauses!) out
of context is a low political trick. I have requoted the full sentence
in another posting, and shall not do so here.

My statement was, however, based on detailed investigations of four
Unices on 4 totally separate architectures, and brief ones on a fair
number of others. In particular, it is true for at least AIX, IRIX
Solaris and Linux/gcc.

| Thirdly, only Java has attempted to include it as part of its
| specification,
| and Kahan has written a diatribe against Java.
|>
|IIRC, the diatribe did *not* complain that Java slavishly followed
|IEEE 754 to its detriment. There was this little thing about favoring
|Sun architecture over Intel, then patching thing up in a half-assed
|manner...

Yes, and there was a much larger thing about how it was essential to
provide both the flags and the values in order to get reliable exception
handling.

| C99 has some support, but
| words fail me when describing how unusable it is.
|>
|The detailed words always seem to fail you, but you're consistently
|quick with the poisonous adjectives.

As you know, that is another falsehood. I wrote a great many detailed
descriptions of the problems for the SC22WG14 reflector, often including
solutions, and some of them were raised by the BSI as official National
Body comments. All were either ignored or responded to entirely by
ad hominem attacks, as you are doing here.

I have a fair number of very detailed documents describing the issues,
and often solutions to the problems, which have been widely circulated.
I posted one to the SC22WG21 list, which you managed to get ignored
without consideration at a meeting at which I was not present, apparently
by claiming that it was false. However, I should point out that I gave
an independent reference that my statements were correct (Python).

[ To anyone else: please Email me if you want copies, and tell me
what aspects you are interested in. I don't guarantee to be able to
find everything! ]

|In fact, C99 has two extensive
|annexes (F and G) describing in exquisite detail how IEEE 754 and
|Standard C should play together.

Well, no, and that was one of the reasons that the BSI voted "no"
to C99 and many customers have explicitly specified C90. As I gave
enough reasons in a previous response in this thread, I shan't repeat
them.

|My current company Dinkumware, Ltd.
|has endeavored to conform completely to those annexes, and aside
|from a few aggressively perverse tests in Tydeman's floating-point
|suite we do just fine. While I don't always agree with some of the
|more creative choices made in those annexes (particularly G), I had
|little trouble following their guidance. Hence, I have to disagree
|that C99 support for IEEE 754 is unusable, either to us or our
|customers.

There is a difference between "unimplementable" and "unusable". I
never said that Annex F or G were unimplementable on systems with
hardware that supports IEEE 754 in at least one mode. They are
unusable for real applications that need robustness, portability
and efficiency (and, to some extent, any of those).

Enough, already. I am not going to respond to your attacks further.
If you ask me to justify what I have actually said, I may respond, but
that is unlikely if you misquote to the above extent.
Regards,
Nick Maclaren.
Aug 31 '06 #36
nm**@cus.cam.ac.uk (Nick Maclaren) writes:
[...]
Very true. In a related niche, I have a simple test that shows up the
chaos with C99's complex division and overflow. It really is VERY
nasty :-(
Can you post it, or a link to it if it's too large? I think a lot of
comp.lang.c folks would be interested (not sure about
comp.lang.fortran).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 31 '06 #37
"Nick Maclaren" <nm**@cus.cam.ac.ukwrote in message
news:ed**********@gemini.csx.cam.ac.uk...
...
|I called you on this in Berlin and you temporized. The statement
|IME is simply untrue. And ME involves supporting Standard C99 and
|C++ libraries on about a dozen popular architectures, with about
|as many floating-point processors.

That is a falsehood.
That's one.
...
As you have done here, you quoted me out of
context, completely changing the meaning of what I said to something
that I did not say and was false, and I was not given a chance to
respond by the chairman. I wondered whether to object on a point
of order, but that seemed excessive.
You're responding now, by questioning my integrity and motives.
...
|Another potential quibble, which I still have trouble believing,
|from direct experience.

For heaven's sake! Quoting individual phrases (not even clauses!) out
of context is a low political trick.
That's two.
...
| C99 has some support,
but
| words fail me when describing how unusable it is.
|>
|The detailed words always seem to fail you, but you're consistently
|quick with the poisonous adjectives.

As you know, that is another falsehood.
That's three strikes, and you're completely out of line. It's one
thing to accuse me of stating falsehoods, and of various other
tricks; it's quite another to say that I deliberately made a false
statement.
...
Enough, already. I am not going to respond to your attacks further.
If you ask me to justify what I have actually said, I may respond, but
that is unlikely if you misquote to the above extent.
Not to worry. The conversation is over.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Aug 31 '06 #38
Nick Maclaren wrote:
In article <cI*****************@newssvr13.news.prodigy.com> ,
"David N. Williams" <wi******@umich.eduwrites:
[...]
|but I was impressed by how easy it was to replicate
|Kahan's Borda's mouthpiece example in C99-based ANS Forth
|implementations (pfe and gforth) of complex mathematics:
|>
|>
http://www-personal.umich.edu/~willi...lex/borda.html
|>
|And furthermore how easy it was to get the right answers
|generally for the complex elementary functions above and below
|their principal value branch cuts:
|>
|>
http://www-personal.umich.edu/~willi...x-ieee-test.fs
>
Well, yes, but one of the questions is whether that is useful. [...]
Indeed!
My experience is that Bill Plauger is understating the case - the
IEEE 754
handling of zeroes (and hence infinities) causes a huge number of errors
that would not have occurred in older arithmetics. People REALLY don't
expect the "gotchas" it introduces - and C99 makes that a lot worse.
I really don't have much experience here.
|The link just above is not comprehensible outside of a niche of
|a niche. :-)

Very true. In a related niche, I have a simple test that shows up the
chaos with C99's complex division and overflow. It really is VERY
nasty :-(
I'd be curious to see it. The stuff I was talking about doesn't
use the C99 complex math library at all, just the underlying
gcc support for IEEE 754.

-- David
Aug 31 '06 #39

In article <U1****************@newssvr25.news.prodigy.net>,
"David N. Williams" <wi******@umich.eduwrites:
| >
| Very true. In a related niche, I have a simple test that shows up the
| chaos with C99's complex division and overflow. It really is VERY
| nasty :-(
|>
|I'd be curious to see it. The stuff I was talking about doesn't
|use the C99 complex math library at all, just the underlying
|gcc support for IEEE 754.

Mine doesn't, either. Yes, it was designed with malice aforethought,
but I was checking whether the situation was really as bad as a look
at the code indicated it was. It shows what happens if you use the
'native' complex divide, the example in Annex G, or calculate the real
and imaginary parts separately. The results on several systems are
along the lines of:

0.00e+00 (1.000,1.000) (1.000,1.000) (1.000,1.000)
1.00e+307 (1.089,0.891) (1.089,0.891) (1.089,0.891)
2.00e+307 (1.154,0.769) (1.154,0.769) (1.154,0.769)
3.00e+307 (1.193,0.642) (1.193,0.642) (1.193,0.642)
4.00e+307 (1.207,0.517) (1.207,0.517) (1.207,0.517)
5.00e+307 (1.200,0.400) (1.200,0.400) (1.200,0.400)
6.00e+307 (1.176,0.294) (1.176,0.294) (1.176,0.294)
7.00e+307 (1.141,0.201) (inf,nan) (1.141,0.201)
8.00e+307 (inf,nan) (inf,nan) (inf,0.122)
9.00e+307 (nan,nan) (inf,nan) (nan,0.000)
1.00e+308 (nan,nan) (inf,nan) (nan,0.000)
1.10e+308 (nan,nan) (inf,nan) (nan,-0.000)
1.20e+308 (nan,nan) (inf,nan) (nan,-0.000)
1.30e+308 (0.000,-0.000) (inf,nan) (0.000,-0.000)
1.40e+308 (0.000,-0.000) (inf,nan) (0.000,-0.000)
1.50e+308 (0.000,-0.000) (inf,nan) (0.000,-0.000)
1.60e+308 (0.000,-0.000) (inf,nan) (0.000,-0.000)
1.70e+308 (0.000,-0.000) (nan,nan) (0.000,-0.000)
inf (nan,nan) (nan,nan) (0.000,-0.000)
inf (nan,nan) (nan,nan) (0.000,-0.000)

Note that the result should be decreasing, but becomes infinite before
it drops to zero. The example code does rather better, but the rule
that (inf,nan) is an infinity causes significant trouble - as I knew it
would, and was investigating. I don't know how much better is possible,
because this sort of issue is very nasty.
Regards,
Nick Maclaren.


#pragma STDC CX_LIMITED_RANGE OFF
#pragma STDC FP_CONTRACT OFF
#include <math.h>
#include <stdio.h>
#include <complex.h>

#ifndef TRUST_C99
#define creal(x) ((double)(x))
#define cimag(x) ((double)(-I*(x)))
#define INFINITY (1.0/0.0)
#define isfinite(x) (! isinf(x) && ! isnan(x))
extern double fmax(double,double);
#endif

double complex cdivd(double complex z, double complex w)
{
double a, b, c, d, logbw, denom, x, y;
int ilogbw = 0;
a = creal(z); b = cimag(z);
c = creal(w); d = cimag(w);
logbw = logb(fmax(fabs(c), fabs(d)));
if (isfinite(logbw)) {
ilogbw = (int)logbw;
c = scalbn(c, -ilogbw); d = scalbn(d, -ilogbw);
}
denom = c * c + d * d;
x = scalbn((a * c + b * d) / denom, -ilogbw);
y = scalbn((b * c - a * d) / denom, -ilogbw);
if (isnan(x) && isnan(y)) {
if ((denom == 0.0) &&
(!isnan(a) || !isnan(b))) {
x = copysign(INFINITY, c) * a;
y = copysign(INFINITY, c) * b;
}
else if ((isinf(a) || isinf(b)) &&
isfinite(c) && isfinite(d)) {
a = copysign(isinf(a) ? 1.0 : 0.0, a);
b = copysign(isinf(b) ? 1.0 : 0.0, b);
x = INFINITY * ( a * c + b * d );
y = INFINITY * ( b * c - a * d );
}
else if (isinf(logbw) &&
isfinite(a) && isfinite(b)) {
c = copysign(isinf(c) ? 1.0 : 0.0, c);
d = copysign(isinf(d) ? 1.0 : 0.0, d);
x = 0.0 * ( a * c + b * d );
y = 0.0 * ( b * c - a * d );
}
}
return x + I * y;
}

int main() {
int i;
double d, r, z;
double complex c1, c2;

for (i = 0; i < 20; ++i) {
d = i*0.1e308;
c1 = (1.0e308+I*1.0e308)/(1.0e308+I*d);
c2 = cdivd(1.0e308+I*1.0e308,1.0e308+I*d);
if (1.0e308 d) {
r = d/1.0e308;
z = 1.0e308+d*r;
printf("%.2e (%.3f,%.3f) (%.3f,%.3f) (%.3f,%.3f)\n",d,
creal(c1),cimag(c1),creal(c2),cimag(c2),
(1.0e308+1.0e308*r)/z,(1.0e308-1.0e308*r)/z);
} else {
r = 1.0e308/d;
z = d+1.0e308*r;
printf("%.2e (%.3f,%.3f) (%.3f,%.3f) (%.3f,%.3f)\n",d,
creal(c1),cimag(c1),creal(c2),cimag(c2),
(1.0e308*r+1.0e308)/z,(1.0e308*r-1.0e308)/z);
}
}
return 0;
}
Aug 31 '06 #40
Steven G. Kargl wrote:
In article <11*********************@m73g2000cwd.googlegroups. com>,
no***@yahoo.com writes:
This makes no sense, as the outcome of the operation is undefined and
should be NaN.
max(NaN,0.) = NaN
Why?
Well, because a NaN *could* be plus infinity, or a number too large to
be represented.

If one wants to *implement* NaNs *at all*, one's _reason_ for doing so
is because one wants computer arithmetic to produce accurate results -
rather than just plugging in the best representable number that fits,
and then giving a result that may not be valid.

So going to the trouble of bothering with NaNs, and then deciding that
treating them pessimistically is just too much bother in a few cases,
vitiates the entire enterprise!

John Savard

Sep 7 '06 #41

js*****@ecn.ab.ca wrote:
Steven G. Kargl wrote:
In article <11*********************@m73g2000cwd.googlegroups. com>,
no***@yahoo.com writes:
This makes no sense, as the outcome of the operation is undefined and
should be NaN.
max(NaN,0.) = NaN
Why?

Well, because a NaN *could* be plus infinity, or a number too large to
be represented.

If one wants to *implement* NaNs *at all*, one's _reason_ for doing so
is because one wants computer arithmetic to produce accurate results -
rather than just plugging in the best representable number that fits,
and then giving a result that may not be valid.

So going to the trouble of bothering with NaNs, and then deciding that
treating them pessimistically is just too much bother in a few cases,
vitiates the entire enterprise!
And you join the list of people who are willing to state on the
basis of a few minutes thought and no research whatsoever, that the
people behind the IEEE 754 standard are idiots.
-William Hughes

Sep 7 '06 #42
William Hughes wrote:
js*****@ecn.ab.ca wrote:
>So going to the trouble of bothering with NaNs, and then deciding that
treating them pessimistically is just too much bother in a few cases,
vitiates the entire enterprise!

And you join the list of people who are willing to state on the
basis of a few minutes thought and no research whatsoever, that the
people behind the IEEE 754 standard are idiots.
There is at least one good reason for the current standard behavior:

It maintains the maximum amount of information.

I.e. doing the opposite which would be to require max(...,NaN,...) to
always be NaN simply discards everything we know about the representable
numbers in the array, even in the case where the NaN simply means Not
Applicable, i.e. 'skip this value'.

What's needed in this case is a side channel which can provide the fact
that at least one of the inputs were NaN, since this is critical when
the NaN is a result of a series of previous calculations which have
blown up.

OTOH there is an equally good reason for requiring the opposite
behavior, i.e. max(...) is NaN if any input value is NaN: This would
obey 'the principle of last astonishment', i.e. in all other IEEE fp
operations any NaN input will propagate into the output to make sure
that this critical piece of information cannot be hidden.

Terje
--
- <Te************@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"
Sep 7 '06 #43
What's needed in this case is a side channel which can provide the fact
that at least one of the inputs were NaN, since this is critical when
the NaN is a result of a series of previous calculations which have
blown up.
I think this apporach would only serve to confuse the issue.

Clearly, there are two current interpretations of the semantics of NaN:
one is that a NaN means some prior computation yielded a non-representable
and exceptional result, the other is that this data value should be ignored.
These different meanings imply different processing in certain situations,
but not in all: It appears to me that this applies in particular to all
reduction operators, with a correction to be applied whereever the count
of operands appears (e.g., for the average value reduction).

Given current facilites in Fortran, I think the reduction operators should
always obey the "exception" semantics - i.e., if ANY(ISNAN(input_data)) is
true, the result should be a NaN (perhaps define a new one?). My reason is
that the "ignore" semantics can be achieved easily by the user: instead of,
for example, writing

X = MAX(input_data)

she can write

X = MAX(input_data(WHERE(.NOT. ISNAN(input_data)))

Of course, if you define the operator semantics the other way, you can
get the exception semantics by writing

IF (ANY(ISNAN(input_data)) THEN
X = some_NaN
ELSE
X = MAX (input_data)
ELSEIF

so it perhaps boils down to frequency of use and to consistency of user
expectations.

The only other alternative would be to define some particular value - which
could be an IEEE 754 NaN - to signify "value not available", and to modify
the semantics of the reduction operators based on whether this value is
present or not. However, one still needs to define the behaviour of what to
do when _both_ an "exception" NaN _and_ an "ingore" NaN are present in the
input 8-). My choice: the "exception" NaN takes precendence.

Jan
Sep 7 '06 #44

In article <11*********************@m73g2000cwd.googlegroups. com>,
"William Hughes" <wp*******@hotmail.comwrites:
|js*****@ecn.ab.ca wrote:
| Steven G. Kargl wrote:
| In article <11*********************@m73g2000cwd.googlegroups. com>,
| no***@yahoo.com writes:
|
| This makes no sense, as the outcome of the operation is undefined and
| should be NaN.
| max(NaN,0.) = NaN
|
| Why?
|
| Well, because a NaN *could* be plus infinity, or a number too large to
| be represented.
|
| If one wants to *implement* NaNs *at all*, one's _reason_ for doing so
| is because one wants computer arithmetic to produce accurate results -
| rather than just plugging in the best representable number that fits,
| and then giving a result that may not be valid.
|
| So going to the trouble of bothering with NaNs, and then deciding that
| treating them pessimistically is just too much bother in a few cases,
| vitiates the entire enterprise!
|>
|And you join the list of people who are willing to state on the
|basis of a few minutes thought and no research whatsoever, that the
|people behind the IEEE 754 standard are idiots.

You are wrong on three counts:

max/min are not part of IEEE 754, and are not even in the appendix;
they are proposed as part of IEEE 754R.

He did not state that they were idiots - merely misguided - and you
have no evidence that he has done no research.

I am pretty sure that he knows of my analysis of the matter (and
document on it), where I do explain why he is correct and the IEEE 754R
people are wrong. And, in THIS respect, I believe that I have more
experience than any of the people on that group.

OK?
Regards,
Nick Maclaren.
Sep 7 '06 #45

In article <e6************@osl016lin.hda.hydro.com>
Terje Mathisen <te************@hda.hydro.comwrites:
|>
|There is at least one good reason for the current standard behavior:
|>
|It maintains the maximum amount of information.
|>
|I.e. doing the opposite which would be to require max(...,NaN,...) to
|always be NaN simply discards everything we know about the representable
|numbers in the array, even in the case where the NaN simply means Not
|Applicable, i.e. 'skip this value'.

Sorry, Terje, but you have missed the point. By providing ways to lose
the NaN state quietly, you are rendering them useless as an error value.
50 years of experience shows that requiring programmers to check every
operation that might fail for possible failure simply does not work; if
checking isn't fail-safe, it is pointless.

As my document explains, there are numerous possible meanings of "not a
number", all of which imply different semantics. In particular, allowing
a missing value indication is one of the oldest and best, but is NOT what
IEEE 754 does and is NOT what IEEE 754R is proposing. The arguments
used for this behaviour by IEEE 754R have been copied from C99 and are
both false have are known to be false.
Regards,
Nick Maclaren.
Sep 7 '06 #46

In article <4m************@individual.net>,
=?ISO-8859-1?Q?Jan_Vorbr=FCggen?= <jv**********@not-mediasec.dewrites:
|>
|The only other alternative would be to define some particular value - which
|could be an IEEE 754 NaN - to signify "value not available", and to modify
|the semantics of the reduction operators based on whether this value is
|present or not. However, one still needs to define the behaviour of what to
|do when _both_ an "exception" NaN _and_ an "ingore" NaN are present in the
|input 8-). My choice: the "exception" NaN takes precendence.

Correct. And, as I have pointed out to both C99 and IEEE 754R, but have
been ignored on purely dogmatic grounds, there are NO uses where ONLY the
"missing value" semantics are wanted, IEEE 754 doesn't support them in the
first place, and the max/min operations aren't the most important anyway.
There ARE uses where only the "error value" semantics are wanted.

In statistics, which is one of the claimed uses, missing value semantics
are wanted ONLY for specific reduction operations, and the ranking of
importance is:

Counting (i.e. number of non-NaNs)
Summation
Derivative operations (mean, variance etc.) |
Max/min | In some order
Multiplication |
Regards,
Nick Maclaren.
Sep 7 '06 #47
Counting (i.e. number of non-NaNs)
Summation
Derivative operations (mean, variance etc.) |
Max/min | In some order
Those are all reductions.
Multiplication |
Do you mean scaling? If so, you probably want to cover any functional
transform of the values.

Jan
Sep 7 '06 #48

In article <4m************@individual.net>,
=?ISO-8859-1?Q?Jan_Vorbr=FCggen?= <jv**********@not-mediasec.dewrites:
| Counting (i.e. number of non-NaNs)
| Summation
| Derivative operations (mean, variance etc.) |
| Max/min | In some order
|>
|Those are all reductions.

Precisely.

| Multiplication |
|>
|Do you mean scaling? If so, you probably want to cover any functional
|transform of the values.

Sorry, I meant product. I.e. reduction by multiplication.
The basic rules with both error and missing values are:

If any operand is erroneous, or the result is mathematically undefined,
the result is erroneous. Missing/0.0 is erroneous, for example.

Otherwise, if it is a reduction, only the non-missing values are used.

If it is not a reduction and any operand is missing, the result is
missing.

In practice, "a reduction" isn't just operations that are reductions, but
specific calls to reduction functions that allow for missing values.
Regards,
Nick Maclaren.
Sep 7 '06 #49
Nick Maclaren wrote:
In article <e6************@osl016lin.hda.hydro.com>
Terje Mathisen <te************@hda.hydro.comwrites:
|>
|There is at least one good reason for the current standard behavior:
|>
|It maintains the maximum amount of information.
|>
|I.e. doing the opposite which would be to require max(...,NaN,...) to
|always be NaN simply discards everything we know about the representable
|numbers in the array, even in the case where the NaN simply means Not
|Applicable, i.e. 'skip this value'.

Sorry, Terje, but you have missed the point. By providing ways to lose
the NaN state quietly, you are rendering them useless as an error value.
Nick!

You always complain about people who quote you selectively! In this case
you have snipped the paragraph where I agree with you, specifically that
dropping NaN information is a _very_ surprising behavior.

I.e. we're in violent agreement, I was just trying to think of a
possible use for the defined (IMHO broken) specification.

Terje

--
- <Te************@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"
Sep 7 '06 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.