xref: /reactos/sdk/lib/crt/string/strtold.c (revision 1734f297)
1 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
2 #include <stdlib.h>
3 #include <msvcrt/ctype.h>
4 
5 static double powten[] =
6 {
7   1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L,
8 #ifdef __GNUC__
9   1e512L, 1e512L*1e512L, 1e2048L, 1e4096L
10 #else
11   1e256L, 1e256L, 1e256L, 1e256L
12 #endif
13 };
14 
15 long double
16 _strtold(const char *s, char **sret)
17 {
18   double r;		/* result */
19   int e, ne;			/* exponent */
20   int sign;			/* +- 1.0 */
21   int esign;
22   int flags=0;
23   int l2powm1;
24 
25   r = 0.0L;
26   sign = 1;
27   e = ne = 0;
28   esign = 1;
29 
30   while(*s && isspace(*s))
31     s++;
32 
33   if (*s == '+')
34     s++;
35   else if (*s == '-')
36   {
37     sign = -1;
38     s++;
39   }
40 
41   while ((*s >= '0') && (*s <= '9'))
42   {
43     flags |= 1;
44     r *= 10.0L;
45     r += *s - '0';
46     s++;
47   }
48 
49   if (*s == '.')
50   {
51     s++;
52     while ((*s >= '0') && (*s <= '9'))
53     {
54       flags |= 2;
55       r *= 10.0L;
56       r += *s - '0';
57       s++;
58       ne++;
59     }
60   }
61   if (flags == 0)
62   {
63     if (sret)
64       *sret = (char *)s;
65     return 0.0L;
66   }
67 
68   if ((*s == 'e') || (*s == 'E'))
69   {
70     s++;
71     if (*s == '+')
72       s++;
73     else if (*s == '-')
74     {
75       s++;
76       esign = -1;
77     }
78     while ((*s >= '0') && (*s <= '9'))
79     {
80       e *= 10;
81       e += *s - '0';
82       s++;
83     }
84   }
85   if (esign < 0)
86   {
87     esign = -esign;
88     e = -e;
89   }
90   e = e - ne;
91   if (e < -4096)
92   {
93     /* possibly subnormal number, 10^e would overflow */
94     r *= 1.0e-2048L;
95     e += 2048;
96   }
97   if (e < 0)
98   {
99     e = -e;
100     esign = -esign;
101   }
102   if (e >= 8192)
103     e = 8191;
104   if (e)
105   {
106     double d = 1.0L;
107     l2powm1 = 0;
108     while (e)
109     {
110       if (e & 1)
111 	d *= powten[l2powm1];
112       e >>= 1;
113       l2powm1++;
114     }
115     if (esign > 0)
116       r *= d;
117     else
118       r /= d;
119   }
120   if (sret)
121     *sret = (char *)s;
122   return r * sign;
123 
124   return 0;
125 }
126