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