1 /* __gmp_extract_double -- convert from double to array of mp_limb_t.
3 Copyright 1996, 1999, 2000, 2001, 2002, 2006 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 the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
24 #undef _GMP_IEEE_FLOATS
27 #ifndef _GMP_IEEE_FLOATS
28 #define _GMP_IEEE_FLOATS 0
31 #define BITS_IN_MANTISSA 53
33 /* Extract a non-negative double in d. */
36 __gmp_extract_double (mp_ptr rp, double d)
40 #ifdef _LONG_LONG_LIMB
41 #define BITS_PER_PART 64 /* somewhat bogus */
42 unsigned long long int manl;
44 #define BITS_PER_PART GMP_LIMB_BITS
45 unsigned long int manh, manl;
50 1. Should handle Inf and NaN in IEEE specific code.
51 2. Handle Inf and NaN also in default code, to avoid hangs.
52 3. Generalize to handle all GMP_LIMB_BITS >= 32.
53 4. This lits is incomplete and misspelled.
60 MPN_ZERO (rp, LIMBS_PER_DOUBLE);
66 #if defined (__alpha) && __GNUC__ == 2 && __GNUC_MINOR__ == 8
67 /* Work around alpha-specific bug in GCC 2.8.x. */
70 union ieee_double_extract x;
73 #if BITS_PER_PART == 64 /* generalize this to BITS_PER_PART > BITS_IN_MANTISSA */
74 manl = (((mp_limb_t) 1 << 63)
75 | ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11));
78 /* Denormalized number. Don't try to be clever about this,
79 since it is not an important case to make fast. */
86 while ((manl & GMP_LIMB_HIGHBIT) == 0);
89 #if BITS_PER_PART == 32
90 manh = ((mp_limb_t) 1 << 31) | (x.s.manh << 11) | (x.s.manl >> 21);
91 manl = x.s.manl << 11;
94 /* Denormalized number. Don't try to be clever about this,
95 since it is not an important case to make fast. */
99 manh = (manh << 1) | (manl >> 31);
103 while ((manh & GMP_LIMB_HIGHBIT) == 0);
106 #if BITS_PER_PART != 32 && BITS_PER_PART != 64
107 You need to generalize the code above to handle this.
109 exp -= 1022; /* Remove IEEE bias. */
113 /* Unknown (or known to be non-IEEE) double format. */
117 ASSERT_ALWAYS (d * 0.5 != d);
121 d *= (1.0 / 65536.0);
132 while (d < (1.0 / 65536.0))
144 d *= (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2)));
145 #if BITS_PER_PART == 64
148 #if BITS_PER_PART == 32
150 manl = (d - manh) * (4.0 * ((unsigned long int) 1 << (BITS_PER_PART - 2)));
155 sc = (unsigned) (exp + 64 * GMP_NUMB_BITS) % GMP_NUMB_BITS;
157 /* We add something here to get rounding right. */
158 exp = (exp + 64 * GMP_NUMB_BITS) / GMP_NUMB_BITS - 64 * GMP_NUMB_BITS / GMP_NUMB_BITS + 1;
160 #if BITS_PER_PART == 64 && LIMBS_PER_DOUBLE == 2
161 #if GMP_NAIL_BITS == 0
164 rp[1] = manl >> (GMP_LIMB_BITS - sc);
174 if (sc > GMP_NAIL_BITS)
176 rp[1] = manl >> (GMP_LIMB_BITS - sc);
177 rp[0] = (manl << (sc - GMP_NAIL_BITS)) & GMP_NUMB_MASK;
183 rp[1] = manl >> GMP_NAIL_BITS;
184 rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS) & GMP_NUMB_MASK;
189 rp[1] = manl >> (GMP_LIMB_BITS - sc);
190 rp[0] = (manl >> (GMP_NAIL_BITS - sc)) & GMP_NUMB_MASK;
196 #if BITS_PER_PART == 64 && LIMBS_PER_DOUBLE == 3
197 if (sc > GMP_NAIL_BITS)
199 rp[2] = manl >> (GMP_LIMB_BITS - sc);
200 rp[1] = (manl << sc - GMP_NAIL_BITS) & GMP_NUMB_MASK;
201 if (sc >= 2 * GMP_NAIL_BITS)
204 rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS + sc) & GMP_NUMB_MASK;
210 rp[2] = manl >> GMP_NAIL_BITS;
211 rp[1] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS) & GMP_NUMB_MASK;
217 rp[2] = manl >> (GMP_LIMB_BITS - sc);
218 rp[1] = (manl >> GMP_NAIL_BITS - sc) & GMP_NUMB_MASK;
219 rp[0] = (manl << GMP_NUMB_BITS - GMP_NAIL_BITS + sc) & GMP_NUMB_MASK;
224 #if BITS_PER_PART == 32 && LIMBS_PER_DOUBLE == 3
225 #if GMP_NAIL_BITS == 0
228 rp[2] = manh >> (GMP_LIMB_BITS - sc);
229 rp[1] = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc));
240 if (sc > GMP_NAIL_BITS)
242 rp[2] = (manh >> (GMP_LIMB_BITS - sc));
243 rp[1] = ((manh << (sc - GMP_NAIL_BITS)) |
244 (manl >> (GMP_LIMB_BITS - sc + GMP_NAIL_BITS))) & GMP_NUMB_MASK;
245 if (sc >= 2 * GMP_NAIL_BITS)
246 rp[0] = (manl << sc - 2 * GMP_NAIL_BITS) & GMP_NUMB_MASK;
248 rp[0] = manl >> (2 * GMP_NAIL_BITS - sc) & GMP_NUMB_MASK;
254 rp[2] = manh >> GMP_NAIL_BITS;
255 rp[1] = ((manh << GMP_NUMB_BITS - GMP_NAIL_BITS) | (manl >> 2 * GMP_NAIL_BITS)) & GMP_NUMB_MASK;
256 rp[0] = (manl << GMP_NUMB_BITS - 2 * GMP_NAIL_BITS) & GMP_NUMB_MASK;
261 rp[2] = (manh >> (GMP_LIMB_BITS - sc));
262 rp[1] = (manh >> (GMP_NAIL_BITS - sc)) & GMP_NUMB_MASK;
263 rp[0] = ((manh << (GMP_NUMB_BITS - GMP_NAIL_BITS + sc))
264 | (manl >> (GMP_LIMB_BITS - (GMP_NUMB_BITS - GMP_NAIL_BITS + sc)))) & GMP_NUMB_MASK;
270 #if BITS_PER_PART == 32 && LIMBS_PER_DOUBLE > 3
275 for (i = LIMBS_PER_DOUBLE - 1; i >= 0; i--)
277 rp[i] = manh >> (BITS_PER_ULONG - GMP_NUMB_BITS);
278 manh = ((manh << GMP_NUMB_BITS)
279 | (manl >> (BITS_PER_ULONG - GMP_NUMB_BITS)));
280 manl = manl << GMP_NUMB_BITS;
288 rp[LIMBS_PER_DOUBLE - 1] = (manh >> (GMP_LIMB_BITS - sc));
289 manh = (manh << sc) | (manl >> (GMP_LIMB_BITS - sc));
291 for (i = LIMBS_PER_DOUBLE - 2; i >= 0; i--)
293 rp[i] = manh >> (BITS_PER_ULONG - GMP_NUMB_BITS);
294 manh = ((manh << GMP_NUMB_BITS)
295 | (manl >> (BITS_PER_ULONG - GMP_NUMB_BITS)));
296 manl = manl << GMP_NUMB_BITS;