[RFC/PATCH] Enable IEEE_Arith when double is 32 bits for strtod

Jeff Johnston jjohnstn@redhat.com
Fri Aug 31 22:36:00 GMT 2007


Patch applied.  Thanks.

-- Jeff J.

Antony KING wrote:
> Hi,
> 
> Attached is a 2 part patch I have constructed against 1.15.0 of newlib
> in which part 1 fixes some compilation errors detected as a result of
> defining "IEEE_Arith" in part 2 of the patch.
> 
> The second part of the patch fixes an error detected by Plumhall C test
> suite (2007A) when running an application where doubles are 32 bits (in
> this instance with the GCC SH4 ABI -m4-single-only). The test suite is
> expecting that +/- HUGE_VAL is returned on overflow, which is the case
> when a double is 64 bits but not when 32 bits. Part 2 of the patch
> enables this behaviour. I also have attached a reduced form of the test
> which illustrates the failure.
> 
> The ChangeLog entry:
> 
>         * libc/stdlib/mprec.h [_DOUBLE_IS_32BITS}: Define IEEE_Arith
> 	bits and redefine associated dword0 macro (rvalue issue).
> 	* libc/stdio/vfieeefp.h: Ditto.
>         * libc/stdlib/strtod.c: Add checks for _DOUBLE_IS_32BITS
>         to prevent setting dword1 which is an rvalue only.
> 
> Cheers,
> 
> Antony.
> 
> 
> 
> ------------------------------------------------------------------------
> 
> --- newlib/libc/stdio/vfieeefp.h@@/NEWLIB-1.15.0	2004-05-26 01:19:14.000000000 +0100
> +++ newlib/libc/stdio/vfieeefp.h	2007-08-17 18:13:46.259368000 +0100
> @@ -170,9 +170,7 @@
>  #define Exp_mask    ((__uint32_t)0x7f800000L)
>  #define P    	    24
>  #define Bias 	    127
> -#if 0
> -#define IEEE_Arith  /* it is, but the code doesn't handle IEEE singles yet */
> -#endif
> +#define IEEE_Arith
>  #define Emin        (-126)
>  #define Exp_1       ((__uint32_t)0x3f800000L)
>  #define Exp_11      ((__uint32_t)0x3f800000L)
> --- newlib/libc/stdlib/mprec.h.orig	2007-08-28 11:41:24.994483000 +0100
> +++ newlib/libc/stdlib/mprec.h	2007-08-17 18:56:06.969216000 +0100
> @@ -139,15 +139,7 @@
>  #define P    	    24
>  #define Bias 	    127
>  #define NO_HEX_FP   /* not supported in this case */
> -#if 0
> -#define IEEE_Arith  /* it is, but the code doesn't handle IEEE singles yet */
> -#endif
> -/* Following is needed due to IEEE_Arith not being set on above.  */
> -#if defined(__v800)
> -#define n_bigtens 2
> -#else
> -#define n_bigtens 5
> -#endif
> +#define IEEE_Arith
>  #define Emin        (-126)
>  #define Exp_1       ((__uint32_t)0x3f800000L)
>  #define Exp_11      ((__uint32_t)0x3f800000L)
> 
> 
> ------------------------------------------------------------------------
> 
> --- newlib/libc/stdlib/mprec.h@@/NEWLIB-1.15.0	2006-07-05 17:18:30.000000000 +0100
> +++ newlib/libc/stdlib/mprec.h	2007-08-28 11:41:24.994483000 +0100
> @@ -175,7 +175,11 @@
>  
>  #define word0(x) (x.i[0])
>  #define word1(x) 0
> +#ifdef YES_ALIAS
>  #define dword0(x) ((__ULong *)&x)[0]
> +#else
> +#define dword0(x) ((U*)&x)->L[0]
> +#endif
>  #define dword1(x) 0
>  #else
>  
> --- newlib/libc/stdlib/strtod.c@@/NEWLIB-1.15.0	2006-07-05 17:18:30.000000000 +0100
> +++ newlib/libc/stdlib/strtod.c	2007-08-17 19:11:58.711787000 +0100
> @@ -386,7 +386,9 @@
>  					if (!match(&s,"inity"))
>  						++s;
>  					dword0(rv) = 0x7ff00000;
> +#ifndef _DOUBLE_IS_32BITS
>  					dword1(rv) = 0;
> +#endif /*!_DOUBLE_IS_32BITS*/
>  					goto ret;
>  					}
>  				break;
> @@ -398,12 +400,16 @@
>  					 && hexnan(&s, &fpinan, bits)
>  							== STRTOG_NaNbits) {
>  						dword0(rv) = 0x7ff00000 | bits[1];
> +#ifndef _DOUBLE_IS_32BITS
>  						dword1(rv) = bits[0];
> +#endif /*!_DOUBLE_IS_32BITS*/
>  						}
>  					else {
>  #endif
>  						dword0(rv) = NAN_WORD0;
> +#ifndef _DOUBLE_IS_32BITS
>  						dword1(rv) = NAN_WORD1;
> +#endif /*!_DOUBLE_IS_32BITS*/
>  #ifndef No_Hex_NaN
>  						}
>  #endif
> @@ -627,8 +633,8 @@
>  #ifndef _DOUBLE_IS_32BITS
>  				else
>  					dword1(rv) &= 0xffffffff << j;
> -				}
>  #endif /*!_DOUBLE_IS_32BITS*/
> +				}
>  #else
>  			for(j = 0; e1 > 1; j++, e1 >>= 1)
>  				if (e1 & 1)
> @@ -1109,7 +1115,9 @@
>  	if (inexact) {
>  		if (!oldinexact) {
>  			dword0(rv0) = Exp_1 + (70 << Exp_shift);
> +#ifndef _DOUBLE_IS_32BITS
>  			dword1(rv0) = 0;
> +#endif /*!_DOUBLE_IS_32BITS*/
>  			dval(rv0) += 1.;
>  			}
>  		}
> @@ -1119,7 +1127,9 @@
>  #ifdef Avoid_Underflow
>  	if (scale) {
>  		dword0(rv0) = Exp_1 - 2*P*Exp_msk1;
> +#ifndef _DOUBLE_IS_32BITS
>  		dword1(rv0) = 0;
> +#endif /*!_DOUBLE_IS_32BITS*/
>  		dval(rv) *= dval(rv0);
>  #ifndef NO_ERRNO
>  		/* try to avoid the bug of testing an 8087 register value */
> 
> 
> ------------------------------------------------------------------------
> 
> #include <errno.h>
> #include <math.h>
> #include <stdio.h>
> #include <stdlib.h>
> 
> static int deq(double val1, double val2)
> {
>   if (val1 != val2) {
>     printf("got %f, expected %f\n", val1, val2);
>   }
> }  
> 
> static int ieq(int val1, int val2)
> {
>   if (val1 != val2) {
>     printf("got %d, expected %d\n", val1, val2);
>   }
> }  
> 
> int main(void)
> {
>   /* overflow returns +/- HUGE_VAL */
>   errno = 0;
>   deq(strtod("2.3e99999999999999999999", NULL), HUGE_VAL);
>   ieq(errno, ERANGE);
>   errno = 0;
>   deq(strtod("-1e99999999999999999999", NULL), -HUGE_VAL);
>   ieq(errno, ERANGE); 
> 
>   return 0;
> }



More information about the Newlib mailing list