(root)/
mpfr-4.2.1/
tests/
tset_ld.c
       1  /* Test file for mpfr_set_ld and mpfr_get_ld.
       2  
       3  Copyright 2002-2023 Free Software Foundation, Inc.
       4  Contributed by the AriC and Caramba projects, INRIA.
       5  
       6  This file is part of the GNU MPFR Library.
       7  
       8  The GNU MPFR Library is free software; you can redistribute it and/or modify
       9  it under the terms of the GNU Lesser General Public License as published by
      10  the Free Software Foundation; either version 3 of the License, or (at your
      11  option) any later version.
      12  
      13  The GNU 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 Lesser General Public
      16  License for more details.
      17  
      18  You should have received a copy of the GNU Lesser General Public License
      19  along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
      20  https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
      21  51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
      22  
      23  #include <float.h>
      24  
      25  #include "mpfr-test.h"
      26  
      27  static void
      28  check_gcc33_bug (void)
      29  {
      30    volatile long double x;
      31  
      32    x = (long double) 9007199254740992.0 + 1.0;
      33    if (x != 0.0)
      34      return;  /* OK */
      35    printf
      36      ("Detected optimization bug of gcc 3.3 on Alpha concerning long double\n"
      37       "comparisons; set_ld tests might fail (set_ld won't work correctly).\n"
      38       "See https://gcc.gnu.org/legacy-ml/gcc-bugs/2003-10/msg00853.html for\n"
      39       "more information.\n");
      40  }
      41  
      42  static int
      43  Isnan_ld (long double d)
      44  {
      45    /* Do not convert d to double as this can give an overflow, which
      46       may confuse compilers without IEEE 754 support (such as clang
      47       -fsanitize=undefined), or trigger a trap if enabled.
      48       The DOUBLE_ISNAN macro should work fine on long double. */
      49    if (DOUBLE_ISNAN (d))
      50      return 1;
      51    LONGDOUBLE_NAN_ACTION (d, goto yes);
      52    return 0;
      53   yes:
      54    return 1;
      55  }
      56  
      57  /* Return the minimal number of bits to represent d exactly (0 for zero).
      58     If flag is non-zero, also print d. */
      59  /* FIXME: This function doesn't work if the rounding precision is reduced. */
      60  static mpfr_prec_t
      61  print_binary (long double d, int flag)
      62  {
      63    long double e, f, r;
      64    long exp = 1;
      65    mpfr_prec_t prec = 0;
      66  
      67    if (Isnan_ld (d))
      68      {
      69        if (flag)
      70          printf ("NaN\n");
      71        return 0;
      72      }
      73    if (d < (long double) 0.0
      74  #if !defined(MPFR_ERRDIVZERO)
      75        || (d == (long double) 0.0 && (1.0 / (double) d < 0.0))
      76  #endif
      77        )
      78      {
      79        if (flag)
      80          printf ("-");
      81        d = -d;
      82      }
      83    /* now d >= 0 */
      84    /* Use 2 different tests for Inf, to avoid potential bugs
      85       in implementations. */
      86    if (Isnan_ld (d - d) || (d > 1 && d * 0.5 == d))
      87      {
      88        if (flag)
      89          printf ("Inf\n");
      90        return 0;
      91      }
      92    if (d == (long double) 0.0)
      93      {
      94        if (flag)
      95          printf ("0.0\n");
      96        return prec;
      97      }
      98    MPFR_ASSERTN (d > 0);
      99    e = (long double) 1.0;
     100    while (e > d)
     101      {
     102        e = e * (long double) 0.5;
     103        exp --;
     104      }
     105    if (flag == 2) printf ("1: e=%.36Le\n", e);
     106    MPFR_ASSERTN (d >= e);
     107    /* FIXME: There can be an overflow here, which may not be supported
     108       on all platforms. */
     109    while (f = e + e, d >= f)
     110      {
     111        e = f;
     112        exp ++;
     113      }
     114    if (flag == 2) printf ("2: e=%.36Le\n", e);
     115    MPFR_ASSERTN (e <= d && d < f);
     116    if (flag == 1)
     117      printf ("0.");
     118    if (flag == 2) printf ("3: d=%.36Le e=%.36Le prec=%ld\n", d, e,
     119                           (long) prec);
     120    /* Note: the method we use here to extract the bits of d is the following,
     121       to deal with the case where the rounding precision is less than the
     122       precision of d:
     123       (1) we accumulate the upper bits of d into f
     124       (2) when accumulating a new bit into f is not exact, we subtract
     125           f from d and reset f to 0
     126       This is guaranteed to work only when the rounding precision is at least
     127       half the precision of d, since otherwise d-f might not be exact.
     128       This method does not work with flush-to-zero on underflow. */
     129    f = 0.0; /* will hold accumulated powers of 2 */
     130    while (1)
     131      {
     132        prec++;
     133        r = f + e;
     134        /* r is close to f (in particular in the cases where f+e may
     135           not be exact), so that r - f should be exact. */
     136        if (r - f != e) /* f+e is not exact */
     137          {
     138            d -= f; /* should be exact */
     139            f = 0.0;
     140            r = e;
     141          }
     142        if (d >= r)
     143          {
     144            if (flag == 1)
     145              printf ("1");
     146            if (d == r)
     147              break;
     148            f = r;
     149          }
     150        else
     151          {
     152            if (flag == 1)
     153              printf ("0");
     154          }
     155        e *= (long double) 0.5;
     156        MPFR_ASSERTN (e != 0); /* may fail with flush-to-zero on underflow */
     157        if (flag == 2) printf ("4: d=%.36Le e=%.36Le prec=%ld\n", d, e,
     158                               (long) prec);
     159      }
     160    if (flag == 1)
     161      printf ("e%ld\n", exp);
     162    return prec;
     163  }
     164  
     165  /* Checks that a long double converted exactly to a MPFR number, then
     166     converted back to a long double gives the initial value, or in other
     167     words, mpfr_get_ld(mpfr_set_ld(d)) = d.
     168  */
     169  static void
     170  check_set_get (long double d)
     171  {
     172    mpfr_exp_t emin, emax;
     173    mpfr_t x;
     174    mpfr_prec_t prec;
     175    int r;
     176    long double e;
     177    int inex;
     178    int red;
     179  
     180    emin = mpfr_get_emin ();
     181    emax = mpfr_get_emax ();
     182  
     183    /* Select a precision to ensure that the conversion of d to x be exact. */
     184    prec = print_binary (d, 0);
     185    if (prec < MPFR_PREC_MIN)
     186      prec = MPFR_PREC_MIN;
     187    mpfr_init2 (x, prec);
     188  
     189    RND_LOOP(r)
     190      {
     191        inex = mpfr_set_ld (x, d, (mpfr_rnd_t) r);
     192        if (inex != 0)
     193          {
     194            printf ("Error: mpfr_set_ld should be exact (rnd = %s)\n",
     195                    mpfr_print_rnd_mode ((mpfr_rnd_t) r));
     196            /* We use 36 digits here, as the maximum LDBL_MANT_DIG value
     197               seen in the current implementations is 113 (binary128),
     198               and ceil(1+113*log(2)/log(10)) = 36. But the current glibc
     199               implementation of printf with double-double arithmetic
     200               (e.g. on PowerPC) is not accurate. */
     201            printf ("  d ~= %.36Le (output may be wrong!)\n", d);
     202            printf ("  inex = %d\n", inex);
     203            if (emin >= LONG_MIN)
     204              printf ("  emin = %ld\n", (long) emin);
     205            if (emax <= LONG_MAX)
     206              printf ("  emax = %ld\n", (long) emax);
     207            ld_trace ("  d", d);
     208            printf ("  d = ");
     209            print_binary (d, 1);
     210            printf ("  x = ");
     211            mpfr_dump (x);
     212            printf ("  MPFR_LDBL_MANT_DIG=%u\n", MPFR_LDBL_MANT_DIG);
     213            printf ("  prec=%ld\n", (long) prec);
     214            print_binary (d, 2);
     215            exit (1);
     216          }
     217        for (red = 0; red < 2; red++)
     218          {
     219            if (red)
     220              {
     221                mpfr_exp_t ex;
     222  
     223                if (MPFR_IS_SINGULAR (x))
     224                  break;
     225                ex = MPFR_GET_EXP (x);
     226                set_emin (ex);
     227                set_emax (ex);
     228              }
     229            e = mpfr_get_ld (x, (mpfr_rnd_t) r);
     230            set_emin (emin);
     231            set_emax (emax);
     232            if (inex == 0 && ((Isnan_ld(d) && ! Isnan_ld(e)) ||
     233                              (Isnan_ld(e) && ! Isnan_ld(d)) ||
     234                              (e != d && !(Isnan_ld(e) && Isnan_ld(d)))))
     235              {
     236                printf ("Error: mpfr_get_ld o mpfr_set_ld <> Id%s\n",
     237                        red ? ", reduced exponent range" : "");
     238                printf ("  rnd = %s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r));
     239                printf ("  d ~= %.36Le (output may be wrong!)\n", d);
     240                printf ("  e ~= %.36Le (output may be wrong!)\n", e);
     241                ld_trace ("  d", d);
     242                printf ("  x = ");
     243                mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN);
     244                printf ("\n");
     245                ld_trace ("  e", e);
     246                printf ("  d = ");
     247                print_binary (d, 1);
     248                printf ("  x = ");
     249                mpfr_dump (x);
     250                printf ("  e = ");
     251                print_binary (e, 1);
     252                printf ("  MPFR_LDBL_MANT_DIG=%u\n", MPFR_LDBL_MANT_DIG);
     253  #ifdef MPFR_NANISNAN
     254                if (Isnan_ld(d) || Isnan_ld(e))
     255                  printf ("The reason is that NAN == NAN. Please look at the "
     256                          "configure output\nand Section \"In case of problem\""
     257                          " of the INSTALL file.\n");
     258  #endif
     259                exit (1);
     260              }
     261          }
     262      }
     263  
     264    mpfr_clear (x);
     265  }
     266  
     267  static void
     268  test_small (void)
     269  {
     270    mpfr_t x, y, z;
     271    long double d;
     272  
     273    mpfr_init2 (x, MPFR_LDBL_MANT_DIG);
     274    mpfr_init2 (y, MPFR_LDBL_MANT_DIG);
     275    mpfr_init2 (z, MPFR_LDBL_MANT_DIG);
     276  
     277    /* x = 11906603631607553907/2^(16381+64) */
     278    mpfr_set_str (x, "0.1010010100111100110000001110101101000111010110000001111101110011E-16381", 2, MPFR_RNDN);
     279    d = mpfr_get_ld (x, MPFR_RNDN);  /* infinite loop? */
     280    mpfr_set_ld (y, d, MPFR_RNDN);
     281    mpfr_sub (z, x, y, MPFR_RNDN);
     282    mpfr_abs (z, z, MPFR_RNDN);
     283    mpfr_clear_erangeflag ();
     284    /* If long double = double, d should be equal to 0;
     285       in this case, everything is OK. */
     286    if (d != 0 && (mpfr_cmp_str (z, "1E-16434", 2, MPFR_RNDN) > 0 ||
     287                   mpfr_erangeflag_p ()))
     288      {
     289        printf ("Error with x = ");
     290        mpfr_out_str (stdout, 10, 21, x, MPFR_RNDN);
     291        printf (" = ");
     292        mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN);
     293        printf ("\n        -> d = %.33Le", d);
     294        printf ("\n        -> y = ");
     295        mpfr_out_str (stdout, 10, 21, y, MPFR_RNDN);
     296        printf (" = ");
     297        mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
     298        printf ("\n        -> |x-y| = ");
     299        mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
     300        printf ("\n");
     301        exit (1);
     302      }
     303  
     304    mpfr_clear (x);
     305    mpfr_clear (y);
     306    mpfr_clear (z);
     307  }
     308  
     309  static void
     310  test_fixed_bugs (void)
     311  {
     312    mpfr_t x;
     313    long double l, m;
     314  
     315    /* bug found by Steve Kargl (2009-03-14) */
     316    mpfr_init2 (x, MPFR_LDBL_MANT_DIG);
     317    mpfr_set_ui_2exp (x, 1, -16447, MPFR_RNDN);
     318    mpfr_get_ld (x, MPFR_RNDN);  /* an assertion failed in init2.c:50 */
     319  
     320    /* bug reported by Jakub Jelinek (2010-10-17)
     321       https://gforge.inria.fr/tracker/?func=detail&aid=11300 */
     322    mpfr_set_prec (x, MPFR_LDBL_MANT_DIG);
     323    /* l = 0x1.23456789abcdef0123456789abcdp-914L; */
     324    l = 8.215640181713713164092636634579e-276;
     325    mpfr_set_ld (x, l, MPFR_RNDN);
     326    m = mpfr_get_ld (x, MPFR_RNDN);
     327    if (m != l)
     328      {
     329        printf ("Error in get_ld o set_ld for l=%Le\n", l);
     330        printf ("Got m=%Le instead of l\n", m);
     331        exit (1);
     332      }
     333  
     334    /* another similar test which failed with extended double precision and the
     335       generic code for mpfr_set_ld */
     336    /* l = 0x1.23456789abcdef0123456789abcdp-968L; */
     337    l = 4.560596445887084662336528403703e-292;
     338    mpfr_set_ld (x, l, MPFR_RNDN);
     339    m = mpfr_get_ld (x, MPFR_RNDN);
     340    if (m != l)
     341      {
     342        printf ("Error in get_ld o set_ld for l=%Le\n", l);
     343        printf ("Got m=%Le instead of l\n", m);
     344        exit (1);
     345      }
     346  
     347    mpfr_clear (x);
     348  }
     349  
     350  static void
     351  check_subnormal (void)
     352  {
     353    long double d, e;
     354    mpfr_t x;
     355  
     356    d = 17.0;
     357    mpfr_init2 (x, MPFR_LDBL_MANT_DIG);
     358    while (d != 0.0)
     359      {
     360        mpfr_set_ld (x, d, MPFR_RNDN);
     361        e = mpfr_get_ld (x, MPFR_RNDN);
     362        if (e != d)
     363          {
     364            printf ("Error in check_subnormal for mpfr_get_ld o mpfr_set_ld\n");
     365            printf ("d=%.30Le\n", d);
     366            printf ("x="); mpfr_dump (x);
     367            printf ("e=%.30Le\n", e);
     368            exit (1);
     369          }
     370        d *= 0.5;
     371      }
     372    mpfr_clear (x);
     373  }
     374  
     375  static void
     376  check_overflow (void)
     377  {
     378    long double d, e;
     379    mpfr_t x;
     380    int i;
     381  
     382    mpfr_init2 (x, MPFR_LDBL_MANT_DIG);
     383    for (i = 0; i < 2; i++)
     384      {
     385        d = i == 0 ? LDBL_MAX : -LDBL_MAX;
     386        mpfr_set_ld (x, d, MPFR_RNDN);
     387        mpfr_mul_2ui (x, x, 1, MPFR_RNDN);
     388        e = mpfr_get_ld (x, MPFR_RNDN);
     389        if (! DOUBLE_ISINF (e) || (i == 0 ? (e < 0) : (e > 0)))
     390          {
     391            printf ("Error in check_overflow.\n");
     392            printf ("d=%Le\n", d);
     393            printf ("x="); mpfr_dump (x);
     394            printf ("e=%Le\n", e);
     395            exit (1);
     396          }
     397      }
     398    mpfr_clear (x);
     399  }
     400  
     401  /* issue reported by Sisyphus on powerpc */
     402  static void
     403  test_20140212 (void)
     404  {
     405    mpfr_t fr1, fr2;
     406    long double ld, h, l, ld2;
     407    int i, c1, c2;
     408  
     409    mpfr_init2 (fr1, 106);
     410    mpfr_init2 (fr2, 2098);
     411  
     412    for (h = 1.0L, i = 0; i < 1023; i++)
     413      h *= 2.0L;
     414    for (l = 1.0L, i = 0; i < 1074; i++)
     415      l *= 0.5L;
     416    ld = h + l; /* rounding of 2^1023 + 2^(-1074) */
     417  
     418    mpfr_set_ld (fr1, ld, MPFR_RNDN);
     419    mpfr_set_ld (fr2, ld, MPFR_RNDN);
     420  
     421    c1 = mpfr_cmp_ld (fr1, ld);
     422    c2 = mpfr_cmp_ld (fr2, ld);
     423  
     424    /* If long double is binary64, then ld = fr1 = fr2 = 2^1023.
     425       If long double is double-double, then ld = 2^1023 + 2^(-1074),
     426       fr1 = 2^1023 and fr2 = 2^1023 + 2^(-1074) */
     427    MPFR_ASSERTN(ld == h ? (c1 == 0) : (c1 < 0));
     428  
     429    MPFR_ASSERTN(c2 == 0);
     430  
     431    ld2 = mpfr_get_ld (fr2, MPFR_RNDN);
     432    MPFR_ASSERTN(ld2 == ld);
     433  
     434    mpfr_clear (fr1);
     435    mpfr_clear (fr2);
     436  }
     437  
     438  /* bug reported by Walter Mascarenhas
     439     https://sympa.inria.fr/sympa/arc/mpfr/2016-09/msg00005.html */
     440  static void
     441  bug_20160907 (void)
     442  {
     443  #if HAVE_LDOUBLE_IEEE_EXT_LITTLE
     444    long double dn, ld;
     445    mpfr_t mp;
     446    long e;
     447    mpfr_long_double_t x;
     448  
     449    /* the following is the encoding of the smallest subnormal number
     450       for HAVE_LDOUBLE_IEEE_EXT_LITTLE */
     451    x.s.manl = 1;
     452    x.s.manh = 0;
     453    x.s.expl = 0;
     454    x.s.exph = 0;
     455    x.s.sign= 0;
     456    dn = x.ld;
     457    e = -16445;
     458    /* dn=2^e is now the smallest subnormal. */
     459  
     460    mpfr_init2 (mp, 64);
     461    mpfr_set_ui_2exp (mp, 1, e - 1, MPFR_RNDN);
     462    ld = mpfr_get_ld (mp, MPFR_RNDU);
     463    /* since mp = 2^(e-1) and ld is rounded upwards, we should have
     464       ld = 2^e */
     465    if (ld != dn)
     466      {
     467        printf ("Error, ld = %Le <> dn = %Le\n", ld, dn);
     468        printf ("mp=");
     469        mpfr_out_str (stdout, 10, 0, mp, MPFR_RNDN);
     470        printf ("\n");
     471        printf ("mp="); mpfr_dump (mp);
     472        exit (1);
     473      }
     474  
     475    /* check a few more numbers */
     476    for (e = -16446; e <= -16381; e++)
     477      {
     478        mpfr_set_ui_2exp (mp, 1, e, MPFR_RNDN);
     479        ld = mpfr_get_ld (mp, MPFR_RNDU);
     480        mpfr_set_ld (mp, ld, MPFR_RNDU);
     481        /* mp is 2^e rounded up, thus should be >= 2^e */
     482        if (mpfr_cmp_ui_2exp (mp, 1, e) < 0)
     483          {
     484            if (tests_run_within_valgrind () && MPFR_IS_ZERO (mp))
     485              {
     486                /* Since this is not a bug in MPFR and it is just caused by
     487                   Valgrind, let's output a message and skip the remaining
     488                   part of the test without an error. Note that the message
     489                   will be not be visible via "make check".
     490                   Note that the other tests do not fail probably because
     491                   long double has the same behavior as double (which is
     492                   allowed by the C standard), but here this is a test that
     493                   is specific to x86 extended precision. */
     494                printf
     495                  ("Error in bug_20160907 due to a bug in Valgrind.\n"
     496                   "https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=890215\n"
     497                   "https://bugs.kde.org/show_bug.cgi?id=421262\n");
     498                break;
     499              }
     500            printf ("Error, expected value >= 2^(%ld)\n", e);
     501            printf ("got "); mpfr_dump (mp);
     502            exit (1);
     503          }
     504  
     505        mpfr_set_ui_2exp (mp, 1, e, MPFR_RNDN);
     506        ld = mpfr_get_ld (mp, MPFR_RNDD);
     507        mpfr_set_ld (mp, ld, MPFR_RNDD);
     508        /* mp is 2^e rounded down, thus should be <= 2^e */
     509        if (mpfr_cmp_ui_2exp (mp, 1, e) > 0)
     510          {
     511            printf ("Error, expected value <= 2^(%ld)\n", e);
     512            printf ("got "); mpfr_dump (mp);
     513            exit (1);
     514          }
     515      }
     516  
     517    mpfr_clear (mp);
     518  #endif
     519  }
     520  
     521  int
     522  main (int argc, char *argv[])
     523  {
     524    volatile long double d, e, maxp2;
     525    mpfr_t x;
     526    int i;
     527    mpfr_exp_t emax;
     528  
     529    tests_start_mpfr ();
     530    mpfr_test_init ();
     531  
     532    check_gcc33_bug ();
     533    test_fixed_bugs ();
     534  
     535    mpfr_init2 (x, MPFR_LDBL_MANT_DIG + 64);
     536  
     537  #if !defined(MPFR_ERRDIVZERO)
     538    /* check NaN */
     539    mpfr_set_nan (x);
     540    d = mpfr_get_ld (x, MPFR_RNDN);
     541    check_set_get (d);
     542  #endif
     543  
     544    /* check +0.0 and -0.0 */
     545    d = 0.0;
     546    check_set_get (d);
     547    d = DBL_NEG_ZERO;
     548    check_set_get (d);
     549  
     550    /* check that the sign of -0.0 is set */
     551    mpfr_set_ld (x, DBL_NEG_ZERO, MPFR_RNDN);
     552    if (MPFR_IS_POS (x))
     553      {
     554  #if defined(HAVE_SIGNEDZ)
     555        printf ("Error: sign of -0.0 is not set correctly\n");
     556        exit (1);
     557  #else
     558        /* Non IEEE doesn't support negative zero yet */
     559        printf ("Warning: sign of -0.0 is not set correctly\n");
     560  #endif
     561      }
     562  
     563  #if !defined(MPFR_ERRDIVZERO)
     564    /* check +Inf */
     565    mpfr_set_inf (x, 1);
     566    d = mpfr_get_ld (x, MPFR_RNDN);
     567    check_set_get (d);
     568  
     569    /* check -Inf */
     570    mpfr_set_inf (x, -1);
     571    d = mpfr_get_ld (x, MPFR_RNDN);
     572    check_set_get (d);
     573  #endif
     574  
     575    /* check the largest power of two */
     576    maxp2 = 1.0;
     577    while (maxp2 < LDBL_MAX / 2.0)
     578      maxp2 *= 2.0;
     579    check_set_get (maxp2);
     580    check_set_get (-maxp2);
     581  
     582    d = LDBL_MAX;
     583    e = d / 2.0;
     584    if (e != maxp2)  /* false under NetBSD/x86 */
     585      {
     586        /* d = LDBL_MAX does not have excess precision. */
     587        check_set_get (d);
     588        check_set_get (-d);
     589      }
     590  
     591    /* check the smallest power of two */
     592    d = 1.0;
     593    while ((e = d / 2.0) != (long double) 0.0 && e != d)
     594      d = e;
     595    check_set_get (d);
     596    check_set_get (-d);
     597  
     598    /* check that 2^i, 2^i+1, 2^i-1 and 2^i-2^(i-2)-1 are correctly converted */
     599    d = 1.0;
     600    for (i = 1; i < MPFR_LDBL_MANT_DIG + 8; i++)
     601      {
     602        d = 2.0 * d; /* d = 2^i */
     603        check_set_get (d);
     604        if (d + 1.0 != d)
     605          check_set_get (d + 1.0);
     606        else
     607          {
     608            mpfr_set_ui_2exp (x, 1, i, MPFR_RNDN);
     609            mpfr_add_ui (x, x, 1, MPFR_RNDN);
     610            e = mpfr_get_ld (x, MPFR_RNDN);
     611            check_set_get (e);
     612          }
     613        if (d - 1.0 != d)
     614          check_set_get (d - 1.0);
     615        else
     616          {
     617            mpfr_set_ui_2exp (x, 1, i, MPFR_RNDN);
     618            mpfr_sub_ui (x, x, 1, MPFR_RNDN);
     619            e = mpfr_get_ld (x, MPFR_RNDN);
     620            check_set_get (e);
     621          }
     622        if (i < 3)
     623          continue;
     624        /* The following test triggers a failure in r10844 for i = 56,
     625           with gcc -mpc64 on x86 (64-bit ABI). */
     626        mpfr_set_ui_2exp (x, 3, i-2, MPFR_RNDN);
     627        mpfr_sub_ui (x, x, 1, MPFR_RNDN);
     628        e = mpfr_get_ld (x, MPFR_RNDN);
     629        check_set_get (e);
     630      }
     631  
     632    for (i = 0; i < 10000; i++)
     633      {
     634        mpfr_urandomb (x, RANDS);
     635        d = mpfr_get_ld (x, MPFR_RNDN);
     636        check_set_get (d);
     637      }
     638  
     639    /* check with reduced emax to exercise overflow */
     640    emax = mpfr_get_emax ();
     641    mpfr_set_prec (x, 2);
     642    set_emax (1);
     643    mpfr_set_ld (x, (long double) 2.0, MPFR_RNDN);
     644    MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
     645    for (d = (long double) 2.0, i = 0; i < 13; i++, d *= d);
     646    /* now d = 2^8192, or an infinity (e.g. with double or double-double) */
     647    mpfr_set_ld (x, d, MPFR_RNDN);
     648    MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
     649    set_emax (emax);
     650  
     651    mpfr_clear (x);
     652  
     653    test_small ();
     654  
     655    check_subnormal ();
     656  #if !defined(MPFR_ERRDIVZERO)
     657    check_overflow ();
     658  #endif
     659  
     660    test_20140212 ();
     661    bug_20160907 ();
     662  
     663    tests_end_mpfr ();
     664  
     665    return 0;
     666  }