Glenn Fowler wrote:
> On Thu, 30 Nov 2006 05:40:28 +0100 Roland Mainz wrote:
> > While writing some regression tests I found a weired detail.
> 
> > The following test script (not exactly correct, but that is not the
> > issue in thid case ; note that you need something like ksh93s- or better
> > for this)
> > -- snip --
[snip]
> > -- snip --
> > ...however I am slightly confused about a "negative NaN" - sure, the
> > floating point datatype allows this since the sign occupies a seperate
> > bit - but is |-NaN| something valid (I think the answer should be "yes"
> > but I am somewhat confused that the Solaris manual pages have zero
> > information about this detail... ;-( ) ?
> 
> > How should C99 |printf()| and the shell's "printf" builtin handle this,
> > e.g. should the sign be printed or not (quick test: $ ksh -c 'float x ;
> > x=-NaN ; printf "%f $x\n" $x' # returns "NaN NaN" and no sign of a
> > "sign") ?
> > Does the C99 standard say anything about this ?
> 
> I believe the key is that every non-relational operation
> on Nan produces NaN -- this includes unary minus,
> and every relational operation/function, except isnan,
> involving NaN is false -- this includes "NaN==NaN" is false
> (there are so many new math functions that I probably missed
>  some exceptions, like the classifier functions)
> 
> so
>         abs(-NaN) => abs(NaN) => NaN
>         NaN < 0 # false
>         NaN == 0 # false
>         NaN > 0 # false
> 
> but the basic premise is that NaN is not intuitive w.r.t. elementary 
> arithmetic
> and therefore regression tests involving isnan(x) need to be separated out 
> from
> those involving !isnan(x)

Mhhh... that's one side of the problem...
... someone on IRC provided a C99 test program:
-- snip --
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>

int main(int argc, char* argv[])
{
    (void) fprintf(stderr, "NAN [UL]:\t %u\n",  strtoul("NAN", NULL,
10));
    (void) fprintf(stderr, "-NAN [UL]:\t %u\n", strtoul("-NAN", NULL,
10));
    (void) fprintf(stderr, "NAN [D]:\t %lf\n",  strtod("NAN", NULL));
    (void) fprintf(stderr, "-NAN [D]:\t %lf\n", strtod("-NAN", NULL));
    (void) fprintf(stderr, "NAN [F]:\t %f\n",   strtof("NAN", NULL));
    (void) fprintf(stderr, "-NAN [F]:\t %f\n",  strtof("-NAN", NULL));
    return EXIT_SUCCESS;
}
-- snip --
... which returns on Solaris 11/B51:
-- snip --
$ c99 negative_nan_test.c
$ ./a.out 
NAN [UL]:        0
-NAN [UL]:       0
NAN [D]:         nan
-NAN [D]:        -nan
NAN [F]:         nan
-NAN [F]:        -nan
-- snip --

Then I hunted down a draft copy of the 2005 version of the C99 standard
(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf) which
explicitly says for |fprintf()|: "A double argument representing a NaN
is converted in one of the styles [-]nan or [-]nan(n-char-sequence)".

AFAIK this means the correct behaviour (assuming it is modelled after
C99+XPG6) for the "printf" and "print" builtin commands would be that $
ksh -c 'float x ; x=-NaN ; printf "%f $x\n" $x' # should return "-NaN
-NaN", e.g. the sign is provided regardless whether the value is a
normal, infinite or NaN ...

... IMO it would make sense to adjust the "printf"/"print" builtins
since some functions use the sign (and others do not) of |NaN| which can
result in some "suprises" for the script authors... =:-)

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) roland.mainz at nrubsig.org
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 7950090
 (;O/ \/ \O;)

Reply via email to