1 /*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * the Systems Programming Group of the University of Utah Computer
7 * Science Department.
8 *
9 * %sccs.include.redist.c%
10 */
11
12 #if defined(LIBC_SCCS) && !defined(lint)
13 static char sccsid[] = "@(#)atof.c 5.2 (Berkeley) 04/12/91";
14 #endif /* LIBC_SCCS and not lint */
15
16 /*
17 * simple atof() for IEEE 754 architectures
18 */
19
20 #include <machine/endian.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <ctype.h>
24
25 static double twoemax = 9007199254740992.; /*2^53*/
26
27 /* attempt to be as exact as possible */
28 static struct {
29 long low_word;
30 long high_word;
31 } exp5[] = {
32 #if BYTE_ORDER == BIG_ENDIAN
33 { 0x40140000, 0x00000000 }, /* 5 */
34 { 0x40390000, 0x00000000 }, /* 25 */
35 { 0x40838800, 0x00000000 }, /* 625 */
36 { 0x4117d784, 0x00000000 }, /* 390625 */
37 { 0x4241c379, 0x37e08000 }, /* 152587890625 */
38 { 0x4493b8b5, 0xb5056e17 }, /* 2.3283064365387e+022 */
39 { 0x49384f03, 0xe93ff9f6 }, /* 5.42101086242753e+044 */
40 { 0x52827748, 0xf9301d33 }, /* 2.93873587705572e+089 */
41 { 0x65154fdd, 0x7f73bf3f } /* 8.63616855509445e+178 */
42 #else /* BYTE_ORDER == LITTLE_ENDIAN */
43 { 0x00000000, 0x40140000 }, /* 5 */
44 { 0x00000000, 0x40390000 }, /* 25 */
45 { 0x00000000, 0x40838800 }, /* 625 */
46 { 0x00000000, 0x4117d784 }, /* 390625 */
47 { 0x37e08000, 0x4241c379 }, /* 152587890625 */
48 { 0xb5056e17, 0x4493b8b5 }, /* 2.3283064365387e+022 */
49 { 0xe93ff9f6, 0x49384f03 }, /* 5.42101086242753e+044 */
50 { 0xf9301d33, 0x52827748 }, /* 2.93873587705572e+089 */
51 { 0x7f73bf3f, 0x65154fdd } /* 8.63616855509445e+178 */
52 #endif
53 };
54
55 double
atof(p)56 atof(p)
57 register const char *p;
58 {
59 register int c;
60 register int exp = 0;
61 register int eexp = 0;
62 double fl = 0;
63 double flexp = 1.0;
64 int bexp;
65 int neg = 1;
66 int negexp = 1;
67
68 while (isspace(*p))
69 ++p;
70
71 if ((c = *p++) == '-')
72 neg = -1;
73 else if (c == '+')
74 /* skip it */;
75 else
76 --p;
77
78 while ((c = *p++) && isdigit(c))
79 if (fl < twoemax)
80 fl = 10 * fl + (c-'0');
81 else
82 ++exp;
83
84 if (c == '.')
85 while ((c = *p++) && isdigit(c))
86 if (fl < twoemax) {
87 fl = 10 * fl + (c-'0');
88 --exp;
89 }
90
91 if (c == 'E' || c == 'e') {
92 if ((c = *p++) == '-')
93 negexp = -1;
94 else if (c == '+')
95 /* skip it */;
96 else
97 --p;
98 while ((c = *p++) && isdigit(c))
99 eexp = 10 * eexp + (c-'0');
100 if (negexp < 0)
101 eexp = -eexp;
102 exp += eexp;
103 }
104
105 bexp = exp;
106 if (exp < 0)
107 exp = -exp;
108
109 for (c = 0; exp && c < sizeof exp5 / sizeof exp5[0]; ++c) {
110 if (exp & 1)
111 flexp *= *(double *)&exp5[c];
112 exp >>= 1;
113 }
114
115 if (bexp < 0)
116 fl /= flexp;
117 else
118 fl *= flexp;
119
120 fl = ldexp(fl, bexp);
121
122 return neg < 0 ? -fl : fl;
123 }
124