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
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
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/. */
35 #undef _GMP_IEEE_FLOATS
38 #ifndef _GMP_IEEE_FLOATS
39 #define _GMP_IEEE_FLOATS 0
42 /* Extract a non-negative double in d. */
45 __gmp_extract_double (mp_ptr rp
, double d
)
49 #ifdef _LONG_LONG_LIMB
50 #define BITS_PER_PART 64 /* somewhat bogus */
51 unsigned long long int manl
;
53 #define BITS_PER_PART GMP_LIMB_BITS
54 unsigned long int manh
, manl
;
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.
69 MPN_ZERO (rp
, LIMBS_PER_DOUBLE
);
75 #if defined (__alpha) && __GNUC__ == 2 && __GNUC_MINOR__ == 8
76 /* Work around alpha-specific bug in GCC 2.8.x. */
79 union ieee_double_extract x
;
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));
87 /* Denormalized number. Don't try to be clever about this,
88 since it is not an important case to make fast. */
95 while ((manl
& GMP_LIMB_HIGHBIT
) == 0);
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;
103 /* Denormalized number. Don't try to be clever about this,
104 since it is not an important case to make fast. */
108 manh
= (manh
<< 1) | (manl
>> 31);
112 while ((manh
& GMP_LIMB_HIGHBIT
) == 0);
115 #if BITS_PER_PART != 32 && BITS_PER_PART != 64
116 You need to generalize the code above to handle
this.
118 exp
-= 1022; /* Remove IEEE bias. */
122 /* Unknown (or known to be non-IEEE) double format. */
126 ASSERT_ALWAYS (d
* 0.5 != d
);
130 d
*= (1.0 / 65536.0);
141 while (d
< (1.0 / 65536.0))
153 d
*= (4.0 * ((unsigned long int) 1 << (BITS_PER_PART
- 2)));
154 #if BITS_PER_PART == 64
157 #if BITS_PER_PART == 32
159 manl
= (d
- manh
) * (4.0 * ((unsigned long int) 1 << (BITS_PER_PART
- 2)));
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
173 rp
[1] = manl
>> (GMP_LIMB_BITS
- sc
);
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
;
192 rp
[1] = manl
>> GMP_NAIL_BITS
;
193 rp
[0] = (manl
<< GMP_NUMB_BITS
- GMP_NAIL_BITS
) & GMP_NUMB_MASK
;
198 rp
[1] = manl
>> (GMP_LIMB_BITS
- sc
);
199 rp
[0] = (manl
>> (GMP_NAIL_BITS
- sc
)) & GMP_NUMB_MASK
;
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
)
213 rp
[0] = (manl
<< GMP_NUMB_BITS
- GMP_NAIL_BITS
+ sc
) & GMP_NUMB_MASK
;
219 rp
[2] = manl
>> GMP_NAIL_BITS
;
220 rp
[1] = (manl
<< GMP_NUMB_BITS
- GMP_NAIL_BITS
) & GMP_NUMB_MASK
;
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
;
233 #if BITS_PER_PART == 32 && LIMBS_PER_DOUBLE == 3
234 #if GMP_NAIL_BITS == 0
237 rp
[2] = manh
>> (GMP_LIMB_BITS
- sc
);
238 rp
[1] = (manh
<< sc
) | (manl
>> (GMP_LIMB_BITS
- sc
));
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
;
257 rp
[0] = manl
>> (2 * GMP_NAIL_BITS
- sc
) & GMP_NUMB_MASK
;
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
;
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
;
279 #if BITS_PER_PART == 32 && LIMBS_PER_DOUBLE > 3
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
;
297 rp
[LIMBS_PER_DOUBLE
- 1] = (manh
>> (GMP_LIMB_BITS
- sc
));
298 manh
= (manh
<< sc
) | (manl
>> (GMP_LIMB_BITS
- 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
;