X-Sybari-Space: 00000000 00000000 00000000 00000000 From: Martin Stromberg 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 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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 Precedence: bulk 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 = ; > > 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