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
;