Annotation of OpenXM_contrib/gmp/mpfr/set_d.c, Revision 1.1.1.1
1.1 maekawa 1: /* mpfr_set_d, mpfr_get_d -- convert a multiple precision floating-point number
2: from/to a machine double precision float
3:
4: Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
5:
6: This file is part of the MPFR Library.
7:
8: The MPFR Library is free software; you can redistribute it and/or modify
9: it under the terms of the GNU Library General Public License as published by
10: the Free Software Foundation; either version 2 of the License, or (at your
11: option) any later version.
12:
13: The MPFR Library is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
16: License for more details.
17:
18: You should have received a copy of the GNU Library General Public License
19: along with the MPFR Library; see the file COPYING.LIB. If not, write to
20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21: MA 02111-1307, USA. */
22:
23: #if __GNUC__ /* gcc "patched" headers seem to omit isnan... */
24: extern int isnan(double);
25: #endif
26: #include <math.h> /* for isnan and NaN */
27:
28: #include "gmp.h"
29: #include "gmp-impl.h"
30: #include "longlong.h"
31: #include "mpfr.h"
32:
33: #define NaN sqrt(-1) /* ensures a machine-independent NaN */
34:
35: /* Included from gmp-2.0.2, patched to support denorms */
36:
37: #ifdef XDEBUG
38: #undef _GMP_IEEE_FLOATS
39: #endif
40:
41: #ifndef _GMP_IEEE_FLOATS
42: #define _GMP_IEEE_FLOATS 0
43: #endif
44:
45: int
46: #if __STDC__
47: __mpfr_extract_double (mp_ptr rp, double d, int e)
48: #else
49: __mpfr_extract_double (rp, d, e)
50: mp_ptr rp;
51: double d;
52: int e;
53: #endif
54: /* e=0 iff BITS_PER_MP_LIMB=32 and rp has only one limb */
55: {
56: long exp;
57: mp_limb_t manl;
58: #if BITS_PER_MP_LIMB == 32
59: mp_limb_t manh;
60: #endif
61:
62: /* BUGS
63:
64: 1. Should handle Inf and NaN in IEEE specific code.
65: 2. Handle Inf and NaN also in default code, to avoid hangs.
66: 3. Generalize to handle all BITS_PER_MP_LIMB >= 32.
67: 4. This lits is incomplete and misspelled.
68: */
69:
70: if (d == 0.0)
71: {
72: rp[0] = 0;
73: #if BITS_PER_MP_LIMB == 32
74: if (e) rp[1] = 0;
75: #endif
76: return 0;
77: }
78:
79: #if _GMP_IEEE_FLOATS
80: {
81: union ieee_double_extract x;
82: x.d = d;
83:
84: exp = x.s.exp;
85: if (exp)
86: {
87: #if BITS_PER_MP_LIMB == 64
88: manl = (((mp_limb_t) 1 << 63)
89: | ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11));
90: #else
91: manh = ((mp_limb_t) 1 << 31) | (x.s.manh << 11) | (x.s.manl >> 21);
92: manl = x.s.manl << 11;
93: #endif
94: }
95: else
96: {
97: #if BITS_PER_MP_LIMB == 64
98: manl = ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11);
99: #else
100: manh = (x.s.manh << 11) | (x.s.manl >> 21);
101: manl = x.s.manl << 11;
102: #endif
103: }
104: }
105: #else
106: {
107: /* Unknown (or known to be non-IEEE) double format. */
108: exp = 0;
109: if (d >= 1.0)
110: {
111: if (d * 0.5 == d)
112: abort ();
113:
114: while (d >= 32768.0)
115: {
116: d *= (1.0 / 65536.0);
117: exp += 16;
118: }
119: while (d >= 1.0)
120: {
121: d *= 0.5;
122: exp += 1;
123: }
124: }
125: else if (d < 0.5)
126: {
127: while (d < (1.0 / 65536.0))
128: {
129: d *= 65536.0;
130: exp -= 16;
131: }
132: while (d < 0.5)
133: {
134: d *= 2.0;
135: exp -= 1;
136: }
137: }
138:
139: d *= MP_BASE_AS_DOUBLE;
140: #if BITS_PER_MP_LIMB == 64
141: manl = d;
142: #else
143: manh = d;
144: manl = (d - manh) * MP_BASE_AS_DOUBLE;
145: #endif
146:
147: exp += 1022;
148: }
149: #endif
150:
151: if (exp) exp = (unsigned) exp - 1022; else exp = -1021;
152:
153: #if BITS_PER_MP_LIMB == 64
154: rp[0] = manl;
155: #else
156: if (e) {
157: rp[1] = manh;
158: rp[0] = manl;
159: }
160: else {
161: rp[0] = manh;
162: }
163: #endif
164:
165: return exp;
166: }
167:
168: /* End of part included from gmp-2.0.2 */
169: /* Part included from gmp temporary releases */
170: double
171: #if __STDC__
172: __mpfr_scale2 (double d, int exp)
173: #else
174: __mpfr_scale2 (d, exp)
175: double d;
176: int exp;
177: #endif
178: {
179: #if _GMP_IEEE_FLOATS
180: {
181: union ieee_double_extract x;
182: x.d = d;
183: exp += x.s.exp;
184: x.s.exp = exp;
185: if (exp >= 2047)
186: {
187: /* Return +-infinity */
188: x.s.exp = 2047;
189: x.s.manl = x.s.manh = 0;
190: }
191: else if (exp < 1)
192: {
193: x.s.exp = 1; /* smallest exponent (biased) */
194: /* Divide result by 2 until we have scaled it to the right IEEE
195: denormalized number, but stop if it becomes zero. */
196: while (exp < 1 && x.d != 0)
197: {
198: x.d *= 0.5;
199: exp++;
200: }
201: }
202: return x.d;
203: }
204: #else
205: {
206: double factor, r;
207:
208: factor = 2.0;
209: if (exp < 0)
210: {
211: factor = 0.5;
212: exp = -exp;
213: }
214: r = d;
215: if (exp != 0)
216: {
217: if ((exp & 1) != 0)
218: r *= factor;
219: exp >>= 1;
220: while (exp != 0)
221: {
222: factor *= factor;
223: if ((exp & 1) != 0)
224: r *= factor;
225: exp >>= 1;
226: }
227: }
228: return r;
229: }
230: #endif
231: }
232:
233:
234: /* End of part included from gmp */
235:
236: void
237: #if __STDC__
238: mpfr_set_d(mpfr_t r, double d, unsigned char rnd_mode)
239: #else
240: mpfr_set_d(r, d, rnd_mode)
241: mpfr_t r;
242: double d;
243: unsigned char rnd_mode;
244: #endif
245: {
246: int signd, sizer; unsigned int cnt;
247:
248: if (d == 0) { SET_ZERO(r); return; }
249: else if (isnan(d)) { SET_NAN(r); return; }
250:
251: signd = (d < 0) ? -1 : 1;
252: d = ABS (d);
253: sizer = (PREC(r)-1)/BITS_PER_MP_LIMB + 1;
254:
255: /* warning: __mpfr_extract_double requires at least two limbs */
256: if (sizer < MPFR_LIMBS_PER_DOUBLE)
257: EXP(r) = __mpfr_extract_double (MANT(r), d, 0);
258: else
259: EXP(r) = __mpfr_extract_double (MANT(r) + sizer - MPFR_LIMBS_PER_DOUBLE, d, 1);
260:
261: if (sizer > MPFR_LIMBS_PER_DOUBLE)
262: MPN_ZERO(MANT(r), sizer - MPFR_LIMBS_PER_DOUBLE);
263:
264: count_leading_zeros(cnt, MANT(r)[sizer-1]);
265: if (cnt) mpn_lshift(MANT(r), MANT(r), sizer, cnt);
266:
267: EXP(r) -= cnt;
268: if (SIZE(r)*signd<0) CHANGE_SIGN(r);
269:
270: mpfr_round(r, rnd_mode, PREC(r));
271: return;
272: }
273:
274: double
275: #if __STDC__
276: mpfr_get_d2(mpfr_srcptr src, long e)
277: #else
278: mpfr_get_d2(src, e)
279: mpfr_srcptr(src);
280: long e;
281: #endif
282: {
283: double res;
284: mp_size_t size, i, n_limbs_to_use;
285: mp_ptr qp;
286: int negative;
287:
288: if (FLAG_NAN(src)) {
289: #ifdef DEBUG
290: printf("recognized NaN\n");
291: #endif
292: return NaN; }
293: if (NOTZERO(src)==0) return 0.0;
294: size = 1+(PREC(src)-1)/BITS_PER_MP_LIMB;
295: qp = MANT(src);
296: negative = (SIGN(src)==-1);
297:
298: /* Warning: don't compute the abs(res) and set the sign afterwards,
299: otherwise the current machine rounding mode will not be taken
300: correctly into account. */
301: /* res = (negative) ? -(double)qp[size - 1] : qp[size - 1]; */
302: res = 0.0;
303: /* Warning: an arbitrary number of limbs may be required for an exact
304: rounding. The following code is correct but not optimal since one
305: may be able to decide without considering all limbs. */
306: /* n_limbs_to_use = MIN (MPFR_LIMBS_PER_DOUBLE, size); */
307: n_limbs_to_use = size;
308: /* Accumulate the limbs from less significant to most significant
309: otherwise due to rounding we may accumulate several ulps,
310: especially in rounding towards -/+infinity. */
311: for (i = n_limbs_to_use; i>=1; i--)
312: res = res / MP_BASE_AS_DOUBLE +
313: ((negative) ? -(double)qp[size - i] : qp[size - i]);
314: res = __mpfr_scale2 (res, e - BITS_PER_MP_LIMB);
315:
316: return res;
317: }
318:
319: double
320: #if __STDC__
321: mpfr_get_d(mpfr_srcptr src)
322: #else
323: mpfr_get_d(src)
324: mpfr_srcptr src;
325: #endif
326: {
327: return mpfr_get_d2(src, EXP(src));
328: }
329:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>