141806Sbostic /*-
241806Sbostic * Copyright (c) 1990 The Regents of the University of California.
341806Sbostic * All rights reserved.
441806Sbostic *
541806Sbostic * This code is derived from software contributed to Berkeley by
641806Sbostic * the Systems Programming Group of the University of Utah Computer
741806Sbostic * Science Department.
841806Sbostic *
941806Sbostic * %sccs.include.redist.c%
1041806Sbostic */
1141806Sbostic
1241806Sbostic #if defined(LIBC_SCCS) && !defined(lint)
13*47921Sdonn static char sccsid[] = "@(#)atof.c 5.2 (Berkeley) 04/12/91";
1441806Sbostic #endif /* LIBC_SCCS and not lint */
1541806Sbostic
16*47921Sdonn /*
17*47921Sdonn * simple atof() for IEEE 754 architectures
18*47921Sdonn */
19*47921Sdonn
20*47921Sdonn #include <machine/endian.h>
21*47921Sdonn #include <stdlib.h>
22*47921Sdonn #include <math.h>
2341806Sbostic #include <ctype.h>
2441806Sbostic
25*47921Sdonn static double twoemax = 9007199254740992.; /*2^53*/
2641806Sbostic
2741806Sbostic /* attempt to be as exact as possible */
28*47921Sdonn static struct {
29*47921Sdonn long low_word;
30*47921Sdonn long high_word;
31*47921Sdonn } exp5[] = {
32*47921Sdonn #if BYTE_ORDER == BIG_ENDIAN
3341806Sbostic { 0x40140000, 0x00000000 }, /* 5 */
3441806Sbostic { 0x40390000, 0x00000000 }, /* 25 */
3541806Sbostic { 0x40838800, 0x00000000 }, /* 625 */
3641806Sbostic { 0x4117d784, 0x00000000 }, /* 390625 */
3741806Sbostic { 0x4241c379, 0x37e08000 }, /* 152587890625 */
3841806Sbostic { 0x4493b8b5, 0xb5056e17 }, /* 2.3283064365387e+022 */
3941806Sbostic { 0x49384f03, 0xe93ff9f6 }, /* 5.42101086242753e+044 */
4041806Sbostic { 0x52827748, 0xf9301d33 }, /* 2.93873587705572e+089 */
4141806Sbostic { 0x65154fdd, 0x7f73bf3f } /* 8.63616855509445e+178 */
42*47921Sdonn #else /* BYTE_ORDER == LITTLE_ENDIAN */
43*47921Sdonn { 0x00000000, 0x40140000 }, /* 5 */
44*47921Sdonn { 0x00000000, 0x40390000 }, /* 25 */
45*47921Sdonn { 0x00000000, 0x40838800 }, /* 625 */
46*47921Sdonn { 0x00000000, 0x4117d784 }, /* 390625 */
47*47921Sdonn { 0x37e08000, 0x4241c379 }, /* 152587890625 */
48*47921Sdonn { 0xb5056e17, 0x4493b8b5 }, /* 2.3283064365387e+022 */
49*47921Sdonn { 0xe93ff9f6, 0x49384f03 }, /* 5.42101086242753e+044 */
50*47921Sdonn { 0xf9301d33, 0x52827748 }, /* 2.93873587705572e+089 */
51*47921Sdonn { 0x7f73bf3f, 0x65154fdd } /* 8.63616855509445e+178 */
5241806Sbostic #endif
5341806Sbostic };
5441806Sbostic
5541806Sbostic double
atof(p)5641806Sbostic atof(p)
57*47921Sdonn register const char *p;
5841806Sbostic {
59*47921Sdonn register int c;
60*47921Sdonn register int exp = 0;
61*47921Sdonn register int eexp = 0;
62*47921Sdonn double fl = 0;
63*47921Sdonn double flexp = 1.0;
64*47921Sdonn int bexp;
65*47921Sdonn int neg = 1;
66*47921Sdonn int negexp = 1;
6741806Sbostic
68*47921Sdonn while (isspace(*p))
69*47921Sdonn ++p;
7041806Sbostic
71*47921Sdonn if ((c = *p++) == '-')
72*47921Sdonn neg = -1;
73*47921Sdonn else if (c == '+')
74*47921Sdonn /* skip it */;
75*47921Sdonn else
76*47921Sdonn --p;
77*47921Sdonn
78*47921Sdonn while ((c = *p++) && isdigit(c))
79*47921Sdonn if (fl < twoemax)
80*47921Sdonn fl = 10 * fl + (c-'0');
81*47921Sdonn else
82*47921Sdonn ++exp;
83*47921Sdonn
8441806Sbostic if (c == '.')
85*47921Sdonn while ((c = *p++) && isdigit(c))
86*47921Sdonn if (fl < twoemax) {
87*47921Sdonn fl = 10 * fl + (c-'0');
88*47921Sdonn --exp;
89*47921Sdonn }
90*47921Sdonn
91*47921Sdonn if (c == 'E' || c == 'e') {
92*47921Sdonn if ((c = *p++) == '-')
93*47921Sdonn negexp = -1;
94*47921Sdonn else if (c == '+')
95*47921Sdonn /* skip it */;
96*47921Sdonn else
97*47921Sdonn --p;
98*47921Sdonn while ((c = *p++) && isdigit(c))
99*47921Sdonn eexp = 10 * eexp + (c-'0');
100*47921Sdonn if (negexp < 0)
101*47921Sdonn eexp = -eexp;
102*47921Sdonn exp += eexp;
10341806Sbostic }
104*47921Sdonn
10541806Sbostic bexp = exp;
106*47921Sdonn if (exp < 0)
107*47921Sdonn exp = -exp;
10841806Sbostic
109*47921Sdonn for (c = 0; exp && c < sizeof exp5 / sizeof exp5[0]; ++c) {
110*47921Sdonn if (exp & 1)
111*47921Sdonn flexp *= *(double *)&exp5[c];
112*47921Sdonn exp >>= 1;
11341806Sbostic }
11441806Sbostic
115*47921Sdonn if (bexp < 0)
116*47921Sdonn fl /= flexp;
117*47921Sdonn else
118*47921Sdonn fl *= flexp;
119*47921Sdonn
12041806Sbostic fl = ldexp(fl, bexp);
121*47921Sdonn
122*47921Sdonn return neg < 0 ? -fl : fl;
12341806Sbostic }
124