[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Radical solutions to global flags



Here is what I believe could be done.  Neither of the solutions are
easy or fully compatible, and a lot of things that have been decided
in IEEE 754R go in exactly the wrong direction.


    1) IEEE 754R or the languages could extend the interchange format to
include the flag values, as Ivan Godard said.  This would be a real pain
for the existing binary formats, as it would double the size of the
representation (due to alignment), but wouldn't be a major problem for
new formats.

There would be screams, as it would mean reducing the number of bits
available for the value by, say, 8.  Not feasible for 32-bit formats,
and a significant issue for 64-bit ones.


    2) IEEE 754R could tidy up its exception value model, and separate
the operations into the arithmetic ones that would ensure that the
exception state propagates, and the auxiliary ones where it could be
lost.  I have never understood what the objection is to doing this in a
compatible fashion, as it was clearly in the back of people's minds with
IEEE 754.

Specifically, the first thing is to take the decision in principle that
the NaN state must NEVER be losable by a NUMERIC operation, and should
invariably be an error state.  Bit-twiddling operations are another
matter.  Related to this is that IEEE 754R should take a definite
decision whether the sign and value of a NaN are meaningful or not, and
follow that decision consistently - IEEE 754 was consistent, IEEE 754R
and C99 are not.

The first and easiest consequence is that the NUMERIC max/min/copysign
etc. need to return a NaN if any argument is a NaN.  I don't care if
there is a SEPARATE copysign auxiliary with bit-twiddling semantics.
See at the end about the use of NaNs as missing values, and min/max,
and why the C99 rationale is complete nonsense.

Unfortunately, there are still some major loopholes involving the signs
of zeroes, infinities and so on, which can be used to prove that 1 = 0,
in a few cases without setting any flags.  Take, for example:

    A = B
    -(A-B) = (B-A)     a mathematical truism
    copysign(1.0,-(A-B)) != copysign(1.0,(B-A))

There is also an inconsistency that +Infinity >= +Infinity but
(+Infinity - +Infinity) = NaN.

The simple solution here would be a mandatory mode that relying on the
sign of zero returns a NaN result (e.g. division by zero and copysign),
and that any loss of the NaN state in a NUMERIC operation (including
ordinary comparisons for equality, and the above loophole) is required
to invoke trap-diagnose-and-terminate semantics.

That would mean that there was a safe way of using IEEE 754R relying
SOLELY on the value, for a traditional interpretation of the word
'safe'.  Yes, I know programs could still fail through loss of
precision, but no program would fail, undiagnosed, with NO loss of
precision.  That is what we used to get with the traditional debugging
compilers, after all.


    3) Something much more radical could be done.  Let's ignore that.



NaNs as missing values
----------------------

This is a digression, and is not related to parallelism as such.
It does describe what should be done if IEEE 754R wants to provide
usable support for missing values in the context of statistical
calculations.

I have extensive experience in using, supporting and developing
statistical packages that use missing values, dating back to the early
1970s.  The C99 rationale for the current specification is quite simply
nonsense, as I have repeatedly pointed out, and would never have got
through if anyone in the inner cabal of C9X had had such experience.

    1) The first point is that the semantics for using NaNs as missing
values conflicts BADLY with IEEE 754 - for example, 0.0*Missing = 0.0
and Missing < Infinity is True.

    2) The second is that the primitives needed are (in THIS order of
importance):

    Count of non-missing values in vector
    Sum all non-missing values in vector
    Max/min of all non-missing values in vector
    Product of all non-missing values in vector

It is complete and utter twaddle to claim that the third is critical for
performance and the others are not.  Also, note that these primitives
are NOT the normal ones.  In a typical statistical package, one may have
A = (1.0, 0.0, 2.0, 0.0, 3.0) and B = (1.0, NaN, 2.0, 0.0, 3.0), where
the NaN means Missing, and the normal (vector) addition and max should
deliver:

    A+B = (1.0, NaN, 4.0, 0.0, 6.0)
    max(A,B) = (1.0, NaN, 4.0, 0.0, 6.0)

    3) The third is that the performance argument applies at least as
strongly the other way round to normal numeric uses of max/min.

    4) The fourth is that statistical packages need BOTH error values
AND missing values, and the two have DISTINCT propagation properties.
For example, consider mean(A/B) with A = (1.0, 0.0, 2.0, 0.0, 3.0) and
B = (1.0, NaN, 2.0, 0.0, 3.0), where the NaN means Missing.

This makes A/B = (1.0, NaN, 2.0, NaN, 3.0), but the FIRST NaN means
Missing and the SECOND NaN means Error, so the correct answer to the
mean is Error.  If, however, B = (1.0, NaN, 2.0, NaN, 3.0), with both
NaNs meaning Missing, A/B is the same but the correct mean is 1.0.

Oh, and Error takes precedence over Missing.

    5) The fifth is that the correct way to include missing values is to
add them as a third class of NaN - i.e. quiet, signalling and missing.
All have subtly different semantics.




Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  nmm1@xxxxxxxxx
Tel.:  +44 1223 334761    Fax:  +44 1223 334679

754 | revision | FAQ | references | list archive