xref: /csrg-svn/lib/libc/hp300/stdlib/atof.c (revision 47921)
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