diff options
Diffstat (limited to 'generic/tclStrToD.c')
-rwxr-xr-x | generic/tclStrToD.c | 1212 |
1 files changed, 590 insertions, 622 deletions
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 9f31841..ab2701d 100755 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -3,19 +3,19 @@ * * tclStrToD.c -- * - * This file contains a TclStrToD procedure that handles conversion - * of string to double, with correct rounding even where extended - * precision is needed to achieve that. It also contains a - * TclDoubleDigits procedure that handles conversion of double - * to string (at least the significand), and several utility functions - * for interconverting 'double' and the integer types. + * This file contains a TclStrToD procedure that handles conversion of + * string to double, with correct rounding even where extended precision + * is needed to achieve that. It also contains a TclDoubleDigits + * procedure that handles conversion of double to string (at least the + * significand), and several utility functions for interconverting + * 'double' and the integer types. * * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclStrToD.c,v 1.5 2005/06/26 22:10:08 dkf Exp $ + * RCS: @(#) $Id: tclStrToD.c,v 1.6 2005/07/05 11:37:02 dkf Exp $ * *---------------------------------------------------------------------- */ @@ -31,46 +31,48 @@ /* * The stuff below is a bit of a hack so that this file can be used in - * environments that include no UNIX, i.e. no errno: just arrange to use - * the errno from tclExecute.c here. + * environments that include no UNIX, i.e. no errno: just arrange to use the + * errno from tclExecute.c here. */ #ifdef TCL_GENERIC_ONLY -#define NO_ERRNO_H +# define NO_ERRNO_H #endif #ifdef NO_ERRNO_H extern int errno; /* Use errno from tclExecute.c. */ -#define ERANGE 34 +# define ERANGE 34 #endif -#if ( FLT_RADIX == 2 ) && ( DBL_MANT_DIG == 53 ) && ( DBL_MAX_EXP == 1024 ) -#define IEEE_FLOATING_POINT +#if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024) +# define IEEE_FLOATING_POINT #endif /* - * gcc on x86 needs access to rounding controls. It is tempting to - * include fpu_control.h, but that file exists only on Linux; it is - * missing on Cygwin and MinGW. + * gcc on x86 needs access to rounding controls. It is tempting to include + * fpu_control.h, but that file exists only on Linux; it is missing on Cygwin + * and MinGW. Most gcc-isms and ix86-isms are factored out here. */ #if defined(__GNUC__) && defined(__i386) typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); -#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) -#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) +# define FPU_IEEE_ROUNDING 0x027f +# define ADJUST_FPU_CONTROL_WORD #endif /* - * HP's PA_RISC architecture uses 7ff4000000000000 to represent a - * quiet NaN. Everyone else uses 7ff8000000000000. (Why, HP, why?) + * HP's PA_RISC architecture uses 7ff4000000000000 to represent a quiet NaN. + * Everyone else uses 7ff8000000000000. (Why, HP, why?) */ #ifdef __hppa -# define NAN_START 0x7ff4 -# define NAN_MASK (((Tcl_WideUInt) 1) << 50) +# define NAN_START 0x7ff4 +# define NAN_MASK (((Tcl_WideUInt) 1) << 50) #else -# define NAN_START 0x7ff8 -# define NAN_MASK (((Tcl_WideUInt) 1) << 51) +# define NAN_START 0x7ff8 +# define NAN_MASK (((Tcl_WideUInt) 1) << 51) #endif /* @@ -79,17 +81,7 @@ typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); * only ever assigned _ONCE_ during Tcl's library initialization sequence. */ -/* The powers of ten that can be represented exactly as IEEE754 doubles. */ - -#define MAXPOW 22 -static double pow10 [MAXPOW+1]; - -static int mmaxpow; /* Largest power of ten that can be - * represented exactly in a 'double'. */ - -/* Inexact higher powers of ten */ - -static CONST double pow_10_2_n [] = { +static const double pow_10_2_n[] = { /* Inexact higher powers of ten */ 1.0, 100.0, 10000.0, @@ -100,43 +92,29 @@ static CONST double pow_10_2_n [] = { 1.0e+128, 1.0e+256 }; - -/* Logarithm of the floating point radix. */ - -static int log2FLT_RADIX; - -/* Number of bits in a double's significand */ - -static int mantBits; - -/* Table of powers of 5**(2**n), up to 5**256 */ - -static mp_int pow5[9]; - -/* The smallest representable double */ - -static double tiny; - -/* The maximum number of digits to the left of the decimal point of a - * double. */ - -static int maxDigits; - -/* The maximum number of digits to the right of the decimal point in a - * double. */ - -static int minDigits; - -/* Number of mp_digit's needed to hold the significand of a double */ - -static int mantDIGIT; +#define MAXPOW 22 /* Num of exactly representable powers of 10 */ +static double pow10[MAXPOW+1]; /* The powers of ten that can be represented + * exactly as IEEE754 doubles. */ +static int mmaxpow; /* Largest power of ten that can be + * represented exactly in a 'double'. */ +static int log2FLT_RADIX; /* Logarithm of the floating point radix. */ +static int mantBits; /* Number of bits in a double's significand. */ +static mp_int pow5[9]; /* Table of powers of 5**(2**n), up to + * 5**256. */ +static double tiny; /* The smallest representable double. */ +static int maxDigits; /* The maximum number of digits to the left of + * the decimal point of a double. */ +static int minDigits; /* The maximum number of digits to the right + * of the decimal point in a double. */ +static int mantDIGIT; /* Number of mp_digit's needed to hold the + * significand of a double. */ /* Static functions defined in this file */ -static double RefineResult _ANSI_ARGS_((double approx, CONST char* start, - int nDigits, long exponent)); -static double ParseNaN _ANSI_ARGS_(( int signum, CONST char** end )); -static double SafeLdExp _ANSI_ARGS_(( double fraction, int exponent )); +static double RefineResult(double approx, CONST char *start, int nDigits, + long exponent); +static double ParseNaN(int signum, CONST char **end); +static double SafeLdExp(double fraction, int exponent); /* *---------------------------------------------------------------------- @@ -146,55 +124,46 @@ static double SafeLdExp _ANSI_ARGS_(( double fraction, int exponent )); * Scans a double from a string. * * Results: - * Returns the scanned number. In the case of underflow, returns - * an appropriately signed zero; in the case of overflow, returns - * an appropriately signed HUGE_VAL. + * Returns the scanned number. In the case of underflow, returns an + * appropriately signed zero; in the case of overflow, returns an + * appropriately signed HUGE_VAL. * * Side effects: - * Stores a pointer to the end of the scanned number in '*endPtr', - * if endPtr is not NULL. If '*endPtr' is equal to 's' on return from - * this function, it indicates that the input string could not be - * recognized as a number. - * In the case of underflow or overflow, 'errno' is set to ERANGE. + * Stores a pointer to the end of the scanned number in '*endPtr', if + * endPtr is not NULL. If '*endPtr' is equal to 's' on return from this + * function, it indicates that the input string could not be recognized + * as a number. In the case of underflow or overflow, 'errno' is set to + * ERANGE. * *------------------------------------------------------------------------ */ double -TclStrToD( CONST char* s, - /* String to scan */ - CONST char ** endPtr ) - /* Pointer to the end of the scanned number */ +TclStrToD(CONST char *s, /* String to scan. */ + CONST char **endPtr) /* Pointer to the end of the scanned number. */ { - - CONST char* p = s; - CONST char* startOfSignificand = NULL; - /* Start of the significand in the - * string */ - int signum = 0; /* Sign of the significand */ + const char *p = s; + const char *startOfSignificand = NULL; + /* Start of the significand in the string. */ + int signum = 0; /* Sign of the significand. */ double exactSignificand = 0.0; - /* Significand, represented exactly - * as a floating-point number */ - int seenDigit = 0; /* Flag == 1 if a digit has been seen */ - int nSigDigs = 0; /* Number of significant digits presented */ - int nDigitsAfterDp = 0; /* Number of digits after the decimal point */ - int nTrailZero = 0; /* Number of trailing zeros in the - * significand */ - long exponent = 0; /* Exponent */ - int seenDp = 0; /* Flag == 1 if decimal point has been seen */ - - char c; /* One character extracted from the input */ - - /* - * v must be 'volatile double' on gc-ix86 to force correct rounding - * to IEEE double and not Intel double-extended. - */ - - volatile double v; /* Scanned value */ - int machexp; /* Exponent of the machine rep of the - * scanned value */ - int expt2; /* Exponent for computing first - * approximation to the true value */ + /* Significand, represented exactly as a + * floating-point number. */ + int seenDigit = 0; /* Flag == 1 if a digit has been seen. */ + int nSigDigs = 0; /* Number of significant digits presented. */ + int nDigitsAfterDp = 0; /* Number of digits after the decimal point. */ + int nTrailZero = 0; /* Number of trailing zeros in the + * significand. */ + long exponent = 0; /* Exponent. */ + int seenDp = 0; /* Flag == 1 if decimal point has been seen. */ + char c; /* One character extracted from the input. */ + volatile double v; /* Scanned value; must be 'volatile double' on + * gc-ix86 to force correct rounding to IEEE + * double and not Intel double-extended. */ + int machexp; /* Exponent of the machine rep of the scanned + * value. */ + int expt2; /* Exponent for computing first approximation + * to the true value. */ int i, j; /* @@ -202,25 +171,32 @@ TclStrToD( CONST char* s, * This causes the result of double-precision calculations to be rounded * twice: once to the precision of double-extended and then again to the * precision of double. Double-rounding introduces gratuitous errors of - * 1 ulp, so we need to change rounding mode to 53-bits. + * one ulp, so we need to change rounding mode to 53-bits. */ -#if defined(__GNUC__) && defined(__i386) - fpu_control_t roundTo53Bits = 0x027f; +#ifdef ADJUST_FPU_CONTROL_WORD + fpu_control_t roundTo53Bits = FPU_IEEE_ROUNDING; fpu_control_t oldRoundingMode; - _FPU_GETCW( oldRoundingMode ); - _FPU_SETCW( roundTo53Bits ); + _FPU_GETCW(oldRoundingMode); + _FPU_SETCW(roundTo53Bits); +# define RestoreRoundingMode() _FPU_SETCW(oldRoundingMode) +#else +# define RestoreRoundingMode() (void) 0 /* Do nothing */ #endif - /* Discard leading whitespace */ + /* + * Discard leading whitespace from input. + */ - while ( isspace( *p ) ) { + while (isspace(UCHAR(*p))) { ++p; } - /* Determine the sign of the significand */ + /* + * Determine the sign of the significand. + */ - switch( *p ) { + switch (*p) { case '-': signum = 1; /* FALLTHROUGH */ @@ -228,48 +204,50 @@ TclStrToD( CONST char* s, ++p; } - /* Discard leading zeroes */ + /* + * Discard leading zeroes from input. + */ - while ( *p == '0' ) { + while (*p == '0') { seenDigit = 1; ++p; } - /* - * Scan digits from the significand. Simultaneously, keep track - * of the number of digits after the decimal point. Maintain - * a pointer to the start of the significand. Keep "exactSignificand" - * equal to the conversion of the DBL_DIG most significant digits. + /* + * Scan digits from the significand. Simultaneously, keep track of the + * number of digits after the decimal point. Maintain a pointer to the + * start of the significand. Keep "exactSignificand" equal to the + * conversion of the DBL_DIG most significant digits. */ - for ( ; ; ) { + for (;;) { c = *p; - if ( c == '.' && !seenDp ) { + if (c == '.' && !seenDp) { seenDp = 1; ++p; - } else if ( isdigit( UCHAR(c) ) ) { - if ( c == '0' ) { - if ( startOfSignificand != NULL ) { + } else if (isdigit(UCHAR(c))) { + if (c == '0') { + if (startOfSignificand != NULL) { ++nTrailZero; } } else { - if ( startOfSignificand == NULL ) { + if (startOfSignificand == NULL) { startOfSignificand = p; - } else if ( nTrailZero ) { - if ( nTrailZero + nSigDigs < DBL_DIG ) { - exactSignificand *= pow10[ nTrailZero ]; - } else if ( nSigDigs < DBL_DIG ) { - exactSignificand *= pow10[ DBL_DIG - nSigDigs ]; + } else if (nTrailZero) { + if (nTrailZero + nSigDigs < DBL_DIG) { + exactSignificand *= pow10[nTrailZero]; + } else if (nSigDigs < DBL_DIG) { + exactSignificand *= pow10[DBL_DIG - nSigDigs]; } nSigDigs += nTrailZero; } - if ( nSigDigs < DBL_DIG ) { + if (nSigDigs < DBL_DIG) { exactSignificand = 10. * exactSignificand + (c - '0'); } ++nSigDigs; nTrailZero = 0; } - if ( seenDp ) { + if (seenDp) { ++nDigitsAfterDp; } seenDigit = 1; @@ -280,29 +258,28 @@ TclStrToD( CONST char* s, } /* - * At this point, we've scanned the significand, and p points - * to the character beyond it. "startOfSignificand" is the first - * non-zero character in the significand. "nSigDigs" is the number - * of significant digits of the significand, not including any - * trailing zeroes. "exactSignificand" is a floating point number - * that represents, without loss of precision, the first - * min(DBL_DIG,n) digits of the significand. "nDigitsAfterDp" - * is the number of digits after the decimal point, again excluding - * trailing zeroes. + * At this point, we've scanned the significand, and p points to the + * character beyond it. "startOfSignificand" is the first non-zero + * character in the significand. "nSigDigs" is the number of significant + * digits of the significand, not including any trailing zeroes. + * "exactSignificand" is a floating point number that represents, without + * loss of precision, the first min(DBL_DIG,n) digits of the significand. + * "nDigitsAfterDp" is the number of digits after the decimal point, again + * excluding trailing zeroes. * * Now scan 'E' format */ exponent = 0; - if ( seenDigit && ( *p == 'e' || *p == 'E' ) ) { - CONST char* stringSave = p; + if (seenDigit && (*p == 'e' || *p == 'E')) { + const char* stringSave = p; ++p; c = *p; - if ( isdigit( UCHAR( c ) ) || c == '+' || c == '-' ) { + if (isdigit(UCHAR(c)) || c == '+' || c == '-') { errno = 0; - exponent = strtol( p, (char**)&p, 10 ); - if ( errno == ERANGE ) { - if ( exponent > 0 ) { + exponent = strtol(p, (char**)&p, 10); + if (errno == ERANGE) { + if (exponent > 0) { v = HUGE_VAL; } else { v = 0.0; @@ -311,68 +288,64 @@ TclStrToD( CONST char* s, goto returnValue; } } - if ( p == stringSave + 1 ) { + if (p == stringSave+1) { p = stringSave; exponent = 0; } } - exponent = exponent + nTrailZero - nDigitsAfterDp; + exponent += nTrailZero - nDigitsAfterDp; /* - * If we come here with no significant digits, we might still be - * looking at Inf or NaN. Go parse them. + * If we come here with no significant digits, we might still be looking + * at Inf or NaN. Go parse them. */ - if ( !seenDigit ) { - - /* Test for Inf */ - - if ( c == 'I' || c == 'i' ) { + if (!seenDigit) { + /* + * Test for Inf or Infinity (in any case). + */ - if ( ( p[1] == 'N' || p[1] == 'n' ) - && ( p[2] == 'F' || p[2] == 'f' ) ) { + if (c == 'I' || c == 'i') { + if ((p[1] == 'N' || p[1] == 'n') + && (p[2] == 'F' || p[2] == 'f')) { p += 3; - if ( ( p[0] == 'I' || p[0] == 'i' ) - && ( p[1] == 'N' || p[1] == 'n' ) - && ( p[2] == 'I' || p[2] == 'i' ) - && ( p[3] == 'T' || p[3] == 't' ) - && ( p[4] == 'Y' || p[1] == 'y' ) ) { + if ((p[0] == 'I' || p[0] == 'i') + && (p[1] == 'N' || p[1] == 'n') + && (p[2] == 'I' || p[2] == 'i') + && (p[3] == 'T' || p[3] == 't') + && (p[4] == 'Y' || p[1] == 'y')) { p += 5; } errno = ERANGE; v = HUGE_VAL; - if ( endPtr != NULL ) { + if (endPtr != NULL) { *endPtr = p; } goto returnValue; } - #ifdef IEEE_FLOATING_POINT - - /* IEEE floating point supports NaN */ - - } else if ( (c == 'N' || c == 'n' ) - && ( sizeof(Tcl_WideUInt) == sizeof( double ) ) ) { - - if ( ( p[1] == 'A' || p[1] == 'a' ) - && ( p[2] == 'N' || p[2] == 'n' ) ) { + /* + * Only IEEE floating point supports NaN + */ + } else if ((c == 'N' || c == 'n') + && (sizeof(Tcl_WideUInt) == sizeof(double))) { + if ((p[1] == 'A' || p[1] == 'a') + && (p[2] == 'N' || p[2] == 'n')) { p += 3; - - if ( endPtr != NULL ) { + + if (endPtr != NULL) { *endPtr = p; } - - /* Restore FPU mode word */ -#if defined(__GNUC__) && defined(__i386) - _FPU_SETCW( oldRoundingMode ); -#endif - return ParseNaN( signum, endPtr ); + /* + * Restore FPU mode word. + */ + RestoreRoundingMode(); + return ParseNaN(signum, endPtr); } #endif - } goto error; @@ -382,162 +355,167 @@ TclStrToD( CONST char* s, * We've successfully scanned; update the end-of-element pointer. */ - if ( endPtr != NULL ) { + if (endPtr != NULL) { *endPtr = p; } - /* Test for zero. */ + /* + * Test for zero. + */ - if ( nSigDigs == 0 ) { + if (nSigDigs == 0) { v = 0.0; goto returnValue; } /* - * The easy cases are where we have an exact significand and - * the exponent is small enough that we can compute the value - * with only one roundoff. In addition to the cases where we - * can multiply or divide an exact-integer significand by an - * exact-integer power of 10, there is also David Gay's case - * where we can scale the significand by a power of 10 (still - * keeping it exact) and then multiply by an exact power of 10. - * The last case enables combinations like 83e25 that would - * otherwise require high precision arithmetic. + * The easy cases are where we have an exact significand and the exponent + * is small enough that we can compute the value with only one roundoff. + * In addition to the cases where we can multiply or divide an + * exact-integer significand by an exact-integer power of 10, there is + * also David Gay's case where we can scale the significand by a power of + * 10 (still keeping it exact) and then multiply by an exact power of 10. + * The last case enables combinations like 83e25 that would otherwise + * require high precision arithmetic. */ - if ( nSigDigs <= DBL_DIG ) { - if ( exponent >= 0 ) { - if ( exponent <= mmaxpow ) { - v = exactSignificand * pow10[ exponent ]; + if (nSigDigs <= DBL_DIG) { + if (exponent >= 0) { + if (exponent <= mmaxpow) { + v = exactSignificand * pow10[exponent]; goto returnValue; } else { int diff = DBL_DIG - nSigDigs; - if ( exponent - diff <= mmaxpow ) { - volatile double factor = exactSignificand * pow10[ diff ]; - v = factor * pow10[ exponent - diff ]; + if (exponent - diff <= mmaxpow) { + volatile double factor = exactSignificand * pow10[diff]; + v = factor * pow10[exponent - diff]; goto returnValue; } } - } else { - if ( exponent >= -mmaxpow ) { - v = exactSignificand / pow10[ -exponent ]; - goto returnValue; - } + } else if (exponent >= -mmaxpow) { + v = exactSignificand / pow10[-exponent]; + goto returnValue; } } - /* - * We don't have one of the easy cases, so we can't compute the - * scanned number exactly, and have to do it in multiple precision. - * Begin by testing for obvious overflows and underflows. + /* + * We don't have one of the easy cases, so we can't compute the scanned + * number exactly, and have to do it in multiple precision. Begin by + * testing for obvious overflows and underflows. */ - if ( nSigDigs + exponent - 1 > maxDigits ) { + if (nSigDigs + exponent - 1 > maxDigits) { v = HUGE_VAL; errno = ERANGE; goto returnValue; } - if ( nSigDigs + exponent - 1 < minDigits ) { + if (nSigDigs + exponent - 1 < minDigits) { errno = ERANGE; v = 0.; goto returnValue; } /* - * Nothing exceeds the boundaries of the tables, at least. - * Compute an approximate value for the number, with - * no possibility of overflow because we manage the exponent - * separately. + * Nothing exceeds the boundaries of the tables, at least. Compute an + * approximate value for the number, with no possibility of overflow + * because we manage the exponent separately. */ - if ( nSigDigs > DBL_DIG ) { + if (nSigDigs > DBL_DIG) { expt2 = exponent + nSigDigs - DBL_DIG; } else { expt2 = exponent; } - v = frexp( exactSignificand, &machexp ); - if ( expt2 > 0 ) { - v = frexp( v * pow10[ expt2 & 0xf ], &j ); + v = frexp(exactSignificand, &machexp); + if (expt2 > 0) { + v = frexp(v * pow10[expt2 & 0xf], &j); machexp += j; - for ( i = 4; i < 9; ++i ) { - if ( expt2 & ( 1 << i ) ) { - v = frexp( v * pow_10_2_n[ i ], &j ); + for (i=4 ; i<9 ; ++i) { + if (expt2 & (1 << i)) { + v = frexp(v * pow_10_2_n[i], &j); machexp += j; } } } else { - v = frexp( v / pow10[ (-expt2) & 0xf ], &j ); + v = frexp(v / pow10[(-expt2) & 0xf], &j); machexp += j; - for ( i = 4; i < 9; ++i ) { - if ( (-expt2) & ( 1 << i ) ) { - v = frexp( v / pow_10_2_n[ i ], &j ); + for (i=4 ; i<9 ; ++i) { + if ((-expt2) & (1 << i)) { + v = frexp(v / pow_10_2_n[i], &j); machexp += j; } } } /* - * A first approximation is that the result will be v * 2 ** machexp. - * v is greater than or equal to 0.5 and less than 1. - * If machexp > DBL_MAX_EXP * log2(FLT_RADIX), there is an overflow. - * Constrain the result to the smallest representible number to avoid - * premature underflow. + * A first approximation is that the result will be v * 2 ** machexp. v is + * greater than or equal to 0.5 and less than 1. If machexp > + * DBL_MAX_EXP*log2(FLT_RADIX), there is an overflow. Constrain the result + * to the smallest representible number to avoid premature underflow. */ - if ( machexp > DBL_MAX_EXP * log2FLT_RADIX ) { + if (machexp > DBL_MAX_EXP * log2FLT_RADIX) { v = HUGE_VAL; errno = ERANGE; goto returnValue; } - v = SafeLdExp( v, machexp ); - if ( v < tiny ) { + v = SafeLdExp(v, machexp); + if (v < tiny) { v = tiny; } - /* We have a first approximation in v. Now we need to refine it. */ + /* + * We have a first approximation in v. Now we need to refine it. + */ + + v = RefineResult(v, startOfSignificand, nSigDigs, exponent); - v = RefineResult( v, startOfSignificand, nSigDigs, exponent ); + /* + * In a very few cases, a second iteration is needed. e.g., 457e-102 + */ - /* In a very few cases, a second iteration is needed. e.g., 457e-102 */ - - v = RefineResult( v, startOfSignificand, nSigDigs, exponent ); + v = RefineResult(v, startOfSignificand, nSigDigs, exponent); - /* Handle underflow */ + /* + * Handle underflow. + */ returnValue: - if ( nSigDigs != 0 && v == 0.0 ) { + if (nSigDigs != 0 && v == 0.0) { errno = ERANGE; } - /* Return a number with correct sign */ + /* + * Return a number with correct sign. + */ - if ( signum ) { + if (signum) { v = -v; } - /* Restore FPU mode word */ - -#if defined(__GNUC__) && defined(__i386) - _FPU_SETCW( oldRoundingMode ); -#endif + /* + * Restore FPU mode word and return. + */ - return v; - - /* Come here on an invalid input */ + RestoreRoundingMode(); + return v; + + /* + * Come here on an invalid input. + */ error: - if ( endPtr != NULL ) { + if (endPtr != NULL) { *endPtr = s; } - /* Restore FPU mode word */ - -#if defined(__GNUC__) && defined(__i386) - _FPU_SETCW( oldRoundingMode ); -#endif - return 0.0; + /* + * Restore FPU mode word and return. + */ + RestoreRoundingMode(); + return 0.0; } /* @@ -545,10 +523,9 @@ TclStrToD( CONST char* s, * * RefineResult -- * - * Given a poor approximation to a floating point number, returns - * a better one (The better approximation is correct to within - * 1 ulp, and is entirely correct if the poor approximation is - * correct to 1 ulp.) + * Given a poor approximation to a floating point number, returns a + * better one. (The better approximation is correct to within 1 ulp, and + * is entirely correct if the poor approximation is correct to 1 ulp.) * * Results: * Returns the improved result. @@ -557,120 +534,119 @@ TclStrToD( CONST char* s, */ static double -RefineResult( double approxResult, - /* Approximate result of conversion */ - CONST char* sigStart, - /* Pointer to start of significand in - * input string. */ - int nSigDigs, /* Number of significant digits */ - long exponent ) /* Power of ten to multiply by significand */ +RefineResult(double approxResult, /* Approximate result of conversion. */ + CONST char* sigStart, + /* Pointer to start of significand in input + * string. */ + int nSigDigs, /* Number of significant digits. */ + long exponent) /* Power of ten to multiply by significand. */ { - - int M2, M5; /* Powers of 2 and of 5 needed to put - * the decimal and binary numbers over - * a common denominator. */ - double significand; /* Sigificand of the binary number */ - int binExponent; /* Exponent of the binary number */ - + int M2, M5; /* Powers of 2 and of 5 needed to put the + * decimal and binary numbers over a common + * denominator. */ + double significand; /* Sigificand of the binary number. */ + int binExponent; /* Exponent of the binary number. */ int msb; /* Most significant bit position of an - * intermediate result */ + * intermediate result. */ int nDigits; /* Number of mp_digit's in an intermediate - * result */ - mp_int twoMv; /* Approx binary value expressed as an - * exact integer scaled by the multiplier 2M */ - mp_int twoMd; /* Exact decimal value expressed as an - * exact integer scaled by the multiplier 2M */ - int scale; /* Scale factor for M */ - int multiplier; /* Power of two to scale M */ - double num, den; /* Numerator and denominator of the - * correction term */ - double quot; /* Correction term */ - double minincr; /* Lower bound on the absolute value - * of the correction term. */ + * result. */ + mp_int twoMv; /* Approx binary value expressed as an exact + * integer scaled by the multiplier 2M. */ + mp_int twoMd; /* Exact decimal value expressed as an exact + * integer scaled by the multiplier 2M. */ + int scale; /* Scale factor for M. */ + int multiplier; /* Power of two to scale M. */ + double num, den; /* Numerator and denominator of the correction + * term. */ + double quot; /* Correction term. */ + double minincr; /* Lower bound on the absolute value of the + * correction term. */ int i; - CONST char* p; + const char* p; /* - * The first approximation is always low. If we find that - * it's HUGE_VAL, we're done. + * The first approximation is always low. If we find that it's HUGE_VAL, + * we're done. */ - if ( approxResult == HUGE_VAL ) { + if (approxResult == HUGE_VAL) { return approxResult; } /* - * Find a common denominator for the decimal and binary fractions. - * The common denominator will be 2**M2 + 5**M5. + * Find a common denominator for the decimal and binary fractions. The + * common denominator will be 2**M2 + 5**M5. */ - significand = frexp( approxResult, &binExponent ); + significand = frexp(approxResult, &binExponent); i = mantBits - binExponent; - if ( i < 0 ) { + if (i < 0) { M2 = 0; } else { M2 = i; } - if ( exponent > 0 ) { + if (exponent > 0) { M5 = 0; } else { M5 = -exponent; - if ( (M5-1) > M2 ) { + if ((M5-1) > M2) { M2 = M5-1; } } - /* - * The floating point number is significand*2**binExponent. - * The 2**-1 bit of the significand (the most significant) - * corresponds to the 2**(binExponent+M2 + 1) bit of 2*M2*v. - * Allocate enough digits to hold that quantity, then - * convert the significand to a large integer, scaled + /* + * The floating point number is significand*2**binExponent. The 2**-1 bit + * of the significand (the most significant) corresponds to the + * 2**(binExponent+M2 + 1) bit of 2*M2*v. Allocate enough digits to hold + * that quantity, then convert the significand to a large integer, scaled * appropriately. Then multiply by the appropriate power of 5. */ - msb = binExponent + M2; /* 1008 */ + msb = binExponent + M2; /* 1008 */ nDigits = msb / DIGIT_BIT + 1; - mp_init_size( &twoMv, nDigits ); - i = ( msb % DIGIT_BIT + 1 ); + mp_init_size(&twoMv, nDigits); + i = (msb % DIGIT_BIT + 1); twoMv.used = nDigits; - significand *= SafeLdExp( 1.0, i ); - while ( -- nDigits >= 0 ) { + significand *= SafeLdExp(1.0, i); + while (--nDigits >= 0) { twoMv.dp[nDigits] = (mp_digit) significand; significand -= (mp_digit) significand; - significand = SafeLdExp( significand, DIGIT_BIT ); + significand = SafeLdExp(significand, DIGIT_BIT); } - for ( i = 0; i <= 8; ++i ) { - if ( M5 & ( 1 << i ) ) { - mp_mul( &twoMv, pow5+i, &twoMv ); + for (i=0 ; i<=8 ; ++i) { + if (M5 & (1 << i)) { + mp_mul(&twoMv, pow5+i, &twoMv); } } - - /* - * Collect the decimal significand as a high precision integer. - * The least significant bit corresponds to bit M2+exponent+1 - * so it will need to be shifted left by that many bits after - * being multiplied by 5**(M5+exponent). + + /* + * Collect the decimal significand as a high precision integer. The least + * significant bit corresponds to bit M2+exponent+1 so it will need to be + * shifted left by that many bits after being multiplied by + * 5**(M5+exponent). */ - mp_init( &twoMd ); mp_zero( &twoMd ); + mp_init(&twoMd); + mp_zero(&twoMd); i = nSigDigs; - for ( p = sigStart ; ; ++p ) { + for (p=sigStart ;; ++p) { char c = *p; - if ( isdigit( UCHAR( c ) ) ) { - mp_mul_d( &twoMd, (unsigned) 10, &twoMd ); - mp_add_d( &twoMd, (unsigned) (c - '0'), &twoMd ); + if (isdigit(UCHAR(c))) { + mp_mul_d(&twoMd, (unsigned) 10, &twoMd); + mp_add_d(&twoMd, (unsigned) (c - '0'), &twoMd); --i; - if ( i == 0 ) break; + if (i == 0) { + break; + } } } - for ( i = 0; i <= 8; ++i ) { - if ( (M5+exponent) & ( 1 << i ) ) { - mp_mul( &twoMd, pow5+i, &twoMd ); + for (i=0 ; i<=8 ; ++i) { + if ((M5+exponent) & (1 << i)) { + mp_mul(&twoMd, pow5+i, &twoMd); } } - mp_mul_2d( &twoMd, M2+exponent+1, &twoMd ); - mp_sub( &twoMd, &twoMv, &twoMd ); + mp_mul_2d(&twoMd, M2+exponent+1, &twoMd); + mp_sub(&twoMd, &twoMv, &twoMd); /* * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction @@ -680,49 +656,48 @@ RefineResult( double approxResult, scale = binExponent - mantBits - 1; - mp_set( &twoMv, 1 ); - for ( i = 0; i <= 8; ++i ) { - if ( M5 & ( 1 << i ) ) { - mp_mul( &twoMv, pow5+i, &twoMv ); + mp_set(&twoMv, 1); + for (i=0 ; i<=8 ; ++i) { + if (M5 & (1 << i)) { + mp_mul(&twoMv, pow5+i, &twoMv); } } multiplier = M2 + scale + 1; - if ( multiplier > 0 ) { - mp_mul_2d( &twoMv, multiplier, &twoMv ); - } else if ( multiplier < 0 ) { - mp_div_2d( &twoMv, -multiplier, &twoMv, NULL ); + if (multiplier > 0) { + mp_mul_2d(&twoMv, multiplier, &twoMv); + } else if (multiplier < 0) { + mp_div_2d(&twoMv, -multiplier, &twoMv, NULL); } /* - * If the result is less than unity, the error is less than 1/2 unit - * in the last place, so there's no correction to make. + * If the result is less than unity, the error is less than 1/2 unit in + * the last place, so there's no correction to make. */ - if ( mp_cmp_mag( &twoMd, &twoMv ) == MP_LT ) { + if (mp_cmp_mag(&twoMd, &twoMv) == MP_LT) { return approxResult; } - /* - * Convert the numerator and denominator of the corrector term - * accurately to floating point numbers. + /* + * Convert the numerator and denominator of the corrector term accurately + * to floating point numbers. */ - num = TclBignumToDouble( &twoMd ); - den = TclBignumToDouble( &twoMv ); + num = TclBignumToDouble(&twoMd); + den = TclBignumToDouble(&twoMv); - quot = SafeLdExp( num/den, scale ); - minincr = SafeLdExp( 1.0, binExponent - mantBits ); + quot = SafeLdExp(num/den, scale); + minincr = SafeLdExp(1.0, binExponent - mantBits); - if ( quot < 0. && quot > -minincr ) { + if (quot<0. && quot>-minincr) { quot = -minincr; - } else if ( quot > 0. && quot < minincr ) { + } else if (quot>0. && quot<minincr) { quot = minincr; } - mp_clear( &twoMd ); - mp_clear( &twoMv ); + mp_clear(&twoMd); + mp_clear(&twoMv); - return approxResult + quot; } @@ -731,70 +706,71 @@ RefineResult( double approxResult, * * ParseNaN -- * - * Parses a "not a number" from an input string, and returns the - * double precision NaN corresponding to it. + * Parses a "not a number" from an input string, and returns the double + * precision NaN corresponding to it. * * Side effects: * Advances endPtr to follow any (hex) in the input string. * - * If the NaN is followed by a left paren, a string of spaes - * and hexadecimal digits, and a right paren, endPtr is advanced - * to follow it. + * If the NaN is followed by a left paren, a string of spaes and + * hexadecimal digits, and a right paren, endPtr is advanced to follow + * it. * - * The string of hexadecimal digits is OR'ed into the resulting - * NaN, and the signum is set as well. Note that a signalling NaN - * is never returned. + * The string of hexadecimal digits is OR'ed into the resulting NaN, and + * the signum is set as well. Note that a signalling NaN is never + * returned. * *---------------------------------------------------------------------- */ -double -ParseNaN( int signum, /* Flag == 1 if minus sign has been - * seen in front of NaN */ - CONST char** endPtr ) - /* Pointer-to-pointer to char following "NaN" - * in the input string */ +static double +ParseNaN(int signum, /* Flag == 1 if minus sign has been seen in + * front of NaN. */ + CONST char** endPtr) /* Pointer-to-pointer to char following "NaN" + * in the input string. */ { - CONST char* p = *endPtr; + const char* p = *endPtr; char c; union { Tcl_WideUInt iv; double dv; } theNaN; - /* Scan off a hex number in parentheses. Embedded blanks are ok. */ + /* + * Scan off a hex number in parentheses. Embedded blanks are ok. + */ theNaN.iv = 0; - if ( *p == '(' ) { + if (*p == '(') { ++p; - for ( ; ; ) { + for (;;) { c = *p++; - if ( isspace( UCHAR(c) ) ) { + if (isspace(UCHAR(c))) { continue; - } else if ( c == ')' ) { + } else if (c == ')') { *endPtr = p; break; - } else if ( isdigit( UCHAR(c) ) ) { + } else if (isdigit(UCHAR(c))) { c -= '0'; - } else if ( c >= 'A' && c <= 'F' ) { - c = c - 'A' + 10; - } else if ( c >= 'a' && c <= 'f' ) { - c = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + c -= 'A' + 10; + } else if (c >= 'a' && c <= 'f') { + c -= 'a' + 10; } else { - theNaN.iv = ( ((Tcl_WideUInt) NAN_START) << 48 ) - | ( ((Tcl_WideUInt) signum) << 63 ); + theNaN.iv = (((Tcl_WideUInt) NAN_START) << 48) + | (((Tcl_WideUInt) signum) << 63); return theNaN.dv; } theNaN.iv = (theNaN.iv << 4) | c; } } - /* + /* * Mask the hex number down to the least significant 51 bits. */ - theNaN.iv &= ( ((Tcl_WideUInt) 1) << 51 ) - 1; - if ( signum ) { + theNaN.iv &= (((Tcl_WideUInt) 1) << 51) - 1; + if (signum) { theNaN.iv |= ((Tcl_WideUInt) 0xfff8) << 48; } else { theNaN.iv |= ((Tcl_WideUInt) NAN_START) << 48; @@ -812,68 +788,59 @@ ParseNaN( int signum, /* Flag == 1 if minus sign has been * Converts a double to a string of digits. * * Results: - * Returns the position of the character in the string - * after which the decimal point should appear. Since - * the string contains only significant digits, the - * position may be less than zero or greater than the - * length of the string. + * Returns the position of the character in the string after which the + * decimal point should appear. Since the string contains only + * significant digits, the position may be less than zero or greater than + * the length of the string. * * Side effects: - * Stores the digits in the given buffer and sets 'signum' - * according to the sign of the number. + * Stores the digits in the given buffer and sets 'signum' according to + * the sign of the number. * *---------------------------------------------------------------------- */ int -TclDoubleDigits( char * strPtr, /* Buffer in which to store the result, - * must have at least 18 chars */ - double v, /* Number to convert. Must be - * finite, and not NaN */ - int *signum ) /* Output: 1 if the number is negative. - * Should handle -0 correctly on the - * IEEE architecture. */ +TclDoubleDigits(char * strPtr, /* Buffer in which to store the result, must + * have at least 18 chars. */ + double v, /* Number to convert. Must be finite, and not + * NaN. */ + int *signum) /* Output: 1 if the number is negative. + * Should handle -0 correctly on the IEEE + * architecture. */ { - - double f; /* Significand of v */ - + double f; /* Significand of v. */ int e; /* Power of FLT_RADIX that satisfies * v = f * FLT_RADIX**e */ - - - int low_ok; - int high_ok; - - mp_int r; /* Scaled significand */ + int lowOK, highOK; + mp_int r; /* Scaled significand. */ mp_int s; /* Divisor such that v = r / s */ - mp_int mplus; /* Scaled epsilon: (r + 2* mplus) == - * v(+) where v(+) is the floating point - * successor of v. */ - mp_int mminus; /* Scaled epsilon: (r - 2*mminus ) == - * v(-) where v(-) is the floating point + mp_int mplus; /* Scaled epsilon: (r + 2* mplus) == v(+) + * where v(+) is the floating point successor + * of v. */ + mp_int mminus; /* Scaled epsilon: (r - 2*mminus) == v(-) + * where v(-) is the floating point * predecessor of v. */ mp_int temp; - int rfac2 = 0; /* Powers of 2 and 5 by which large */ - int rfac5 = 0; /* integers should be scaled */ + int rfac5 = 0; /* integers should be scaled. */ int sfac2 = 0; int sfac5 = 0; int mplusfac2 = 0; int mminusfac2 = 0; - double a; char c; int i, k, n; - /* - * Take the absolute value of the number, and report the number's - * sign. Take special steps to preserve signed zeroes in IEEE floating - * point. (We can't use fpclassify, because that's a C9x feature and - * we still have to build on C89 compilers.) + /* + * Take the absolute value of the number, and report the number's sign. + * Take special steps to preserve signed zeroes in IEEE floating point. + * (We can't use fpclassify, because that's a C9x feature and we still + * have to build on C89 compilers.) */ #ifndef IEEE_FLOATING_POINT - if ( v >= 0.0 ) { + if (v >= 0.0) { *signum = 0; } else { *signum = 1; @@ -885,159 +852,152 @@ TclDoubleDigits( char * strPtr, /* Buffer in which to store the result, double dv; } bitwhack; bitwhack.dv = v; - if ( bitwhack.iv & ( (Tcl_WideUInt) 1 << 63 ) ) { + if (bitwhack.iv & ((Tcl_WideUInt) 1 << 63)) { *signum = 1; - bitwhack.iv &= ~( (Tcl_WideUInt) 1 << 63 ); + bitwhack.iv &= ~((Tcl_WideUInt) 1 << 63); v = bitwhack.dv; } else { *signum = 0; } #endif - /* Handle zero specially */ + /* + * Handle zero specially. + */ - if ( v == 0.0 ) { + if (v == 0.0) { *strPtr++ = '0'; *strPtr++ = '\0'; return 1; } - /* + /* * Develop f and e such that v = f * FLT_RADIX**e, with * 1.0/FLT_RADIX <= f < 1. */ - f = frexp( v, &e ); + f = frexp(v, &e); n = e % log2FLT_RADIX; - if ( n > 0 ) { + if (n > 0) { n -= log2FLT_RADIX; e += 1; } - f *= ldexp( 1.0, n ); - e = ( e - n ) / log2FLT_RADIX; - if ( f == 1.0 ) { + f *= ldexp(1.0, n); + e = (e - n) / log2FLT_RADIX; + if (f == 1.0) { f = 1.0 / FLT_RADIX; e += 1; } /* - * If the original number was denormalized, adjust e and f to be - * denormal as well. + * If the original number was denormalized, adjust e and f to be denormal + * as well. */ - if ( e < DBL_MIN_EXP ) { - n = mantBits + ( e - DBL_MIN_EXP ) * log2FLT_RADIX; - f = ldexp( f, ( e - DBL_MIN_EXP ) * log2FLT_RADIX ); + if (e < DBL_MIN_EXP) { + n = mantBits + (e - DBL_MIN_EXP)*log2FLT_RADIX; + f = ldexp(f, (e - DBL_MIN_EXP)*log2FLT_RADIX); e = DBL_MIN_EXP; - n = ( n + DIGIT_BIT - 1 ) / DIGIT_BIT; + n = (n + DIGIT_BIT - 1) / DIGIT_BIT; } else { n = mantDIGIT; } /* * Now extract the base-2**DIGIT_BIT digits of f into a multi-precision - * integer r. Preserve the invariant v = r * 2**rfac2 * FLT_RADIX**e - * by adjusting e. + * integer r. Preserve the invariant v = r * 2**rfac2 * FLT_RADIX**e by + * adjusting e. */ - + a = f; n = mantDIGIT; - mp_init_size( &r, n ); + mp_init_size(&r, n); r.used = n; r.sign = MP_ZPOS; - i = ( mantBits % DIGIT_BIT ); - if ( i == 0 ) { + i = (mantBits % DIGIT_BIT); + if (i == 0) { i = DIGIT_BIT; } - while ( n > 0 ) { - a *= ldexp( 1.0, i ); + while (n > 0) { + a *= ldexp(1.0, i); i = DIGIT_BIT; r.dp[--n] = (mp_digit) a; a -= (mp_digit) a; } e -= DBL_MANT_DIG; - low_ok = high_ok = ( mp_iseven( &r ) ); + lowOK = highOK = (mp_iseven(&r)); - /* - * We are going to want to develop integers r, s, mplus, and mminus - * such that v = r / s, v(+)-v / 2 = mplus / s; v-v(-) / 2 = mminus / s - * and then scale either s or r, mplus, mminus by an appropriate - * power of ten. + /* + * We are going to want to develop integers r, s, mplus, and mminus such + * that v = r / s, v(+)-v / 2 = mplus / s; v-v(-) / 2 = mminus / s and + * then scale either s or r, mplus, mminus by an appropriate power of ten. * - * We actually do this by keeping track of the powers of 2 and 5 - * by which f is multiplied to yield v and by which 1 is multiplied - * to yield s, mplus, and mminus. + * We actually do this by keeping track of the powers of 2 and 5 by which + * f is multiplied to yield v and by which 1 is multiplied to yield s, + * mplus, and mminus. */ - if ( e >= 0 ) { - + if (e >= 0) { int bits = e * log2FLT_RADIX; - if ( f != 1.0 / FLT_RADIX ) { - - /* Normal case, m+ and m- are both FLT_RADIX**e */ + if (f != 1.0/FLT_RADIX) { + /* + * Normal case, m+ and m- are both FLT_RADIX**e + */ rfac2 += bits + 1; sfac2 = 1; mplusfac2 = bits; mminusfac2 = bits; - } else { - - /* + /* * If f is equal to the smallest significand, then we need another - * factor of FLT_RADIX in s to cope with stepping to - * the next smaller exponent when going to e's predecessor. + * factor of FLT_RADIX in s to cope with stepping to the next + * smaller exponent when going to e's predecessor. */ rfac2 += bits + log2FLT_RADIX - 1; sfac2 = 1 + log2FLT_RADIX; mplusfac2 = bits + log2FLT_RADIX; mminusfac2 = bits; - } - } else { - - /* v has digits after the binary point */ - - if ( e <= DBL_MIN_EXP - DBL_MANT_DIG - || f != 1.0 / FLT_RADIX ) { - - /* - * Either f isn't the smallest significand or e is - * the smallest exponent. mplus and mminus will both be 1. + /* + * v has digits after the binary point + */ + + if (e <= DBL_MIN_EXP-DBL_MANT_DIG || f != 1.0/FLT_RADIX) { + /* + * Either f isn't the smallest significand or e is the smallest + * exponent. mplus and mminus will both be 1. */ rfac2 += 1; sfac2 = 1 - e * log2FLT_RADIX; mplusfac2 = 0; mminusfac2 = 0; - } else { - - /* + /* * f is the smallest significand, but e is not the smallest - * exponent. We need to scale by FLT_RADIX again to cope - * with the fact that v's predecessor has a smaller exponent. + * exponent. We need to scale by FLT_RADIX again to cope with the + * fact that v's predecessor has a smaller exponent. */ rfac2 += 1 + log2FLT_RADIX; - sfac2 = 1 + log2FLT_RADIX * ( 1 - e ); + sfac2 = 1 + log2FLT_RADIX * (1 - e); mplusfac2 = FLT_RADIX; mminusfac2 = 0; - } } - /* - * Estimate the highest power of ten that will be - * needed to hold the result. + /* + * Estimate the highest power of ten that will be needed to hold the + * result. */ - k = (int) ceil( log( v ) / log( 10. ) ); - if ( k >= 0 ) { + k = (int) ceil(log(v) / log(10.)); + if (k >= 0) { sfac2 += k; sfac5 = k; } else { @@ -1051,88 +1011,88 @@ TclDoubleDigits( char * strPtr, /* Buffer in which to store the result, * Scale r, s, mplus, mminus by the appropriate powers of 2 and 5. */ - mp_init_set( &mplus, 1 ); - for ( i = 0; i <= 8; ++i ) { - if ( rfac5 & ( 1 << i ) ) { - mp_mul( &mplus, pow5+i, &mplus ); + mp_init_set(&mplus, 1); + for (i=0 ; i<=8 ; ++i) { + if (rfac5 & (1 << i)) { + mp_mul(&mplus, pow5+i, &mplus); } } - mp_mul( &r, &mplus, &r ); - mp_mul_2d( &r, rfac2, &r ); - mp_init_copy( &mminus, &mplus ); - mp_mul_2d( &mplus, mplusfac2, &mplus ); - mp_mul_2d( &mminus, mminusfac2, &mminus ); - mp_init_set( &s, 1 ); - for ( i = 0; i <= 8; ++i ) { - if ( sfac5 & ( 1 << i ) ) { - mp_mul( &s, pow5+i, &s ); + mp_mul(&r, &mplus, &r); + mp_mul_2d(&r, rfac2, &r); + mp_init_copy(&mminus, &mplus); + mp_mul_2d(&mplus, mplusfac2, &mplus); + mp_mul_2d(&mminus, mminusfac2, &mminus); + mp_init_set(&s, 1); + for (i=0 ; i<=8 ; ++i) { + if (sfac5 & (1 << i)) { + mp_mul(&s, pow5+i, &s); } } - mp_mul_2d( &s, sfac2, &s ); + mp_mul_2d(&s, sfac2, &s); /* - * It is possible for k to be off by one because we used an - * inexact logarithm. + * It is possible for k to be off by one because we used an inexact + * logarithm. */ - mp_init( &temp ); - mp_add( &r, &mplus, &temp ); - i = mp_cmp_mag( &temp, &s ); - if ( i > 0 || ( high_ok && i == 0 ) ) { - mp_mul_d( &s, 10, &s ); + mp_init(&temp); + mp_add(&r, &mplus, &temp); + i = mp_cmp_mag(&temp, &s); + if (i>0 || (highOK && i==0)) { + mp_mul_d(&s, 10, &s); ++k; } else { - mp_mul_d( &temp, 10, &temp ); - i = mp_cmp_mag( &temp, &s ); - if ( i < 0 || ( high_ok && i == 0 ) ) { - mp_mul_d( &r, 10, &r ); - mp_mul_d( &mplus, 10, &mplus ); - mp_mul_d( &mminus, 10, &mminus ); + mp_mul_d(&temp, 10, &temp); + i = mp_cmp_mag(&temp, &s); + if (i<0 || (highOK && i==0)) { + mp_mul_d(&r, 10, &r); + mp_mul_d(&mplus, 10, &mplus); + mp_mul_d(&mminus, 10, &mminus); --k; } } /* - * At this point, k contains the power of ten by which we're - * scaling the result. r/s is at least 1/10 and strictly less - * than ten, and v = r/s * 10**k. mplus and mminus give the - * rounding limits. + * At this point, k contains the power of ten by which we're scaling the + * result. r/s is at least 1/10 and strictly less than ten, and v = r/s * + * 10**k. mplus and mminus give the rounding limits. */ - for ( ; ; ) { + for (;;) { int tc1, tc2; - mp_mul_d( &r, 10, &r ); - mp_div( &r, &s, &temp, &r ); /* temp = 10r / s; r = 10r mod s */ + + mp_mul_d(&r, 10, &r); + mp_div(&r, &s, &temp, &r); /* temp = 10r / s; r = 10r mod s */ i = temp.dp[0]; - mp_mul_d( &mplus, 10, &mplus ); - mp_mul_d( &mminus, 10, &mminus ); - tc1 = mp_cmp_mag( &r, &mminus ); - if ( low_ok ) { - tc1 = ( tc1 <= 0 ); + mp_mul_d(&mplus, 10, &mplus); + mp_mul_d(&mminus, 10, &mminus); + tc1 = mp_cmp_mag(&r, &mminus); + if (lowOK) { + tc1 = (tc1 <= 0); } else { - tc1 = ( tc1 < 0 ); + tc1 = (tc1 < 0); } - mp_add( &r, &mplus, &temp ); - tc2 = mp_cmp_mag( &temp, &s ); - if ( high_ok ) { - tc2 = ( tc2 >= 0 ); + mp_add(&r, &mplus, &temp); + tc2 = mp_cmp_mag(&temp, &s); + if (highOK) { + tc2 = (tc2 >= 0); } else { - tc2= ( tc2 > 0 ); + tc2= (tc2 > 0); } - if ( ! tc1 ) { - if ( !tc2 ) { + if (!tc1) { + if (!tc2) { *strPtr++ = '0' + i; } else { c = (char) (i + '1'); break; } } else { - if ( !tc2 ) { + if (!tc2) { c = (char) (i + '0'); } else { - mp_mul_2d( &r, 1, &r ); - n = mp_cmp_mag( &r, &s ); - if ( n < 0 ) { + mp_mul_2d(&r, 1, &r); + n = mp_cmp_mag(&r, &s); + if (n < 0) { c = (char) (i + '0'); } else { c = (char) (i + '1'); @@ -1144,11 +1104,12 @@ TclDoubleDigits( char * strPtr, /* Buffer in which to store the result, *strPtr++ = c; *strPtr++ = '\0'; - /* Free memory */ + /* + * Free memory, and return. + */ - mp_clear_multi( &r, &s, &mplus, &mminus, &temp, NULL ); + mp_clear_multi(&r, &s, &mplus, &mminus, &temp, NULL); return k; - } /* @@ -1156,56 +1117,56 @@ TclDoubleDigits( char * strPtr, /* Buffer in which to store the result, * * TclInitDoubleConversion -- * - * Initializes constants that are needed for conversions to and - * from 'double' + * Initializes constants that are needed for conversions to and from + * 'double' * * Results: * None. * * Side effects: - * The log base 2 of the floating point radix, the number of - * bits in a double mantissa, and a table of the powers of five - * and ten are computed and stored. + * The log base 2 of the floating point radix, the number of bits in a + * double mantissa, and a table of the powers of five and ten are + * computed and stored. * *---------------------------------------------------------------------- */ void -TclInitDoubleConversion( void ) +TclInitDoubleConversion(void) { int i; int x; double d; - if ( frexp( (double) FLT_RADIX, &log2FLT_RADIX ) != 0.5 ) { - Tcl_Panic( "This code doesn't work on a decimal machine!" ); + + if (frexp((double) FLT_RADIX, &log2FLT_RADIX) != 0.5) { + Tcl_Panic("This code doesn't work on a decimal machine!"); } --log2FLT_RADIX; mantBits = DBL_MANT_DIG * log2FLT_RADIX; d = 1.0; - x = (int) (DBL_MANT_DIG * log((double) FLT_RADIX) / log( 5.0 )); - if ( x < MAXPOW ) { + x = (int) (DBL_MANT_DIG * log((double) FLT_RADIX) / log(5.0)); + if (x < MAXPOW) { mmaxpow = x; } else { mmaxpow = MAXPOW; } - for ( i = 0; i <= mmaxpow; ++i ) { + for (i=0 ; i<=mmaxpow ; ++i) { pow10[i] = d; d *= 10.0; } - for ( i = 0; i < 9; ++i ) { - mp_init( pow5 + i ); + for (i=0 ; i<9 ; ++i) { + mp_init(pow5 + i); } - mp_set( pow5, 5 ); - for ( i = 0; i < 8; ++i ) { - mp_sqr( pow5+i, pow5+i+1 ); + mp_set(pow5, 5); + for (i=0 ; i<8 ; ++i) { + mp_sqr(pow5+i, pow5+i+1); } - tiny = SafeLdExp( 1.0, DBL_MIN_EXP * log2FLT_RADIX - mantBits ); - maxDigits = (int) ((DBL_MAX_EXP * log((double) FLT_RADIX) - + 0.5 * log(10.)) - / log( 10. )); - minDigits = (int) floor ( ( DBL_MIN_EXP - DBL_MANT_DIG ) - * log( (double) FLT_RADIX ) / log( 10. ) ); - mantDIGIT = ( mantBits + DIGIT_BIT - 1 ) / DIGIT_BIT; + tiny = SafeLdExp(1.0, DBL_MIN_EXP * log2FLT_RADIX - mantBits); + maxDigits = (int) + ((DBL_MAX_EXP * log((double) FLT_RADIX) + log(10.)/2) / log(10.)); + minDigits = (int) + floor((DBL_MIN_EXP-DBL_MANT_DIG)*log((double)FLT_RADIX)/log(10.)); + mantDIGIT = (mantBits + DIGIT_BIT - 1) / DIGIT_BIT; } /* @@ -1228,8 +1189,8 @@ void TclFinalizeDoubleConversion() { int i; - for ( i = 0; i < 9; ++i ) { - mp_clear( pow5 + i ); + for (i=0 ; i<9 ; ++i) { + mp_clear(pow5 + i); } } @@ -1238,19 +1199,18 @@ TclFinalizeDoubleConversion() * * TclBignumToDouble -- * - * Convert an arbitrary-precision integer to a native floating - * point number. + * Convert an arbitrary-precision integer to a native floating point + * number. * * Results: - * Returns the converted number. Sets errno to ERANGE if the - * number is too large to convert. + * Returns the converted number. Sets errno to ERANGE if the number is + * too large to convert. * *---------------------------------------------------------------------- */ double -TclBignumToDouble( mp_int* a ) - /* Integer to convert */ +TclBignumToDouble(mp_int *a) /* Integer to convert. */ { mp_int b; int bits; @@ -1258,46 +1218,54 @@ TclBignumToDouble( mp_int* a ) int i; double r; - /* Determine how many bits we need, and extract that many from - * the input. Round to nearest unit in the last place. */ + /* + * Determine how many bits we need, and extract that many from the input. + * Round to nearest unit in the last place. + */ - bits = mp_count_bits( a ); - if ( bits > DBL_MAX_EXP * log2FLT_RADIX ) { + bits = mp_count_bits(a); + if (bits > DBL_MAX_EXP*log2FLT_RADIX) { errno = ERANGE; return HUGE_VAL; } shift = mantBits + 1 - bits; - mp_init( &b ); - if ( shift > 0 ) { - mp_mul_2d( a, shift, &b ); - } else if ( shift < 0 ) { - mp_div_2d( a, -shift, &b, NULL ); + mp_init(&b); + if (shift > 0) { + mp_mul_2d(a, shift, &b); + } else if (shift < 0) { + mp_div_2d(a, -shift, &b, NULL); } else { - mp_copy( a, &b ); + mp_copy(a, &b); } - mp_add_d( &b, 1, &b ); - mp_div_2d( &b, 1, &b, NULL ); + mp_add_d(&b, 1, &b); + mp_div_2d(&b, 1, &b, NULL); - /* Accumulate the result, one mp_digit at a time */ + /* + * Accumulate the result, one mp_digit at a time. + */ r = 0.0; - for ( i = b.used-1; i >= 0; --i ) { - r = ldexp( r, DIGIT_BIT ) + b.dp[i]; + for (i=b.used-1 ; i>=0 ; --i) { + r = ldexp(r, DIGIT_BIT) + b.dp[i]; } - mp_clear( &b ); + mp_clear(&b); - /* Scale the result to the correct number of bits. */ + /* + * Scale the result to the correct number of bits. + */ - r = ldexp( r, bits - mantBits ); + r = ldexp(r, bits - mantBits); - /* Return the result with the appropriate sign. */ + /* + * Return the result with the appropriate sign. + */ - if ( a->sign == MP_ZPOS ) { + if (a->sign == MP_ZPOS) { return r; } else { return -r; } -} +} /* *---------------------------------------------------------------------- @@ -1309,25 +1277,25 @@ TclBignumToDouble( mp_int* a ) * Results: * Returns the appropriately scaled value. * - * On some platforms, 'ldexp' fails when presented with a number - * too small to represent as a normalized double. This routine - * does 'ldexp' in two steps for those numbers, to return correctly - * denormalized values. + * On some platforms, 'ldexp' fails when presented with a number too + * small to represent as a normalized double. This routine does 'ldexp' + * in two steps for those numbers, to return correctly denormalized + * values. * *---------------------------------------------------------------------- */ static double -SafeLdExp( double fract, int expt ) +SafeLdExp(double fract, int expt) { int minexpt = DBL_MIN_EXP * log2FLT_RADIX; volatile double a, b, retval; - if ( expt < minexpt ) { - a = ldexp( fract, expt - mantBits - minexpt ); - b = ldexp( 1.0, mantBits + minexpt ); + if (expt < minexpt) { + a = ldexp(fract, expt - mantBits - minexpt); + b = ldexp(1.0, mantBits + minexpt); retval = a * b; } else { - retval = ldexp( fract, expt ); + retval = ldexp(fract, expt); } return retval; } @@ -1343,38 +1311,38 @@ SafeLdExp( double fract, int expt ) * None. * * Side effects: - * Stores the string representation in the supplied buffer, - * which must be at least TCL_DOUBLE_SPACE characters. + * Stores the string representation in the supplied buffer, which must be + * at least TCL_DOUBLE_SPACE characters. * *---------------------------------------------------------------------- */ void -TclFormatNaN( double value, /* The Not-a-Number to format */ - char* buffer ) /* String representation */ +TclFormatNaN(double value, /* The Not-a-Number to format. */ + char *buffer) /* String representation. */ { #ifndef IEEE_FLOATING_POINT - strcpy( buffer, "NaN" ); + strcpy(buffer, "NaN"); return; #else - union { double dv; Tcl_WideUInt iv; } bitwhack; bitwhack.dv = value; - if ( bitwhack.iv & ((Tcl_WideUInt) 1 << 63 ) ) { - bitwhack.iv &= ~ ((Tcl_WideUInt) 1 << 63 ); + if (bitwhack.iv & ((Tcl_WideUInt) 1 << 63)) { + bitwhack.iv &= ~ ((Tcl_WideUInt) 1 << 63); *buffer++ = '-'; } - *buffer++ = 'N'; *buffer++ = 'a'; *buffer++ = 'N'; + *buffer++ = 'N'; + *buffer++ = 'a'; + *buffer++ = 'N'; bitwhack.iv &= (((Tcl_WideUInt) 1) << 51) - 1; - if ( bitwhack.iv != 0 ) { - sprintf( buffer, "(%" TCL_LL_MODIFIER "x)", bitwhack.iv ); + if (bitwhack.iv != 0) { + sprintf(buffer, "(%" TCL_LL_MODIFIER "x)", bitwhack.iv); } else { *buffer = '\0'; } - -#endif +#endif /* IEEE_FLOATING_POINT */ } |