]> git.saurik.com Git - apple/libc.git/blame - gdtoa/gdtoa-strtopdd-fbsd.c
Libc-594.9.5.tar.gz
[apple/libc.git] / gdtoa / gdtoa-strtopdd-fbsd.c
CommitLineData
224c7076
A
1/****************************************************************
2
3The author of this software is David M. Gay.
4
5Copyright (C) 1998, 2000 by Lucent Technologies
6All Rights Reserved
7
8Permission to use, copy, modify, and distribute this software and
9its documentation for any purpose and without fee is hereby
10granted, provided that the above copyright notice appear in all
11copies and that both that the copyright notice and this
12permission notice and warranty disclaimer appear in supporting
13documentation, and that the name of Lucent or any of its entities
14not be used in advertising or publicity pertaining to
15distribution of the software without specific, written prior
16permission.
17
18LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25THIS SOFTWARE.
26
27****************************************************************/
28
29/* Please send bug reports to David M. Gay (dmg at acm dot org,
30 * with " at " changed at "@" and " dot " changed to "."). */
31
32#include "xlocale_private.h"
33
34#include "gdtoaimp.h"
35
36#ifdef __APPLE__
37/*
38 * IEEE specifies that the most significant (head) double is required to
39 * be equal to the long double rounded to the nearest double, so that means
40 * the tail double might be the opposite sign as the head. We can do this
41 * adding (long double)0 to the number, which will fix it up.
42 */
43#define fixLDBL(x) ((x) += 0.L)
44#endif /* __APPLE__ */
45
46 int
47#ifdef KR_headers
34e8f829 48strtopdd(s, sp, dd, loc) CONST char *s; char **sp; double *dd; locale_t loc;
224c7076
A
49#else
50strtopdd(CONST char *s, char **sp, double *dd, locale_t loc)
51#endif
52{
53#ifdef Sudden_Underflow
54 static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
55#else
56 static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
57#endif
58 ULong bits[4];
59 Long exp;
60 int i, j, rv;
61 typedef union {
62 double d[2];
63 ULong L[4];
64#ifdef __APPLE__
65 long double ld;
66#endif /* __APPLE__ */
67 } U;
68 U *u;
224c7076 69#ifdef Honor_FLT_ROUNDS
34e8f829
A
70#include "gdtoa_fltrnds.h"
71#else
72#define fpi &fpi0
224c7076
A
73#endif
74
224c7076
A
75 rv = strtodg(s, sp, fpi, &exp, bits, loc);
76 u = (U*)dd;
77 switch(rv & STRTOG_Retmask) {
78 case STRTOG_NoNumber:
79 u->d[0] = u->d[1] = 0.;
80 return rv; // avoid setting sign
81
82 case STRTOG_Zero:
83 u->d[0] = u->d[1] = 0.;
84 break;
85
86 case STRTOG_Normal:
87 u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL;
88 u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
89 | exp + 0x3ff + 105 << 20;
90 exp += 0x3ff + 52;
91 if (bits[1] &= 0x1fffff) {
92 i = hi0bits(bits[1]) - 11;
93 if (i >= exp) {
94 i = exp - 1;
95 exp = 0;
96 }
97 else
98 exp -= i;
99 if (i > 0) {
100 bits[1] = bits[1] << i | bits[0] >> 32-i;
101 bits[0] = bits[0] << i & 0xffffffffL;
102 }
103 }
104 else if (bits[0]) {
105 i = hi0bits(bits[0]) + 21;
106 if (i >= exp) {
107 i = exp - 1;
108 exp = 0;
109 }
110 else
111 exp -= i;
112 if (i < 32) {
113 bits[1] = bits[0] >> 32 - i;
114 bits[0] = bits[0] << i & 0xffffffffL;
115 }
116 else {
117 bits[1] = bits[0] << i - 32;
118 bits[0] = 0;
119 }
120 }
121 else {
122 u->L[2] = u->L[3] = 0;
123 break;
124 }
125 u->L[2+_1] = bits[0];
126 u->L[2+_0] = bits[1] & 0xfffff | exp << 20;
127#ifdef __APPLE__
128 fixLDBL(u->ld);
129#endif /* __APPLE__ */
130 break;
131
132 case STRTOG_Denormal:
133 if (bits[3])
134 goto nearly_normal;
135 if (bits[2])
136 goto partly_normal;
137 if (bits[1] & 0xffe00000)
138 goto hardly_normal;
139 /* completely denormal */
140 u->L[2] = u->L[3] = 0;
141 u->L[_1] = bits[0];
142 u->L[_0] = bits[1];
143 break;
144
145 nearly_normal:
146 i = hi0bits(bits[3]) - 11; /* i >= 12 */
147 j = 32 - i;
148 u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
149 | 65 - i << 20;
150 u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
151 u->L[2+_0] = bits[1] & (1L << j) - 1;
152 u->L[2+_1] = bits[0];
153#ifdef __APPLE__
154 fixLDBL(u->ld);
155#endif /* __APPLE__ */
156 break;
157
158 partly_normal:
159 i = hi0bits(bits[2]) - 11;
160 if (i < 0) {
161 j = -i;
162 i += 32;
163 u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
164 u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
165 u->L[2+_0] = bits[1] & (1L << j) - 1;
166 u->L[2+_1] = bits[0];
167#ifdef __APPLE__
168 fixLDBL(u->ld);
169#endif /* __APPLE__ */
170 break;
171 }
172 if (i == 0) {
173 u->L[_0] = bits[2] & 0xfffff | 33 << 20;
174 u->L[_1] = bits[1];
175 u->L[2+_0] = 0;
176 u->L[2+_1] = bits[0];
177#ifdef __APPLE__
178 fixLDBL(u->ld);
179#endif /* __APPLE__ */
180 break;
181 }
182 j = 32 - i;
183 u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
184 | j + 1 << 20;
185 u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
186 u->L[2+_0] = 0;
187 u->L[2+_1] = bits[0] & (1L << j) - 1;
188#ifdef __APPLE__
189 fixLDBL(u->ld);
190#endif /* __APPLE__ */
191 break;
192
193 hardly_normal:
194 j = 11 - hi0bits(bits[1]);
195 i = 32 - j;
196 u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
197 u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
198 u->L[2+_0] = 0;
199 u->L[2+_1] = bits[0] & (1L << j) - 1;
200#ifdef __APPLE__
201 fixLDBL(u->ld);
202#endif /* __APPLE__ */
203 break;
204
205 case STRTOG_Infinite:
206#ifdef __APPLE__
207 u->L[_0] = 0x7ff00000;
208 u->L[_1] = u->L[2+_0] = u->L[2+_1] = 0;
209#else /* __APPLE__ */
210 u->L[_0] = u->L[2+_0] = 0x7ff00000;
211 u->L[_1] = u->L[2+_1] = 0;
212#endif /* __APPLE__ */
213 break;
214
215 case STRTOG_NaN:
216#ifdef __APPLE__
217 u->L[0] = d_QNAN0;
218 u->L[1] = d_QNAN1;
219 u->L[2] = u->L[3] = 0;
220#else /* __APPLE__ */
221 u->L[0] = u->L[2] = d_QNAN0;
222 u->L[1] = u->L[3] = d_QNAN1;
223#endif /* __APPLE__ */
34e8f829 224 break;
224c7076
A
225#ifdef __APPLE__
226 case STRTOG_NaNbits:
227 u->L[0] = d_QNAN0 | ((bits[2] >> 20 | bits[3] << 12) & 0xfffff);
228 u->L[1] = d_QNAN1 | bits[1] >> 20 | bits[2] << 12;
229 u->L[2] = u->L[3] = 0;
230#endif /* __APPLE__ */
231 }
232 if (rv & STRTOG_Neg) {
233 u->L[ _0] |= 0x80000000L;
234#ifdef __APPLE__
235 u->L[2+_0] ^= 0x80000000L;
236#else /* __APPLE__ */
237 u->L[2+_0] |= 0x80000000L;
238#endif /* __APPLE__ */
239 }
240 return rv;
241 }