delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/04/03/10:08:53

X-Sybari-Space: 00000000 00000000 00000000 00000000
From: Martin Stromberg <Martin DOT Stromberg AT epl DOT ericsson DOT se>
Message-Id: <200304031505.RAA19060@lws256.lu.erisoft.se>
Subject: Re: Support for nan(0x[0-9a-f]*) in strto*, *printf
To: djgpp-workers AT delorie DOT com
Date: Thu, 3 Apr 2003 17:05:08 +0200 (MET DST)
In-Reply-To: <3E89B1F9.1BC8C387@phekda.freeserve.co.uk> from "Richard Dawe" at Apr 01, 2003 04:36:25 PM
X-Mailer: ELM [version 2.5 PL3]
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

Hi!

Richard said:
> * (double) NAN or (long double) NAN results in the exponent being extended up
> to the maximum for double or long double.

iff hardware FPU. Perhaps your mail only talks about hardware
FPU. That's reasonable. I'll only think/talk of hardware FPU from now
unless somebody explicitly talks about FPU emulation.

> * (double) a long double NaN == a double NaN. See the test program t-nan.c
> below.
> 
> * (float) a long double NaN == a float NaN. See the test program t-nan.c
> below.

You probably mean "the long double NaN used in t-nan.c" instead of "a
long double NaN", right? (There are many different NaNs.)

Also you probably mean "the bit pattern of ..." prepended to left and
right sides of ==, because I thought "fcmp st, st1" (I made up that
instruction as I don't know the syntax for them; hopefully you get my
meaning) where st and st1 both contain a NaN with the same bit pattern
sets the flag(s) to not equal ( x != x, if x == a NaN). I could be
wrong here.

I'm also a little confused where t-nan2.c enters the discussion.

> The way I've implemented support for nan(0x[0-9a-f]*) at the moment means
> that:
> 
>     printf("%f", NAN);
> 
> would display:
> 
>     nan(0xfffffe0000000)
> 
> This is because the float is converted to a double. I can't see a way round
> this. There is no way that the _doprnt code can know that the number is a
> float and not a double.

Right.

> The current proposed implementation of strtof (see "strtof()'s NaN and Inf
> support", dated Sat, 22 Mar 2003 12:32:13 +0100 (CET)) will not return NAN,
> when asked to parse "nan(0xfffffe0000000)". The problem is that it assumes the
> data it wants is in the lowest 23 bits of the hex data (the mantissa). This is
> not the case for floats converted to doubles. I suspect a similar problem

Right.

> exists, when doubles are converted to long doubles.

Possible.

> I'd like to propose a solution:
> 
> Since the hex data in nan(0x[0-9a-f]*) is implementation-specific, I think we
> should always write the mantissa from a long double representation of the NaN
> there in *printf. This long double representation would then be used as the

I might disagree, because that might destroy the bit pattern in the
double NaN when assigned to a long double.

> lowest- (highest-?) common denominator. It would be down converted to float,
> double as appropriate by strto*. strto* could set up a long_double_t and cast
> that down to the appropriate size. E.g.: for strtof:

Again that might destroy the very bit pattern that the code took such
care of inserting, see below.

> 
>     long_double_t ldt;
>     long double ld;
>     unsigned long long mantissa_bits;
> 
>     mantissa_bits = strtoull(&s[4], &endptr, 16);
> 
>     ldt.mantissah = mantissa_bits >> 32;
>     ldt.mantissal = mantissa_bits & 0xffffffffU;

Nice, we get the bit pattern.

>     ldt.exponent  = 0x7fffU;
>     ldt.sign      = <whatever>;
> 
>     ld = *(long double *) &ldt;
> 
>     /* endptr stuff here */
> 
>     return(ld); /* <- converts to a float return value */

Oops, we let the hardware convert our bit pattern. Might be any
representation of a NaN now.

Or perhaps it just works?

Anyway I'd prefer to stay away from any automatic conversions by the
hardware (what might it do to the sign bit, e. g.?) to be able to
provide the closest bit pattern the user requested as possible. (Why
else bother with this bit messing?)

> Does this make sense? Any thoughts?

Thanks for the coding and testing.

I propose all strto*() do use an unsigned long long to store the
mantissa (X) given in "nan(X)". If X > the maximum for float or
double, set the mantissa to all-ones (we clamp the value to the
maximum possible).

This will make ``strtof(sprintf(s, "%d", NAN), NULL)'' return a
NaN. 

There's not much we can do about *printf()'s problem forcing it into
double. But this will let a coder that really wants a certain bit
pattern in a float use ``strtof("nan(0x1)", NULL)'' to achive this
(except for the automatical silencing of SNaNs).

If *printf() will handle NaN in a double separately from long doubles
this should make ``double value1 =
extreme_cpu_use_generating_unusual_nans();
double value2 = strtod(sprintf(s, "%d", value1), NULL)'' make the bit
pattern of value1 == the bit pattern of value2.


Right,

						MartinS

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019