]> git.saurik.com Git - apple/libc.git/blame - gdtoa/FreeBSD/gdtoa-strtopdd.c
Libc-825.24.tar.gz
[apple/libc.git] / gdtoa / FreeBSD / gdtoa-strtopdd.c
CommitLineData
3d9156a7
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
ad3c9f2a
A
32#include "xlocale_private.h"
33
3d9156a7
A
34#include "gdtoaimp.h"
35
ad3c9f2a
A
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
3d9156a7
A
46 int
47#ifdef KR_headers
ad3c9f2a 48strtopdd(s, sp, dd, loc) CONST char *s; char **sp; double *dd; locale_t loc;
3d9156a7 49#else
ad3c9f2a 50strtopdd(CONST char *s, char **sp, double *dd, locale_t loc)
3d9156a7
A
51#endif
52{
53#ifdef Sudden_Underflow
34e8f829 54 static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
3d9156a7 55#else
34e8f829 56 static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
3d9156a7
A
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];
ad3c9f2a
A
64#ifdef __APPLE__
65 long double ld;
66#endif /* __APPLE__ */
3d9156a7
A
67 } U;
68 U *u;
34e8f829
A
69#ifdef Honor_FLT_ROUNDS
70#include "gdtoa_fltrnds.h"
71#else
72#define fpi &fpi0
73#endif
3d9156a7 74
ad3c9f2a 75 rv = strtodg(s, sp, fpi, &exp, bits, loc);
3d9156a7
A
76 u = (U*)dd;
77 switch(rv & STRTOG_Retmask) {
78 case STRTOG_NoNumber:
ad3c9f2a
A
79 u->d[0] = u->d[1] = 0.;
80 return rv; // avoid setting sign
81
3d9156a7
A
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;
1f2f436a
A
88 u->L[_0] = (bits[2] >> 21) | ((bits[3] << 11) & 0xfffff)
89 | ((exp + 0x3ff + 105) << 20);
3d9156a7
A
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) {
1f2f436a 100 bits[1] = bits[1] << i | bits[0] >> (32-i);
3d9156a7
A
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) {
1f2f436a 113 bits[1] = bits[0] >> (32 - i);
3d9156a7
A
114 bits[0] = bits[0] << i & 0xffffffffL;
115 }
116 else {
1f2f436a 117 bits[1] = bits[0] << (i - 32);
3d9156a7
A
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];
1f2f436a 126 u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
ad3c9f2a
A
127#ifdef __APPLE__
128 fixLDBL(u->ld);
129#endif /* __APPLE__ */
3d9156a7
A
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;
1f2f436a
A
148 u->L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
149 | ((65 - i) << 20);
3d9156a7 150 u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
1f2f436a 151 u->L[2+_0] = bits[1] & ((1L << j) - 1);
3d9156a7 152 u->L[2+_1] = bits[0];
ad3c9f2a
A
153#ifdef __APPLE__
154 fixLDBL(u->ld);
155#endif /* __APPLE__ */
3d9156a7
A
156 break;
157
158 partly_normal:
159 i = hi0bits(bits[2]) - 11;
160 if (i < 0) {
161 j = -i;
162 i += 32;
1f2f436a
A
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);
3d9156a7 166 u->L[2+_1] = bits[0];
ad3c9f2a
A
167#ifdef __APPLE__
168 fixLDBL(u->ld);
169#endif /* __APPLE__ */
3d9156a7
A
170 break;
171 }
172 if (i == 0) {
1f2f436a 173 u->L[_0] = (bits[2] & 0xfffff) | (33 << 20);
3d9156a7
A
174 u->L[_1] = bits[1];
175 u->L[2+_0] = 0;
176 u->L[2+_1] = bits[0];
ad3c9f2a
A
177#ifdef __APPLE__
178 fixLDBL(u->ld);
179#endif /* __APPLE__ */
3d9156a7
A
180 break;
181 }
182 j = 32 - i;
1f2f436a
A
183 u->L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
184 | ((j + 1) << 20);
3d9156a7
A
185 u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
186 u->L[2+_0] = 0;
1f2f436a 187 u->L[2+_1] = bits[0] & ((1L << j) - 1);
ad3c9f2a
A
188#ifdef __APPLE__
189 fixLDBL(u->ld);
190#endif /* __APPLE__ */
3d9156a7
A
191 break;
192
193 hardly_normal:
194 j = 11 - hi0bits(bits[1]);
195 i = 32 - j;
1f2f436a 196 u->L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
3d9156a7
A
197 u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
198 u->L[2+_0] = 0;
1f2f436a 199 u->L[2+_1] = bits[0] & ((1L << j) - 1);
ad3c9f2a
A
200#ifdef __APPLE__
201 fixLDBL(u->ld);
202#endif /* __APPLE__ */
3d9156a7
A
203 break;
204
205 case STRTOG_Infinite:
ad3c9f2a
A
206#ifdef __APPLE__
207 u->L[_0] = 0x7ff00000;
208 u->L[_1] = u->L[2+_0] = u->L[2+_1] = 0;
209#else /* __APPLE__ */
3d9156a7
A
210 u->L[_0] = u->L[2+_0] = 0x7ff00000;
211 u->L[_1] = u->L[2+_1] = 0;
ad3c9f2a 212#endif /* __APPLE__ */
3d9156a7
A
213 break;
214
215 case STRTOG_NaN:
ad3c9f2a
A
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__ */
3d9156a7
A
221 u->L[0] = u->L[2] = d_QNAN0;
222 u->L[1] = u->L[3] = d_QNAN1;
ad3c9f2a
A
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__ */
3d9156a7
A
231 }
232 if (rv & STRTOG_Neg) {
233 u->L[ _0] |= 0x80000000L;
ad3c9f2a
A
234#ifdef __APPLE__
235 u->L[2+_0] ^= 0x80000000L;
236#else /* __APPLE__ */
3d9156a7 237 u->L[2+_0] |= 0x80000000L;
ad3c9f2a 238#endif /* __APPLE__ */
3d9156a7
A
239 }
240 return rv;
241 }