new beta-0.90.0
[luatex.git] / source / libs / gmp / gmp-src / extract-dbl.c
bloba6e7bf946813af0649f456a7200c876dae7d0a8f
1 /* __gmp_extract_double -- convert from double to array of mp_limb_t.
3 Copyright 1996, 1999-2002, 2006, 2012 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of either:
10 * the GNU Lesser General Public License as published by the Free
11 Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
16 * the GNU General Public License as published by the Free Software
17 Foundation; either version 2 of the License, or (at your option) any
18 later version.
20 or both in parallel, as here.
22 The GNU MP Library is distributed in the hope that it will be useful, but
23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 for more details.
27 You should have received copies of the GNU General Public License and the
28 GNU Lesser General Public License along with the GNU MP Library. If not,
29 see https://www.gnu.org/licenses/. */
31 #include "gmp.h"
32 #include "gmp-impl.h"
34 #ifdef XDEBUG
35 #undef _GMP_IEEE_FLOATS
36 #endif
38 #ifndef _GMP_IEEE_FLOATS
39 #define _GMP_IEEE_FLOATS 0
40 #endif
42 /* Extract a non-negative double in d. */
44 int
45 __gmp_extract_double (mp_ptr rp, double d)
47 long exp;
48 unsigned sc;
49 #ifdef _LONG_LONG_LIMB
50 #define BITS_PER_PART 64 /* somewhat bogus */
51 unsigned long long int manl;
52 #else
53 #define BITS_PER_PART GMP_LIMB_BITS
54 unsigned long int manh, manl;
55 #endif
57 /* BUGS
59 1. Should handle Inf and NaN in IEEE specific code.
60 2. Handle Inf and NaN also in default code, to avoid hangs.
61 3. Generalize to handle all GMP_LIMB_BITS >= 32.
62 4. This lits is incomplete and misspelled.
65 ASSERT (d >= 0.0);
67 if (d == 0.0)
69 MPN_ZERO (rp, LIMBS_PER_DOUBLE);
70 return 0;
73 #if _GMP_IEEE_FLOATS
75 #if defined (__alpha) && __GNUC__ == 2 && __GNUC_MINOR__ == 8
76 /* Work around alpha-specific bug in GCC 2.8.x. */
77 volatile
78 #endif
79 union ieee_double_extract x;
80 x.d = d;
81 exp = x.s.exp;
82 #if BITS_PER_PART == 64 /* generalize this to BITS_PER_PART > BITS_IN_MANTISSA */
83 manl = (((mp_limb_t) 1 << 63)
84 | ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11));
85 if (exp == 0)
87 /* Denormalized number. Don't try to be clever about this,
88 since it is not an important case to make fast. */
89 exp = 1;
92 manl = manl << 1;
93 exp--;
95 while ((manl & GMP_LIMB_HIGHBIT) == 0);
97 #endif
98 #if BITS_PER_PART == 32
99 manh = ((mp_limb_t) 1 << 31) | (x.s.manh << 11) | (x.s.manl >> 21);
100 manl = x.s.manl << 11;
101 if (exp == 0)
103 /* Denormalized number. Don't try to be clever about this,
104 since it is not an important case to make fast. */
105 exp = 1;
108 manh = (manh << 1) | (manl >> 31);
109 manl = manl << 1;
110 exp--;
112 while ((manh & GMP_LIMB_HIGHBIT) == 0);
114 #endif
115 #if BITS_PER_PART != 32 && BITS_PER_PART != 64
116 You need to generalize the code above to handle this.
117 #endif
118 exp -= 1022; /* Remove IEEE bias. */
120 #else
122 /* Unknown (or known to be non-IEEE) double format. */
123 exp = 0;
124 if (d >= 1.0)
126 ASSERT_ALWAYS (d * 0.5 != d);
128 while (d >= 32768.0)
130 d *= (1.0 / 65536.0);
131 exp += 16;
133 while (d >= 1.0)
135 d *= 0.5;
136 exp += 1;
139 else if (d < 0.5)
141 while (d < (1.0 / 65536.0))
143 d *= 65536.0;
144 exp -= 16;
146 while (d < 0.5)
148 d *= 2.0;
149 exp -= 1;
153 d *= (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2)));
154 #if BITS_PER_PART == 64
155 manl = d;
156 #endif
157 #if BITS_PER_PART == 32
158 manh = d;
159 manl = (d - manh) * (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2)));
160 #endif
162 #endif /* IEEE */
164 sc = (unsigned) (exp + 64 * GMP_NUMB_BITS) % GMP_NUMB_BITS;
166 /* We add something here to get rounding right. */
167 exp = (exp + 64 * GMP_NUMB_BITS) / GMP_NUMB_BITS - 64 * GMP_NUMB_BITS / GMP_NUMB_BITS + 1;
169 #if BITS_PER_PART == 64 && LIMBS_PER_DOUBLE == 2
170 #if GMP_NAIL_BITS == 0
171 if (sc != 0)
173 rp[1] = manl >> (GMP_LIMB_BITS - sc);
174 rp[0] = manl << sc;
176 else
178 rp[1] = manl;
179 rp[0] = 0;
180 exp--;
182 #else
183 if (sc > GMP_NAIL_BITS)
185 rp[1] = manl >> (GMP_LIMB_BITS - sc);
186 rp[0] = (manl << (sc - GMP_NAIL_BITS)) & GMP_NUMB_MASK;
188 else
190 if (sc == 0)
192 rp[1] = manl >> GMP_NAIL_BITS;
193 rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS) & GMP_NUMB_MASK;
194 exp--;
196 else
198 rp[1] = manl >> (GMP_LIMB_BITS - sc);
199 rp[0] = (manl >> (GMP_NAIL_BITS - sc)) & GMP_NUMB_MASK;
202 #endif
203 #endif
205 #if BITS_PER_PART == 64 && LIMBS_PER_DOUBLE == 3
206 if (sc > GMP_NAIL_BITS)
208 rp[2] = manl >> (GMP_LIMB_BITS - sc);
209 rp[1] = (manl << sc - GMP_NAIL_BITS) & GMP_NUMB_MASK;
210 if (sc >= 2 * GMP_NAIL_BITS)
211 rp[0] = 0;
212 else
213 rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS + sc) & GMP_NUMB_MASK;
215 else
217 if (sc == 0)
219 rp[2] = manl >> GMP_NAIL_BITS;
220 rp[1] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS) & GMP_NUMB_MASK;
221 rp[0] = 0;
222 exp--;
224 else
226 rp[2] = manl >> (GMP_LIMB_BITS - sc);
227 rp[1] = (manl >> GMP_NAIL_BITS - sc) & GMP_NUMB_MASK;
228 rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS + sc) & GMP_NUMB_MASK;
231 #endif
233 #if BITS_PER_PART == 32 && LIMBS_PER_DOUBLE == 3
234 #if GMP_NAIL_BITS == 0
235 if (sc != 0)
237 rp[2] = manh >> (GMP_LIMB_BITS - sc);
238 rp[1] = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc));
239 rp[0] = manl << sc;
241 else
243 rp[2] = manh;
244 rp[1] = manl;
245 rp[0] = 0;
246 exp--;
248 #else
249 if (sc > GMP_NAIL_BITS)
251 rp[2] = (manh >> (GMP_LIMB_BITS - sc));
252 rp[1] = ((manh << (sc - GMP_NAIL_BITS)) |
253 (manl >> (GMP_LIMB_BITS - sc + GMP_NAIL_BITS))) & GMP_NUMB_MASK;
254 if (sc >= 2 * GMP_NAIL_BITS)
255 rp[0] = (manl << sc - 2 * GMP_NAIL_BITS) & GMP_NUMB_MASK;
256 else
257 rp[0] = manl >> (2 * GMP_NAIL_BITS - sc) & GMP_NUMB_MASK;
259 else
261 if (sc == 0)
263 rp[2] = manh >> GMP_NAIL_BITS;
264 rp[1] = ((manh << GMP_NUMB_BITS - GMP_NAIL_BITS) | (manl >> 2 * GMP_NAIL_BITS)) & GMP_NUMB_MASK;
265 rp[0] = (manl << GMP_NUMB_BITS - 2 * GMP_NAIL_BITS) & GMP_NUMB_MASK;
266 exp--;
268 else
270 rp[2] = (manh >> (GMP_LIMB_BITS - sc));
271 rp[1] = (manh >> (GMP_NAIL_BITS - sc)) & GMP_NUMB_MASK;
272 rp[0] = ((manh << (GMP_NUMB_BITS - GMP_NAIL_BITS + sc))
273 | (manl >> (GMP_LIMB_BITS - (GMP_NUMB_BITS - GMP_NAIL_BITS + sc)))) & GMP_NUMB_MASK;
276 #endif
277 #endif
279 #if BITS_PER_PART == 32 && LIMBS_PER_DOUBLE > 3
280 if (sc == 0)
282 int i;
284 for (i = LIMBS_PER_DOUBLE - 1; i >= 0; i--)
286 rp[i] = manh >> (BITS_PER_ULONG - GMP_NUMB_BITS);
287 manh = ((manh << GMP_NUMB_BITS)
288 | (manl >> (BITS_PER_ULONG - GMP_NUMB_BITS)));
289 manl = manl << GMP_NUMB_BITS;
291 exp--;
293 else
295 int i;
297 rp[LIMBS_PER_DOUBLE - 1] = (manh >> (GMP_LIMB_BITS - sc));
298 manh = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc));
299 manl = (manl << sc);
300 for (i = LIMBS_PER_DOUBLE - 2; i >= 0; i--)
302 rp[i] = manh >> (BITS_PER_ULONG - GMP_NUMB_BITS);
303 manh = ((manh << GMP_NUMB_BITS)
304 | (manl >> (BITS_PER_ULONG - GMP_NUMB_BITS)));
305 manl = manl << GMP_NUMB_BITS;
308 #endif
310 return exp;