]> git.saurik.com Git - apple/libc.git/blame - gdtoa/gdtoa-strtopdd-fbsd.c
Libc-498.1.7.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
48strtopdd(s, sp, dd) CONST char *s; char **sp; double *dd; locale_t loc;
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;
69 FPI *fpi = &fpi0, fpi1;
70#ifdef Honor_FLT_ROUNDS
71 int rounding = Flt_Rounds;
72#endif
73
74#ifdef Honor_FLT_ROUNDS
75 if (rounding != fpi0.rounding) {
76 fpi1 = fpi0; /* for thread safety */
77 fpi1.rounding = rounding;
78 fpi = &fpi1;
79 }
80#endif /* Honor_FLT_ROUNDS */
81 rv = strtodg(s, sp, fpi, &exp, bits, loc);
82 u = (U*)dd;
83 switch(rv & STRTOG_Retmask) {
84 case STRTOG_NoNumber:
85 u->d[0] = u->d[1] = 0.;
86 return rv; // avoid setting sign
87
88 case STRTOG_Zero:
89 u->d[0] = u->d[1] = 0.;
90 break;
91
92 case STRTOG_Normal:
93 u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL;
94 u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
95 | exp + 0x3ff + 105 << 20;
96 exp += 0x3ff + 52;
97 if (bits[1] &= 0x1fffff) {
98 i = hi0bits(bits[1]) - 11;
99 if (i >= exp) {
100 i = exp - 1;
101 exp = 0;
102 }
103 else
104 exp -= i;
105 if (i > 0) {
106 bits[1] = bits[1] << i | bits[0] >> 32-i;
107 bits[0] = bits[0] << i & 0xffffffffL;
108 }
109 }
110 else if (bits[0]) {
111 i = hi0bits(bits[0]) + 21;
112 if (i >= exp) {
113 i = exp - 1;
114 exp = 0;
115 }
116 else
117 exp -= i;
118 if (i < 32) {
119 bits[1] = bits[0] >> 32 - i;
120 bits[0] = bits[0] << i & 0xffffffffL;
121 }
122 else {
123 bits[1] = bits[0] << i - 32;
124 bits[0] = 0;
125 }
126 }
127 else {
128 u->L[2] = u->L[3] = 0;
129 break;
130 }
131 u->L[2+_1] = bits[0];
132 u->L[2+_0] = bits[1] & 0xfffff | exp << 20;
133#ifdef __APPLE__
134 fixLDBL(u->ld);
135#endif /* __APPLE__ */
136 break;
137
138 case STRTOG_Denormal:
139 if (bits[3])
140 goto nearly_normal;
141 if (bits[2])
142 goto partly_normal;
143 if (bits[1] & 0xffe00000)
144 goto hardly_normal;
145 /* completely denormal */
146 u->L[2] = u->L[3] = 0;
147 u->L[_1] = bits[0];
148 u->L[_0] = bits[1];
149 break;
150
151 nearly_normal:
152 i = hi0bits(bits[3]) - 11; /* i >= 12 */
153 j = 32 - i;
154 u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
155 | 65 - i << 20;
156 u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
157 u->L[2+_0] = bits[1] & (1L << j) - 1;
158 u->L[2+_1] = bits[0];
159#ifdef __APPLE__
160 fixLDBL(u->ld);
161#endif /* __APPLE__ */
162 break;
163
164 partly_normal:
165 i = hi0bits(bits[2]) - 11;
166 if (i < 0) {
167 j = -i;
168 i += 32;
169 u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
170 u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
171 u->L[2+_0] = bits[1] & (1L << j) - 1;
172 u->L[2+_1] = bits[0];
173#ifdef __APPLE__
174 fixLDBL(u->ld);
175#endif /* __APPLE__ */
176 break;
177 }
178 if (i == 0) {
179 u->L[_0] = bits[2] & 0xfffff | 33 << 20;
180 u->L[_1] = bits[1];
181 u->L[2+_0] = 0;
182 u->L[2+_1] = bits[0];
183#ifdef __APPLE__
184 fixLDBL(u->ld);
185#endif /* __APPLE__ */
186 break;
187 }
188 j = 32 - i;
189 u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
190 | j + 1 << 20;
191 u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
192 u->L[2+_0] = 0;
193 u->L[2+_1] = bits[0] & (1L << j) - 1;
194#ifdef __APPLE__
195 fixLDBL(u->ld);
196#endif /* __APPLE__ */
197 break;
198
199 hardly_normal:
200 j = 11 - hi0bits(bits[1]);
201 i = 32 - j;
202 u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
203 u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
204 u->L[2+_0] = 0;
205 u->L[2+_1] = bits[0] & (1L << j) - 1;
206#ifdef __APPLE__
207 fixLDBL(u->ld);
208#endif /* __APPLE__ */
209 break;
210
211 case STRTOG_Infinite:
212#ifdef __APPLE__
213 u->L[_0] = 0x7ff00000;
214 u->L[_1] = u->L[2+_0] = u->L[2+_1] = 0;
215#else /* __APPLE__ */
216 u->L[_0] = u->L[2+_0] = 0x7ff00000;
217 u->L[_1] = u->L[2+_1] = 0;
218#endif /* __APPLE__ */
219 break;
220
221 case STRTOG_NaN:
222#ifdef __APPLE__
223 u->L[0] = d_QNAN0;
224 u->L[1] = d_QNAN1;
225 u->L[2] = u->L[3] = 0;
226#else /* __APPLE__ */
227 u->L[0] = u->L[2] = d_QNAN0;
228 u->L[1] = u->L[3] = d_QNAN1;
229#endif /* __APPLE__ */
230#ifdef __APPLE__
231 case STRTOG_NaNbits:
232 u->L[0] = d_QNAN0 | ((bits[2] >> 20 | bits[3] << 12) & 0xfffff);
233 u->L[1] = d_QNAN1 | bits[1] >> 20 | bits[2] << 12;
234 u->L[2] = u->L[3] = 0;
235#endif /* __APPLE__ */
236 }
237 if (rv & STRTOG_Neg) {
238 u->L[ _0] |= 0x80000000L;
239#ifdef __APPLE__
240 u->L[2+_0] ^= 0x80000000L;
241#else /* __APPLE__ */
242 u->L[2+_0] |= 0x80000000L;
243#endif /* __APPLE__ */
244 }
245 return rv;
246 }