]> git.saurik.com Git - apple/libc.git/blob - gdtoa/FreeBSD/gdtoa-strtopdd.c
Libc-825.40.1.tar.gz
[apple/libc.git] / gdtoa / FreeBSD / gdtoa-strtopdd.c
1 /****************************************************************
2
3 The author of this software is David M. Gay.
4
5 Copyright (C) 1998, 2000 by Lucent Technologies
6 All Rights Reserved
7
8 Permission to use, copy, modify, and distribute this software and
9 its documentation for any purpose and without fee is hereby
10 granted, provided that the above copyright notice appear in all
11 copies and that both that the copyright notice and this
12 permission notice and warranty disclaimer appear in supporting
13 documentation, and that the name of Lucent or any of its entities
14 not be used in advertising or publicity pertaining to
15 distribution of the software without specific, written prior
16 permission.
17
18 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25 THIS 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
48 strtopdd(s, sp, dd, loc) CONST char *s; char **sp; double *dd; locale_t loc;
49 #else
50 strtopdd(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;
69 #ifdef Honor_FLT_ROUNDS
70 #include "gdtoa_fltrnds.h"
71 #else
72 #define fpi &fpi0
73 #endif
74
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__ */
224 break;
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 }