diff -Naurd mpfr-2.2.0-p7/get_f.c mpfr-2.2.0-p8/get_f.c --- mpfr-2.2.0-p7/get_f.c 2005-06-08 09:53:48.000000000 +0000 +++ mpfr-2.2.0-p8/get_f.c 2006-01-13 15:04:34.000000000 +0000 @@ -1,6 +1,6 @@ /* mpfr_get_f -- convert a MPFR number to a GNU MPF number -Copyright 2005 Free Software Foundation, Inc. +Copyright 2005, 2006 Free Software Foundation, Inc. This file is part of the MPFR Library. @@ -27,8 +27,9 @@ int mpfr_get_f (mpf_ptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) { - unsigned long sx, sy, precx, precy, sh; - mp_exp_t ey; + mp_size_t sx, sy; + mp_prec_t precx, precy; + int sh; if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(y))) { @@ -44,20 +45,18 @@ sx = PREC(x); /* number of limbs of the mantissa of x */ precy = MPFR_PREC(y); - precx = sx * BITS_PER_MP_LIMB; - sy = 1 + (MPFR_PREC(y) - 1) / BITS_PER_MP_LIMB; + precx = (mp_prec_t) sx * BITS_PER_MP_LIMB; + sy = MPFR_LIMB_SIZE (y); /* since mpf numbers are represented in base 2^BITS_PER_MP_LIMB, we loose -EXP(y) % BITS_PER_MP_LIMB bits in the most significant limb */ - ey = MPFR_GET_EXP(y) % BITS_PER_MP_LIMB; - if (ey <= 0) - sh = (unsigned long) (-ey); - else /* 0 < ey < BITS_PER_MP_LIMB */ - sh = BITS_PER_MP_LIMB - (unsigned long) ey; + sh = MPFR_GET_EXP(y) % BITS_PER_MP_LIMB; + sh = sh <= 0 ? - sh : BITS_PER_MP_LIMB - sh; + MPFR_ASSERTD (sh >= 0); if (precy + sh <= precx) /* we can copy directly */ { - /* necessarily sy <= sx */ - if (sh) + MPFR_ASSERTN (sx >= sy); + if (sh != 0) mpn_rshift (PTR(x) + sx - sy, MPFR_MANT(y), sy, sh); else MPN_COPY (PTR(x) + sx - sy, MPFR_MANT(y), sy); @@ -68,17 +67,17 @@ else /* we have to round to precx - sh bits */ { mpfr_t z; - unsigned long sz; + mp_size_t sz; mpfr_init2 (z, precx - sh); - sz = 1 + (MPFR_PREC(z) - 1) / BITS_PER_MP_LIMB; + sz = MPFR_LIMB_SIZE (z); mpfr_set (z, y, rnd_mode); /* warning, sh may change due to rounding, but then z is a power of two, thus we can safely ignore its last bit which is 0 */ - ey = MPFR_GET_EXP(z) % BITS_PER_MP_LIMB; - sh = (ey <= 0) ? (unsigned long) (-ey) - : BITS_PER_MP_LIMB - (unsigned long) ey; - if (sh) + sh = MPFR_GET_EXP(z) % BITS_PER_MP_LIMB; + sh = sh <= 0 ? - sh : BITS_PER_MP_LIMB - sh; + MPFR_ASSERTD (sh >= 0); + if (sh != 0) mpn_rshift (PTR(x) + sx - sz, MPFR_MANT(z), sz, sh); else MPN_COPY (PTR(x) + sx - sz, MPFR_MANT(z), sz); diff -Naurd mpfr-2.2.0-p7/set_f.c mpfr-2.2.0-p8/set_f.c --- mpfr-2.2.0-p7/set_f.c 2005-08-18 16:35:13.000000000 +0000 +++ mpfr-2.2.0-p8/set_f.c 2006-01-12 10:34:40.000000000 +0000 @@ -1,6 +1,6 @@ /* mpfr_set_f -- set a MPFR number from a GNU MPF number -Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the MPFR Library. @@ -80,7 +80,22 @@ inexact = 0; } - MPFR_SET_EXP(y, EXP(x) * BITS_PER_MP_LIMB - cnt + carry); + /* warning: EXP(x) * BITS_PER_MP_LIMB may exceed the maximal exponent */ + if (EXP(x) > 1 + (__gmpfr_emax - 1) / BITS_PER_MP_LIMB) + { + /* EXP(x) >= 2 + floor((__gmpfr_emax-1)/BITS_PER_MP_LIMB) + EXP(x) >= 2 + (__gmpfr_emax - BITS_PER_MP_LIMB) / BITS_PER_MP_LIMB + >= 1 + __gmpfr_emax / BITS_PER_MP_LIMB + EXP(x) * BITS_PER_MP_LIMB >= __gmpfr_emax + BITS_PER_MP_LIMB + Since 0 <= cnt <= BITS_PER_MP_LIMB-1, and 0 <= carry <= 1, + we have then EXP(x) * BITS_PER_MP_LIMB - cnt + carry > __gmpfr_emax */ + return mpfr_overflow (y, rnd_mode, MPFR_SIGN (y)); + } + else + { + /* Do not use MPFR_SET_EXP as the exponent may be out of range. */ + MPFR_EXP (y) = EXP (x) * BITS_PER_MP_LIMB - (mp_exp_t) cnt + carry; + } - return inexact; + return mpfr_check_range (y, inexact, rnd_mode); } diff -Naurd mpfr-2.2.0-p7/tests/tget_f.c mpfr-2.2.0-p8/tests/tget_f.c --- mpfr-2.2.0-p7/tests/tget_f.c 2005-06-02 16:12:04.000000000 +0000 +++ mpfr-2.2.0-p8/tests/tget_f.c 2006-01-13 15:05:14.000000000 +0000 @@ -1,6 +1,6 @@ /* Test file for mpfr_get_f. -Copyright 2005 Free Software Foundation, Inc. +Copyright 2005, 2006 Free Software Foundation, Inc. This file is part of the MPFR Library. @@ -22,6 +22,7 @@ #include #include #include +#include #include "mpfr-test.h" @@ -31,6 +32,7 @@ mpf_t x; mpfr_t y; unsigned long i; + mp_exp_t e; MPFR_TEST_USE_RANDS (); tests_start_mpfr (); @@ -83,11 +85,14 @@ printf ("Error: mpfr_get_f(%lu) fails\n", i); exit (1); } - mpfr_set_si (y, (signed long) -i, GMP_RNDN); - if (mpfr_get_f (x, y, GMP_RNDN) || mpf_cmp_si (x, (signed long) -i)) + if (i <= - (unsigned long) LONG_MIN) { - printf ("Error: mpfr_get_f(-%lu) fails\n", i); - exit (1); + mpfr_set_si (y, - (long) i, GMP_RNDN); + if (mpfr_get_f (x, y, GMP_RNDN) || mpf_cmp_si (x, - (long) i)) + { + printf ("Error: mpfr_get_f(-%lu) fails\n", i); + exit (1); + } } i *= 2; } @@ -113,6 +118,42 @@ i *= 2; } + /* bug reported by Jim White */ + for (e = 0; e <= 2 * BITS_PER_MP_LIMB; e++) + { + /* test with 2^(-e) */ + mpfr_set_ui (y, 1, GMP_RNDN); + mpfr_div_2exp (y, y, e, GMP_RNDN); + mpfr_get_f (x, y, GMP_RNDN); + mpf_mul_2exp (x, x, e); + if (mpf_cmp_ui (x, 1) != 0) + { + printf ("Error: mpfr_get_f(x,y,GMP_RNDN) fails\n"); + printf ("y="); + mpfr_dump (y); + printf ("x="); + mpf_div_2exp (x, x, e); + mpf_dump (x); + exit (1); + } + + /* test with 2^(e) */ + mpfr_set_ui (y, 1, GMP_RNDN); + mpfr_mul_2exp (y, y, e, GMP_RNDN); + mpfr_get_f (x, y, GMP_RNDN); + mpf_div_2exp (x, x, e); + if (mpf_cmp_ui (x, 1) != 0) + { + printf ("Error: mpfr_get_f(x,y,GMP_RNDN) fails\n"); + printf ("y="); + mpfr_dump (y); + printf ("x="); + mpf_mul_2exp (x, x, e); + mpf_dump (x); + exit (1); + } + } + mpfr_clear (y); mpf_clear (x); diff -Naurd mpfr-2.2.0-p7/tests/tset_f.c mpfr-2.2.0-p8/tests/tset_f.c --- mpfr-2.2.0-p7/tests/tset_f.c 2005-09-09 15:18:00.000000000 +0000 +++ mpfr-2.2.0-p8/tests/tset_f.c 2006-01-12 10:31:42.000000000 +0000 @@ -1,6 +1,6 @@ /* Test file for mpfr_set_f. -Copyright 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the MPFR Library. @@ -22,6 +22,7 @@ #include #include #include +#include /* for ULONG_MAX */ #include "mpfr-test.h" @@ -30,6 +31,7 @@ { mpfr_t x, u; mpf_t y, z; + mp_exp_t emax; unsigned long k, pr; int r, inexact; @@ -87,8 +89,6 @@ } MPFR_ASSERTN(mpfr_cmp_ui_2exp (x, 1, 901) == 0); - mpfr_clear (u); - for (k = 1; k <= 100000; k++) { pr = 2 + (randlimb () & 255); @@ -131,7 +131,49 @@ mpf_mul_2exp (y, y, 1); } + mpf_set_ui (y, 1); + mpf_mul_2exp (y, y, ULONG_MAX); + mpfr_set_f (x, y, GMP_RNDN); + mpfr_set_ui (u, 1, GMP_RNDN); + mpfr_mul_2ui (u, u, ULONG_MAX, GMP_RNDN); + if (!mpfr_equal_p (x, u)) + { + printf ("Error: mpfr_set_f (x, y, GMP_RNDN) for y = 2^ULONG_MAX\n"); + exit (1); + } + + emax = mpfr_get_emax (); + + /* For mpf_mul_2exp, emax must fit in an unsigned long! */ + if (emax >= 0 && emax <= ULONG_MAX) + { + mpf_set_ui (y, 1); + mpf_mul_2exp (y, y, emax); + mpfr_set_f (x, y, GMP_RNDN); + mpfr_set_ui_2exp (u, 1, emax, GMP_RNDN); + if (!mpfr_equal_p (x, u)) + { + printf ("Error: mpfr_set_f (x, y, GMP_RNDN) for y = 2^emax\n"); + exit (1); + } + } + + /* For mpf_mul_2exp, emax - 1 must fit in an unsigned long! */ + if (emax >= 1 && emax - 1 <= ULONG_MAX) + { + mpf_set_ui (y, 1); + mpf_mul_2exp (y, y, emax - 1); + mpfr_set_f (x, y, GMP_RNDN); + mpfr_set_ui_2exp (u, 1, emax - 1, GMP_RNDN); + if (!mpfr_equal_p (x, u)) + { + printf ("Error: mpfr_set_f (x, y, GMP_RNDN) for y = 2^(emax-1)\n"); + exit (1); + } + } + mpfr_clear (x); + mpfr_clear (u); mpf_clear (y); mpf_clear (z);