xref: /original-bsd/lib/libc/hp300/stdlib/atof.c (revision e0399a72)
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
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