kernel - Reenable acpi sleep states
[dragonfly.git] / contrib / mpfr / set_ld.c
blob39e0eb25b0acbf80a09d7a1807de9e8a4ed3d947
1 /* mpfr_set_ld -- convert a machine long double to
2 a multiple precision floating-point number
4 Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
5 Contributed by the Arenaire and Cacao projects, INRIA.
7 This file is part of the GNU MPFR Library.
9 The GNU MPFR Library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or (at your
12 option) any later version.
14 The GNU MPFR Library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with the GNU MPFR Library; see the file COPYING.LIB. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
22 MA 02110-1301, USA. */
24 #include <float.h>
26 #define MPFR_NEED_LONGLONG_H
27 #include "mpfr-impl.h"
29 /* Various i386 systems have been seen with float.h LDBL constants equal to
30 the DBL ones, whereas they ought to be bigger, reflecting the 10-byte
31 IEEE extended format on that processor. gcc 3.2.1 on FreeBSD and Solaris
32 has been seen with the problem, and gcc 2.95.4 on FreeBSD 4.7. */
34 #if HAVE_LDOUBLE_IEEE_EXT_LITTLE
35 static const struct {
36 char bytes[10];
37 long double dummy; /* for memory alignment */
38 } ldbl_max_struct = {
39 { '\377','\377','\377','\377',
40 '\377','\377','\377','\377',
41 '\376','\177' }, 0.0
43 #define MPFR_LDBL_MAX (* (const long double *) ldbl_max_struct.bytes)
44 #else
45 #define MPFR_LDBL_MAX LDBL_MAX
46 #endif
48 #ifndef HAVE_LDOUBLE_IEEE_EXT_LITTLE
50 /* Generic code */
51 int
52 mpfr_set_ld (mpfr_ptr r, long double d, mp_rnd_t rnd_mode)
54 mpfr_t t, u;
55 int inexact, shift_exp;
56 long double x;
57 MPFR_SAVE_EXPO_DECL (expo);
59 /* Check for NAN */
60 LONGDOUBLE_NAN_ACTION (d, goto nan);
62 /* Check for INF */
63 if (d > MPFR_LDBL_MAX)
65 mpfr_set_inf (r, 1);
66 return 0;
68 else if (d < -MPFR_LDBL_MAX)
70 mpfr_set_inf (r, -1);
71 return 0;
73 /* Check for ZERO */
74 else if (d == 0.0)
75 return mpfr_set_d (r, (double) d, rnd_mode);
77 mpfr_init2 (t, MPFR_LDBL_MANT_DIG);
78 mpfr_init2 (u, IEEE_DBL_MANT_DIG);
80 MPFR_SAVE_EXPO_MARK (expo);
82 convert:
83 x = d;
84 MPFR_SET_ZERO (t); /* The sign doesn't matter. */
85 shift_exp = 0; /* invariant: remainder to deal with is d*2^shift_exp */
86 while (x != (long double) 0.0)
88 /* Check overflow of double */
89 if (x > (long double) DBL_MAX || (-x) > (long double) DBL_MAX)
91 long double div9, div10, div11, div12, div13;
93 #define TWO_64 18446744073709551616.0 /* 2^64 */
94 #define TWO_128 (TWO_64 * TWO_64)
95 #define TWO_256 (TWO_128 * TWO_128)
96 div9 = (long double) (double) (TWO_256 * TWO_256); /* 2^(2^9) */
97 div10 = div9 * div9;
98 div11 = div10 * div10; /* 2^(2^11) */
99 div12 = div11 * div11; /* 2^(2^12) */
100 div13 = div12 * div12; /* 2^(2^13) */
101 if (ABS (x) >= div13)
103 x /= div13; /* exact */
104 shift_exp += 8192;
106 if (ABS (x) >= div12)
108 x /= div12; /* exact */
109 shift_exp += 4096;
111 if (ABS (x) >= div11)
113 x /= div11; /* exact */
114 shift_exp += 2048;
116 if (ABS (x) >= div10)
118 x /= div10; /* exact */
119 shift_exp += 1024;
121 /* warning: we may have DBL_MAX=2^1024*(1-2^(-53)) < x < 2^1024,
122 therefore we have one extra exponent reduction step */
123 if (ABS (x) >= div9)
125 x /= div9; /* exact */
126 shift_exp += 512;
128 } /* Check overflow of double */
129 else
131 long double div9, div10, div11;
133 div9 = (long double) (double) 7.4583407312002067432909653e-155;
134 /* div9 = 2^(-2^9) */
135 div10 = div9 * div9; /* 2^(-2^10) */
136 div11 = div10 * div10; /* 2^(-2^11) if extended precision */
137 /* since -DBL_MAX <= x <= DBL_MAX, the cast to double should not
138 overflow here */
139 if (ABS(x) < div10 &&
140 div11 != (long double) 0.0 &&
141 div11 / div10 == div10) /* possible underflow */
143 long double div12, div13;
144 /* After the divisions, any bit of x must be >= div10,
145 hence the possible division by div9. */
146 div12 = div11 * div11; /* 2^(-2^12) */
147 div13 = div12 * div12; /* 2^(-2^13) */
148 if (ABS (x) <= div13)
150 x /= div13; /* exact */
151 shift_exp -= 8192;
153 if (ABS (x) <= div12)
155 x /= div12; /* exact */
156 shift_exp -= 4096;
158 if (ABS (x) <= div11)
160 x /= div11; /* exact */
161 shift_exp -= 2048;
163 if (ABS (x) <= div10)
165 x /= div10; /* exact */
166 shift_exp -= 1024;
168 if (ABS(x) <= div9)
170 x /= div9; /* exact */
171 shift_exp -= 512;
174 else
176 inexact = mpfr_set_d (u, (double) x, GMP_RNDZ);
177 MPFR_ASSERTD (inexact == 0);
178 if (mpfr_add (t, t, u, GMP_RNDZ) != 0)
180 if (!mpfr_number_p (t))
181 break;
182 /* Inexact. This cannot happen unless the C implementation
183 "lies" on the precision or when long doubles are
184 implemented with FP expansions like under Mac OS X. */
185 if (MPFR_PREC (t) != MPFR_PREC (r) + 1)
187 /* We assume that MPFR_PREC (r) < MPFR_PREC_MAX.
188 The precision MPFR_PREC (r) + 1 allows us to
189 deduce the rounding bit and the sticky bit. */
190 mpfr_set_prec (t, MPFR_PREC (r) + 1);
191 goto convert;
193 else
195 mp_limb_t *tp;
196 int rb_mask;
198 /* Since mpfr_add was inexact, the sticky bit is 1. */
199 tp = MPFR_MANT (t);
200 rb_mask = MPFR_LIMB_ONE <<
201 (BITS_PER_MP_LIMB - 1 -
202 (MPFR_PREC (r) & (BITS_PER_MP_LIMB - 1)));
203 if (rnd_mode == GMP_RNDN)
204 rnd_mode = (*tp & rb_mask) ^ MPFR_IS_NEG (t) ?
205 GMP_RNDU : GMP_RNDD;
206 *tp |= rb_mask;
207 break;
210 x -= (long double) mpfr_get_d1 (u); /* exact */
214 inexact = mpfr_mul_2si (r, t, shift_exp, rnd_mode);
215 mpfr_clear (t);
216 mpfr_clear (u);
218 MPFR_SAVE_EXPO_FREE (expo);
219 return mpfr_check_range (r, inexact, rnd_mode);
221 nan:
222 MPFR_SET_NAN(r);
223 MPFR_RET_NAN;
226 #else /* IEEE Extended Little Endian Code */
229 mpfr_set_ld (mpfr_ptr r, long double d, mp_rnd_t rnd_mode)
231 int inexact, i, k, cnt;
232 mpfr_t tmp;
233 mp_limb_t tmpmant[MPFR_LIMBS_PER_LONG_DOUBLE];
234 mpfr_long_double_t x;
235 mp_exp_t exp;
236 int signd;
237 MPFR_SAVE_EXPO_DECL (expo);
239 /* Check for NAN */
240 if (MPFR_UNLIKELY (d != d))
242 MPFR_SET_NAN (r);
243 MPFR_RET_NAN;
245 /* Check for INF */
246 else if (MPFR_UNLIKELY (d > MPFR_LDBL_MAX))
248 MPFR_SET_INF (r);
249 MPFR_SET_POS (r);
250 return 0;
252 else if (MPFR_UNLIKELY (d < -MPFR_LDBL_MAX))
254 MPFR_SET_INF (r);
255 MPFR_SET_NEG (r);
256 return 0;
258 /* Check for ZERO */
259 else if (MPFR_UNLIKELY (d == 0.0))
261 x.ld = d;
262 MPFR_SET_ZERO (r);
263 if (x.s.sign == 1)
264 MPFR_SET_NEG(r);
265 else
266 MPFR_SET_POS(r);
267 return 0;
270 /* now d is neither 0, nor NaN nor Inf */
271 MPFR_SAVE_EXPO_MARK (expo);
273 MPFR_MANT (tmp) = tmpmant;
274 MPFR_PREC (tmp) = 64;
276 /* Extract sign */
277 x.ld = d;
278 signd = MPFR_SIGN_POS;
279 if (x.ld < 0.0)
281 signd = MPFR_SIGN_NEG;
282 x.ld = -x.ld;
285 /* Extract mantissa */
286 #if BITS_PER_MP_LIMB >= 64
287 tmpmant[0] = ((mp_limb_t) x.s.manh << 32) | ((mp_limb_t) x.s.manl);
288 #else
289 tmpmant[0] = (mp_limb_t) x.s.manl;
290 tmpmant[1] = (mp_limb_t) x.s.manh;
291 #endif
293 /* Normalize mantissa */
294 i = MPFR_LIMBS_PER_LONG_DOUBLE;
295 MPN_NORMALIZE_NOT_ZERO (tmpmant, i);
296 k = MPFR_LIMBS_PER_LONG_DOUBLE - i;
297 count_leading_zeros (cnt, tmpmant[i - 1]);
298 if (MPFR_LIKELY (cnt != 0))
299 mpn_lshift (tmpmant + k, tmpmant, i, cnt);
300 else if (k != 0)
301 MPN_COPY (tmpmant + k, tmpmant, i);
302 if (MPFR_UNLIKELY (k != 0))
303 MPN_ZERO (tmpmant, k);
305 /* Set exponent */
306 exp = (mp_exp_t) ((x.s.exph << 8) + x.s.expl); /* 15-bit unsigned int */
307 if (MPFR_UNLIKELY (exp == 0))
308 exp -= 0x3FFD;
309 else
310 exp -= 0x3FFE;
312 MPFR_SET_EXP (tmp, exp - cnt - k * BITS_PER_MP_LIMB);
314 /* tmp is exact */
315 inexact = mpfr_set4 (r, tmp, rnd_mode, signd);
317 MPFR_SAVE_EXPO_FREE (expo);
318 return mpfr_check_range (r, inexact, rnd_mode);
321 #endif