~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Cross Reference
BRL-CAD/src/other/tcl/compat/strtod.c

Version: ~ [ 7.24.0 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.