os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/compat/strtod.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* 
     2  * strtod.c --
     3  *
     4  *	Source code for the "strtod" library procedure.
     5  *
     6  * Copyright (c) 1988-1993 The Regents of the University of California.
     7  * Copyright (c) 1994 Sun Microsystems, Inc.
     8  *
     9  * See the file "license.terms" for information on usage and redistribution
    10  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    11  *
    12  * RCS: @(#) $Id: strtod.c,v 1.6 2002/02/25 14:26:12 dgp Exp $
    13  */
    14 
    15 #include "tclInt.h"
    16 #include "tclPort.h"
    17 #include <ctype.h>
    18 
    19 #ifndef TRUE
    20 #define TRUE 1
    21 #define FALSE 0
    22 #endif
    23 #ifndef NULL
    24 #define NULL 0
    25 #endif
    26 
    27 static int maxExponent = 511;	/* Largest possible base 10 exponent.  Any
    28 				 * exponent larger than this will already
    29 				 * produce underflow or overflow, so there's
    30 				 * no need to worry about additional digits.
    31 				 */
    32 static double powersOf10[] = {	/* Table giving binary powers of 10.  Entry */
    33     10.,			/* is 10^2^i.  Used to convert decimal */
    34     100.,			/* exponents into floating-point numbers. */
    35     1.0e4,
    36     1.0e8,
    37     1.0e16,
    38     1.0e32,
    39     1.0e64,
    40     1.0e128,
    41     1.0e256
    42 };
    43 
    44 /*
    45  *----------------------------------------------------------------------
    46  *
    47  * strtod --
    48  *
    49  *	This procedure converts a floating-point number from an ASCII
    50  *	decimal representation to internal double-precision format.
    51  *
    52  * Results:
    53  *	The return value is the double-precision floating-point
    54  *	representation of the characters in string.  If endPtr isn't
    55  *	NULL, then *endPtr is filled in with the address of the
    56  *	next character after the last one that was part of the
    57  *	floating-point number.
    58  *
    59  * Side effects:
    60  *	None.
    61  *
    62  *----------------------------------------------------------------------
    63  */
    64 
    65 double
    66 strtod(string, endPtr)
    67     CONST char *string;		/* A decimal ASCII floating-point number,
    68 				 * optionally preceded by white space.
    69 				 * Must have form "-I.FE-X", where I is the
    70 				 * integer part of the mantissa, F is the
    71 				 * fractional part of the mantissa, and X
    72 				 * is the exponent.  Either of the signs
    73 				 * may be "+", "-", or omitted.  Either I
    74 				 * or F may be omitted, or both.  The decimal
    75 				 * point isn't necessary unless F is present.
    76 				 * The "E" may actually be an "e".  E and X
    77 				 * may both be omitted (but not just one).
    78 				 */
    79     char **endPtr;		/* If non-NULL, store terminating character's
    80 				 * address here. */
    81 {
    82     int sign, expSign = FALSE;
    83     double fraction, dblExp, *d;
    84     register CONST char *p;
    85     register int c;
    86     int exp = 0;		/* Exponent read from "EX" field. */
    87     int fracExp = 0;		/* Exponent that derives from the fractional
    88 				 * part.  Under normal circumstatnces, it is
    89 				 * the negative of the number of digits in F.
    90 				 * However, if I is very long, the last digits
    91 				 * of I get dropped (otherwise a long I with a
    92 				 * large negative exponent could cause an
    93 				 * unnecessary overflow on I alone).  In this
    94 				 * case, fracExp is incremented one for each
    95 				 * dropped digit. */
    96     int mantSize;		/* Number of digits in mantissa. */
    97     int decPt;			/* Number of mantissa digits BEFORE decimal
    98 				 * point. */
    99     CONST char *pExp;		/* Temporarily holds location of exponent
   100 				 * in string. */
   101 
   102     /*
   103      * Strip off leading blanks and check for a sign.
   104      */
   105 
   106     p = string;
   107     while (isspace(UCHAR(*p))) {
   108 	p += 1;
   109     }
   110     if (*p == '-') {
   111 	sign = TRUE;
   112 	p += 1;
   113     } else {
   114 	if (*p == '+') {
   115 	    p += 1;
   116 	}
   117 	sign = FALSE;
   118     }
   119 
   120     /*
   121      * Count the number of digits in the mantissa (including the decimal
   122      * point), and also locate the decimal point.
   123      */
   124 
   125     decPt = -1;
   126     for (mantSize = 0; ; mantSize += 1)
   127     {
   128 	c = *p;
   129 	if (!isdigit(c)) {
   130 	    if ((c != '.') || (decPt >= 0)) {
   131 		break;
   132 	    }
   133 	    decPt = mantSize;
   134 	}
   135 	p += 1;
   136     }
   137 
   138     /*
   139      * Now suck up the digits in the mantissa.  Use two integers to
   140      * collect 9 digits each (this is faster than using floating-point).
   141      * If the mantissa has more than 18 digits, ignore the extras, since
   142      * they can't affect the value anyway.
   143      */
   144     
   145     pExp  = p;
   146     p -= mantSize;
   147     if (decPt < 0) {
   148 	decPt = mantSize;
   149     } else {
   150 	mantSize -= 1;			/* One of the digits was the point. */
   151     }
   152     if (mantSize > 18) {
   153 	fracExp = decPt - 18;
   154 	mantSize = 18;
   155     } else {
   156 	fracExp = decPt - mantSize;
   157     }
   158     if (mantSize == 0) {
   159 	fraction = 0.0;
   160 	p = string;
   161 	goto done;
   162     } else {
   163 	int frac1, frac2;
   164 	frac1 = 0;
   165 	for ( ; mantSize > 9; mantSize -= 1)
   166 	{
   167 	    c = *p;
   168 	    p += 1;
   169 	    if (c == '.') {
   170 		c = *p;
   171 		p += 1;
   172 	    }
   173 	    frac1 = 10*frac1 + (c - '0');
   174 	}
   175 	frac2 = 0;
   176 	for (; mantSize > 0; mantSize -= 1)
   177 	{
   178 	    c = *p;
   179 	    p += 1;
   180 	    if (c == '.') {
   181 		c = *p;
   182 		p += 1;
   183 	    }
   184 	    frac2 = 10*frac2 + (c - '0');
   185 	}
   186 	fraction = (1.0e9 * frac1) + frac2;
   187     }
   188 
   189     /*
   190      * Skim off the exponent.
   191      */
   192 
   193     p = pExp;
   194     if ((*p == 'E') || (*p == 'e')) {
   195 	p += 1;
   196 	if (*p == '-') {
   197 	    expSign = TRUE;
   198 	    p += 1;
   199 	} else {
   200 	    if (*p == '+') {
   201 		p += 1;
   202 	    }
   203 	    expSign = FALSE;
   204 	}
   205 	if (!isdigit(UCHAR(*p))) {
   206 	    p = pExp;
   207 	    goto done;
   208 	}
   209 	while (isdigit(UCHAR(*p))) {
   210 	    exp = exp * 10 + (*p - '0');
   211 	    p += 1;
   212 	}
   213     }
   214     if (expSign) {
   215 	exp = fracExp - exp;
   216     } else {
   217 	exp = fracExp + exp;
   218     }
   219 
   220     /*
   221      * Generate a floating-point number that represents the exponent.
   222      * Do this by processing the exponent one bit at a time to combine
   223      * many powers of 2 of 10. Then combine the exponent with the
   224      * fraction.
   225      */
   226     
   227     if (exp < 0) {
   228 	expSign = TRUE;
   229 	exp = -exp;
   230     } else {
   231 	expSign = FALSE;
   232     }
   233     if (exp > maxExponent) {
   234 	exp = maxExponent;
   235 	errno = ERANGE;
   236     }
   237     dblExp = 1.0;
   238     for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
   239 	if (exp & 01) {
   240 	    dblExp *= *d;
   241 	}
   242     }
   243     if (expSign) {
   244 	fraction /= dblExp;
   245     } else {
   246 	fraction *= dblExp;
   247     }
   248 
   249 done:
   250     if (endPtr != NULL) {
   251 	*endPtr = (char *) p;
   252     }
   253 
   254     if (sign) {
   255 	return -fraction;
   256     }
   257     return fraction;
   258 }