2828 * does this with many compilers. Whether this or another call is
2929 * appropriate depends on the compiler; for this to work, it may be
3030 * necessary to #include "float.h" or another system-dependent header
31- * file.
31+ * file. When needed, this call avoids double rounding, which can
32+ * cause one bit errors, e.g., with strtod on 8.3e26 or 6.3876e-16.
3233 */
3334
3435/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
@@ -2716,13 +2717,14 @@ enum { /* rounding values: same as FLT_ROUNDS */
27162717 };
27172718
27182719 void
2719- gethex ( const char * * sp , U * rvp , int rounding , int sign MTd )
2720+ gethex (const char * * sp , U * rvp , int rounding , int sign MTd )
27202721{
27212722 Bigint * b ;
2723+ char d ;
27222724 const unsigned char * decpt , * s0 , * s , * s1 ;
27232725 Long e , e1 ;
27242726 ULong L , lostbits , * x ;
2725- int big , denorm , esign , havedig , k , n , nbits , up , zret ;
2727+ int big , denorm , esign , havedig , k , n , nb , nbits , nz , up , zret ;
27262728#ifdef IBM
27272729 int j ;
27282730#endif
@@ -2740,6 +2742,9 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
27402742#endif
27412743#endif /*}}*/
27422744 };
2745+ #ifdef IEEE_Arith
2746+ int check_denorm = 0 ;
2747+ #endif
27432748#ifdef USE_LOCALE
27442749 int i ;
27452750#ifdef NO_LOCALE_CACHE
@@ -2891,7 +2896,7 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
28912896 k ++ ;
28922897 b = Balloc (k MTa );
28932898 x = b -> x ;
2894- n = 0 ;
2899+ havedig = n = nz = 0 ;
28952900 L = 0 ;
28962901#ifdef USE_LOCALE
28972902 for (i = 0 ; decimalpoint [i + 1 ]; ++ i );
@@ -2906,22 +2911,28 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
29062911 if (* -- s1 == '.' )
29072912 continue ;
29082913#endif
2914+ if ((d = hexdig [* s1 ]))
2915+ havedig = 1 ;
2916+ else if (!havedig ) {
2917+ e += 4 ;
2918+ continue ;
2919+ }
29092920 if (n == ULbits ) {
29102921 * x ++ = L ;
29112922 L = 0 ;
29122923 n = 0 ;
29132924 }
2914- L |= (hexdig [ * s1 ] & 0x0f ) << n ;
2925+ L |= (d & 0x0f ) << n ;
29152926 n += 4 ;
29162927 }
29172928 * x ++ = L ;
29182929 b -> wds = n = x - b -> x ;
2919- n = ULbits * n - hi0bits (L );
2930+ nb = ULbits * n - hi0bits (L );
29202931 nbits = Nbits ;
29212932 lostbits = 0 ;
29222933 x = b -> x ;
2923- if (n > nbits ) {
2924- n -= nbits ;
2934+ if (nb > nbits ) {
2935+ n = nb - nbits ;
29252936 if (any_on (b ,n )) {
29262937 lostbits = 1 ;
29272938 k = n - 1 ;
@@ -2934,8 +2945,8 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
29342945 rshift (b , n );
29352946 e += n ;
29362947 }
2937- else if (n < nbits ) {
2938- n = nbits - n ;
2948+ else if (nb < nbits ) {
2949+ n = nbits - nb ;
29392950 b = lshift (b , n MTa );
29402951 e -= n ;
29412952 x = b -> x ;
@@ -2990,12 +3001,49 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
29903001 return ;
29913002 }
29923003 k = n - 1 ;
3004+ #ifdef IEEE_Arith
3005+ if (!k ) {
3006+ switch (rounding ) {
3007+ case Round_near :
3008+ if (((b -> x [0 ] & 3 ) == 3 ) || (lostbits && (b -> x [0 ] & 1 ))) {
3009+ multadd (b , 1 , 1 MTa );
3010+ emin_check :
3011+ if (b -> x [1 ] == (1 << (Exp_shift + 1 ))) {
3012+ rshift (b ,1 );
3013+ e = emin ;
3014+ goto normal ;
3015+ }
3016+ }
3017+ break ;
3018+ case Round_up :
3019+ if (!sign && (lostbits || (b -> x [0 ] & 1 ))) {
3020+ incr_denorm :
3021+ multadd (b , 1 , 2 MTa );
3022+ check_denorm = 1 ;
3023+ lostbits = 0 ;
3024+ goto emin_check ;
3025+ }
3026+ break ;
3027+ case Round_down :
3028+ if (sign && (lostbits || (b -> x [0 ] & 1 )))
3029+ goto incr_denorm ;
3030+ break ;
3031+ }
3032+ }
3033+ #endif
29933034 if (lostbits )
29943035 lostbits = 1 ;
29953036 else if (k > 0 )
29963037 lostbits = any_on (b ,k );
3038+ #ifdef IEEE_Arith
3039+ else if (check_denorm )
3040+ goto no_lostbits ;
3041+ #endif
29973042 if (x [k >>kshift ] & 1 << (k & kmask ))
29983043 lostbits |= 2 ;
3044+ #ifdef IEEE_Arith
3045+ no_lostbits :
3046+ #endif
29993047 nbits -= n ;
30003048 rshift (b ,n );
30013049 e = emin ;
@@ -3020,16 +3068,9 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
30203068 k = b -> wds ;
30213069 b = increment (b MTa );
30223070 x = b -> x ;
3023- if (denorm ) {
3024- #if 0
3025- if (nbits == Nbits - 1
3026- && x [nbits >> kshift ] & 1 << (nbits & kmask ))
3027- denorm = 0 ; /* not currently used */
3028- #endif
3029- }
3030- else if (b -> wds > k
3071+ if (!denorm && (b -> wds > k
30313072 || ((n = nbits & kmask ) != 0
3032- && hi0bits (x [k - 1 ]) < 32 - n )) {
3073+ && hi0bits (x [k - 1 ]) < 32 - n ))) {
30333074 rshift (b ,1 );
30343075 if (++ e > Emax )
30353076 goto ovfl ;
@@ -3039,8 +3080,10 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
30393080#ifdef IEEE_Arith
30403081 if (denorm )
30413082 word0 (rvp ) = b -> wds > 1 ? b -> x [1 ] & ~0x100000 : 0 ;
3042- else
3083+ else {
3084+ normal :
30433085 word0 (rvp ) = (b -> x [1 ] & ~0x100000 ) | ((e + 0x3ff + 52 ) << 20 );
3086+ }
30443087 word1 (rvp ) = b -> x [0 ];
30453088#endif
30463089#ifdef IBM
@@ -3617,10 +3660,11 @@ strtod(const char *s00, char **se)
36173660 c = * ++ s ;
36183661 if (c > '0' && c <= '9' ) {
36193662 L = c - '0' ;
3620- s1 = s ;
3621- while ((c = * ++ s ) >= '0' && c <= '9' )
3622- L = 10 * L + c - '0' ;
3623- if (s - s1 > 8 || L > 19999 )
3663+ while ((c = * ++ s ) >= '0' && c <= '9' ) {
3664+ if (L <= 19999 )
3665+ L = 10 * L + c - '0' ;
3666+ }
3667+ if (L > 19999 )
36243668 /* Avoid confusion from exponents
36253669 * so large that e might overflow.
36263670 */
@@ -5416,7 +5460,8 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
54165460 && (spec_case ? 4 * res <= ulp : (2 * res < ulp || dig & 1 ))) {
54175461 ulp_reached :
54185462 if (ures < res
5419- || (ures == res && dig & 1 ))
5463+ || (ures == res && dig & 1 )
5464+ || (dig == 9 && 2 * ures <= ulp ))
54205465 goto Roundup ;
54215466 goto retc ;
54225467 }
@@ -5662,7 +5707,7 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
56625707 }
56635708 }
56645709 if (!(zb & ures ) && (ures - rb ) << (1 - eulp ) < ulp ) {
5665- if ((ures + rb ) << (1 - eulp ) < ulp )
5710+ if ((ures + rb ) << (2 - eulp ) < ulp )
56665711 goto Roundup ;
56675712 goto Fast_failed1 ;
56685713 }
0 commit comments