Commit | Line | Data |
---|---|---|
2a9e442d KB |
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.1 (Berkeley) %G%"; | |
14 | #endif /* LIBC_SCCS and not lint */ | |
15 | ||
16 | #include <ctype.h> | |
17 | ||
18 | double _twoemax = | |
19 | #ifdef IEEE | |
20 | 9007199254740992.; /*2^53*/ | |
21 | #else | |
22 | 72057594037927936.; /*2^56*/ | |
23 | #endif | |
24 | ||
25 | #ifdef hp300 | |
26 | /* attempt to be as exact as possible */ | |
27 | struct { | |
28 | long d_high; | |
29 | long d_low; | |
30 | } _exp5[] = { | |
31 | { 0x40140000, 0x00000000 }, /* 5 */ | |
32 | { 0x40390000, 0x00000000 }, /* 25 */ | |
33 | { 0x40838800, 0x00000000 }, /* 625 */ | |
34 | { 0x4117d784, 0x00000000 }, /* 390625 */ | |
35 | { 0x4241c379, 0x37e08000 }, /* 152587890625 */ | |
36 | { 0x4493b8b5, 0xb5056e17 }, /* 2.3283064365387e+022 */ | |
37 | { 0x49384f03, 0xe93ff9f6 }, /* 5.42101086242753e+044 */ | |
38 | { 0x52827748, 0xf9301d33 }, /* 2.93873587705572e+089 */ | |
39 | { 0x65154fdd, 0x7f73bf3f } /* 8.63616855509445e+178 */ | |
40 | }; | |
41 | #else | |
42 | double _exp5[] = { | |
43 | 5., | |
44 | 25., | |
45 | 625., | |
46 | 390625., | |
47 | 152587890625., | |
48 | 23283064365386962890625., | |
49 | #ifdef IEEE | |
50 | 5.4210108624275231e+044, | |
51 | 2.9387358770557196e+089, | |
52 | 8.6361685550944492e+178, | |
53 | #endif | |
54 | }; | |
55 | #endif | |
56 | ||
57 | double | |
58 | atof(p) | |
59 | register char *p; | |
60 | { | |
61 | extern double ldexp(); | |
62 | register c, exp = 0, eexp = 0; | |
63 | double fl = 0, flexp = 1.0; | |
64 | int bexp, neg = 1, negexp = 1; | |
65 | ||
66 | while((c = *p++) == ' '); | |
67 | if (c == '-') neg = -1; else if (c == '+'); else --p; | |
68 | ||
69 | while ((c = *p++), isdigit(c)) | |
70 | if (fl < _twoemax) fl = 10*fl + (c-'0'); else exp++; | |
71 | if (c == '.') | |
72 | while ((c = *p++), isdigit(c)) | |
73 | if (fl < _twoemax) | |
74 | { | |
75 | fl = 10*fl + (c-'0'); | |
76 | exp--; | |
77 | } | |
78 | if ((c == 'E') || (c == 'e')) | |
79 | { | |
80 | if ((c= *p++) == '+'); else if (c=='-') negexp = -1; else --p; | |
81 | while ((c = *p++), isdigit(c)) eexp = 10*eexp + (c-'0'); | |
82 | if (negexp < 0) eexp = -eexp; exp += eexp; | |
83 | } | |
84 | bexp = exp; | |
85 | if (exp < 0) exp = -exp; | |
86 | ||
87 | for (c = 0; c < sizeof(_exp5)/sizeof(_exp5[0]); c++) | |
88 | { | |
89 | #ifdef hp300 | |
90 | if (exp & 01) flexp *= *(double *)&_exp5[c]; | |
91 | #else | |
92 | if (exp & 01) flexp *= _exp5[c]; | |
93 | #endif | |
94 | exp >>= 1; if (exp == 0) break; | |
95 | } | |
96 | ||
97 | if (bexp < 0) fl /= flexp; else fl *= flexp; | |
98 | fl = ldexp(fl, bexp); | |
99 | if (neg < 0) return(-fl); else return(fl); | |
100 | } |