(root)/
mpfr-4.2.1/
tests/
trint.c
       1  /* Test file for mpfr_rint, mpfr_trunc, mpfr_floor, mpfr_ceil, mpfr_round,
       2     mpfr_rint_trunc, mpfr_rint_floor, mpfr_rint_ceil, mpfr_rint_round.
       3  
       4  Copyright 2002-2023 Free Software Foundation, Inc.
       5  Contributed by the AriC and Caramba projects, INRIA.
       6  
       7  This file is part of the GNU MPFR Library.
       8  
       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 3 of the License, or (at your
      12  option) any later version.
      13  
      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.
      18  
      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.LESSER.  If not, see
      21  https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
      22  51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
      23  
      24  #include "mpfr-test.h"
      25  
      26  #if __MPFR_STDC (199901L)
      27  # include <math.h>
      28  #endif
      29  
      30  static void
      31  special (void)
      32  {
      33    mpfr_t x, y;
      34    mpfr_exp_t emax;
      35  
      36    mpfr_init (x);
      37    mpfr_init (y);
      38  
      39    mpfr_set_nan (x);
      40    mpfr_rint (y, x, MPFR_RNDN);
      41    MPFR_ASSERTN(mpfr_nan_p (y));
      42  
      43    mpfr_set_inf (x, 1);
      44    mpfr_rint (y, x, MPFR_RNDN);
      45    MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
      46  
      47    mpfr_set_inf (x, -1);
      48    mpfr_rint (y, x, MPFR_RNDN);
      49    MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) < 0);
      50  
      51    mpfr_set_ui (x, 0, MPFR_RNDN);
      52    mpfr_rint (y, x, MPFR_RNDN);
      53    MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS(y));
      54  
      55    mpfr_set_ui (x, 0, MPFR_RNDN);
      56    mpfr_neg (x, x, MPFR_RNDN);
      57    mpfr_rint (y, x, MPFR_RNDN);
      58    MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_NEG(y));
      59  
      60    /* coverage test */
      61    mpfr_set_prec (x, 2);
      62    mpfr_set_ui (x, 1, MPFR_RNDN);
      63    mpfr_mul_2ui (x, x, mp_bits_per_limb, MPFR_RNDN);
      64    mpfr_rint (y, x, MPFR_RNDN);
      65    MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
      66  
      67    /* another coverage test */
      68    emax = mpfr_get_emax ();
      69    set_emax (1);
      70    mpfr_set_prec (x, 3);
      71    mpfr_set_str_binary (x, "1.11E0");
      72    mpfr_set_prec (y, 2);
      73    mpfr_rint (y, x, MPFR_RNDU); /* x rounds to 1.0E1=0.1E2 which overflows */
      74    MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
      75    set_emax (emax);
      76  
      77    /* yet another */
      78    mpfr_set_prec (x, 97);
      79    mpfr_set_prec (y, 96);
      80    mpfr_set_str_binary (x, "-0.1011111001101111000111011100011100000110110110110000000111010001000101001111101010101011010111100E97");
      81    mpfr_rint (y, x, MPFR_RNDN);
      82    MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
      83  
      84    mpfr_set_prec (x, 53);
      85    mpfr_set_prec (y, 53);
      86    mpfr_set_str_binary (x, "0.10101100000000101001010101111111000000011111010000010E-1");
      87    mpfr_rint (y, x, MPFR_RNDU);
      88    MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
      89    mpfr_rint (y, x, MPFR_RNDD);
      90    MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS(y));
      91  
      92    mpfr_set_prec (x, 36);
      93    mpfr_set_prec (y, 2);
      94    mpfr_set_str_binary (x, "-11000110101010111111110111001.0000100");
      95    mpfr_rint (y, x, MPFR_RNDN);
      96    mpfr_set_str_binary (x, "-11E27");
      97    MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
      98  
      99    mpfr_set_prec (x, 39);
     100    mpfr_set_prec (y, 29);
     101    mpfr_set_str_binary (x, "-0.100010110100011010001111001001001100111E39");
     102    mpfr_rint (y, x, MPFR_RNDN);
     103    mpfr_set_str_binary (x, "-0.10001011010001101000111100101E39");
     104    MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
     105  
     106    mpfr_set_prec (x, 46);
     107    mpfr_set_prec (y, 32);
     108    mpfr_set_str_binary (x, "-0.1011100110100101000001011111101011001001101001E32");
     109    mpfr_rint (y, x, MPFR_RNDN);
     110    mpfr_set_str_binary (x, "-0.10111001101001010000010111111011E32");
     111    MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
     112  
     113    /* coverage test for mpfr_round */
     114    mpfr_set_prec (x, 3);
     115    mpfr_set_str_binary (x, "1.01E1"); /* 2.5 */
     116    mpfr_set_prec (y, 2);
     117    mpfr_round (y, x);
     118    /* since mpfr_round breaks ties away, should give 3 and not 2 as with
     119       the "round to even" rule */
     120    MPFR_ASSERTN(mpfr_cmp_ui (y, 3) == 0);
     121    /* same test for the function */
     122    (mpfr_round) (y, x);
     123    MPFR_ASSERTN(mpfr_cmp_ui (y, 3) == 0);
     124  
     125    mpfr_set_prec (x, 6);
     126    mpfr_set_prec (y, 3);
     127    mpfr_set_str_binary (x, "110.111");
     128    mpfr_round (y, x);
     129    if (mpfr_cmp_ui (y, 7))
     130      {
     131        printf ("Error in round(110.111)\n");
     132        exit (1);
     133      }
     134  
     135    /* Bug found by  Mark J Watkins */
     136    mpfr_set_prec (x, 84);
     137    mpfr_set_str_binary (x,
     138     "0.110011010010001000000111101101001111111100101110010000000000000" \
     139                         "000000000000000000000E32");
     140    mpfr_round (x, x);
     141    if (mpfr_cmp_str (x, "0.1100110100100010000001111011010100000000000000" \
     142                      "00000000000000000000000000000000000000E32", 2, MPFR_RNDN))
     143      {
     144        printf ("Rounding error when dest=src\n");
     145        exit (1);
     146      }
     147  
     148    mpfr_clear (x);
     149    mpfr_clear (y);
     150  }
     151  
     152  #define BASIC_TEST(F,J)                                                 \
     153    do                                                                    \
     154      {                                                                   \
     155        int red;                                                          \
     156        for (red = 0; red <= 1; red++)                                    \
     157          {                                                               \
     158            int inex1, inex2;                                             \
     159            unsigned int ex_flags, flags;                                 \
     160                                                                          \
     161            if (red)                                                      \
     162              {                                                           \
     163                set_emin (e);                                             \
     164                set_emax (e);                                             \
     165              }                                                           \
     166                                                                          \
     167            mpfr_clear_flags ();                                          \
     168            inex1 = mpfr_set_si (y, J, (mpfr_rnd_t) r);                   \
     169            ex_flags = __gmpfr_flags;                                     \
     170            mpfr_clear_flags ();                                          \
     171            inex2 = mpfr_rint_##F (z, x, (mpfr_rnd_t) r);                 \
     172            flags = __gmpfr_flags;                                        \
     173            if (! (mpfr_equal_p (y, z) &&                                 \
     174                   SAME_SIGN (inex1, inex2) &&                            \
     175                   flags == ex_flags))                                    \
     176              {                                                           \
     177                printf ("Basic test failed on mpfr_rint_" #F              \
     178                        ", prec = %d, i = %d, %s\n", prec, s * i,         \
     179                        mpfr_print_rnd_mode ((mpfr_rnd_t) r));            \
     180                printf ("i.e. x = ");                                     \
     181                mpfr_dump (x);                                            \
     182                if (red)                                                  \
     183                  printf ("with emin = emax = %d\n", e);                  \
     184                printf ("Expected ");                                     \
     185                mpfr_dump (y);                                            \
     186                printf ("with inex = %d (or equivalent)\n", inex1);       \
     187                printf ("     flags:");                                   \
     188                flags_out (ex_flags);                                     \
     189                printf ("Got      ");                                     \
     190                mpfr_dump (z);                                            \
     191                printf ("with inex = %d (or equivalent)\n", inex2);       \
     192                printf ("     flags:");                                   \
     193                flags_out (flags);                                        \
     194                exit (1);                                                 \
     195              }                                                           \
     196          }                                                               \
     197        set_emin (emin);                                                  \
     198        set_emax (emax);                                                  \
     199      }                                                                   \
     200    while (0)
     201  
     202  #define BASIC_TEST2(F,J,INEX)                                   \
     203    do                                                            \
     204      {                                                           \
     205        int red;                                                  \
     206        for (red = 0; red <= 1; red++)                            \
     207          {                                                       \
     208            int inex;                                             \
     209            unsigned int ex_flags, flags;                         \
     210                                                                  \
     211            if (red)                                              \
     212              {                                                   \
     213                set_emin (e);                                     \
     214                set_emax (e);                                     \
     215              }                                                   \
     216                                                                  \
     217            mpfr_clear_flags ();                                  \
     218            inex = mpfr_set_si (y, J, MPFR_RNDN);                 \
     219            MPFR_ASSERTN (inex == 0 || mpfr_overflow_p ());       \
     220            ex_flags = __gmpfr_flags;                             \
     221            mpfr_clear_flags ();                                  \
     222            inex = mpfr_##F (z, x);                               \
     223            if (inex != 0)                                        \
     224              ex_flags |= MPFR_FLAGS_INEXACT;                     \
     225            flags = __gmpfr_flags;                                \
     226            if (! (mpfr_equal_p (y, z) &&                         \
     227                   inex == (INEX) &&                              \
     228                   flags == ex_flags))                            \
     229              {                                                   \
     230                printf ("Basic test failed on mpfr_" #F           \
     231                        ", prec = %d, i = %d\n", prec, s * i);    \
     232                printf ("i.e. x = ");                             \
     233                mpfr_dump (x);                                    \
     234                if (red)                                          \
     235                  printf ("with emin = emax = %d\n", e);          \
     236                printf ("Expected ");                             \
     237                mpfr_dump (y);                                    \
     238                printf ("with inex = %d\n", (INEX));              \
     239                printf ("     flags:");                           \
     240                flags_out (ex_flags);                             \
     241                printf ("Got      ");                             \
     242                mpfr_dump (z);                                    \
     243                printf ("with inex = %d\n", inex);                \
     244                printf ("     flags:");                           \
     245                flags_out (flags);                                \
     246                exit (1);                                         \
     247              }                                                   \
     248          }                                                       \
     249        set_emin (emin);                                          \
     250        set_emax (emax);                                          \
     251      }                                                           \
     252    while (0)
     253  
     254  /* Test mpfr_rint_* on i/4 with |i| between 1 and 72. */
     255  static void
     256  basic_tests (void)
     257  {
     258    mpfr_t x, y, z;
     259    int prec, s, i, r;
     260    mpfr_exp_t emin, emax;
     261  
     262    emin = mpfr_get_emin ();
     263    emax = mpfr_get_emax ();
     264  
     265    mpfr_init2 (x, 16);
     266    for (prec = MPFR_PREC_MIN; prec <= 7; prec++)
     267      {
     268        mpfr_inits2 (prec, y, z, (mpfr_ptr) 0);
     269        for (s = 1; s >= -1; s -= 2)
     270          for (i = 1; i <= 72; i++)
     271            {
     272              int k, t, u, v, f, e, b;
     273  
     274              for (t = i/4, k = 0; t >= 1 << prec; t >>= 1, k++)
     275                ;
     276              b = !(t & 1);
     277              t <<= k;
     278              for (u = (i+3)/4, k = 0; u >= 1 << prec; u = (u+1)/2, k++)
     279                ;
     280              u <<= k;
     281              v = i < (t+u) << 1 ? t : u;
     282              if (b)
     283                b = i == (t+u) << 1;
     284              f = t == u ? 0 : i % 4 == 0 ? 1 : 2;
     285  
     286              mpfr_set_si_2exp (x, s * i, -2, MPFR_RNDN);
     287              e = mpfr_get_exp (x);
     288              RND_LOOP_NO_RNDF (r)
     289                {
     290                  BASIC_TEST (trunc, s * (i/4));
     291                  BASIC_TEST (floor, s > 0 ? i/4 : - ((i+3)/4));
     292                  BASIC_TEST (ceil, s > 0 ? (i+3)/4 : - (i/4));
     293                  BASIC_TEST (round, s * ((i+2)/4));
     294                  BASIC_TEST (roundeven, s * (i % 8 == 2 ? i/4 : (i+2)/4));
     295                }
     296              BASIC_TEST2 (trunc, s * t, - s * f);
     297              BASIC_TEST2 (floor, s > 0 ? t : - u, - f);
     298              BASIC_TEST2 (ceil, s > 0 ? u : - t, f);
     299              BASIC_TEST2 (round, s * v, v == t ? - s * f : s * f);
     300              BASIC_TEST2 (roundeven, s * (b ? t : v),
     301                           b || v == t ? - s * f : s * f);
     302            }
     303        mpfr_clears (y, z, (mpfr_ptr) 0);
     304      }
     305    mpfr_clear (x);
     306  }
     307  
     308  #if __MPFR_STDC (199901L)
     309  
     310  typedef int (*F2)(mpfr_ptr, mpfr_srcptr);
     311  
     312  /* The argument g below will be of type F2 with args (mpfr_ptr, mpfr_srcptr),
     313     except for mpfr_rint, with args (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t). So,
     314     when passing mpfr_rint, we need a cast: "(F2) &mpfr_rint". The cast will
     315     also be needed to compare the pointers: "g == (F2) &mpfr_rint", and that's
     316     all. */
     317  
     318  #if defined(__GNUC__)
     319  #pragma GCC diagnostic push
     320  #if __GNUC__ >= 8 || __clang_major__ >= 13
     321  #pragma GCC diagnostic ignored "-Wcast-function-type"
     322  #endif
     323  #endif
     324  
     325  static void
     326  test_fct (double (*f)(double), F2 g, const char *s, mpfr_rnd_t r)
     327  {
     328    double d, y;
     329    mpfr_t dd, yy;
     330  
     331    mpfr_init2 (dd, 53);
     332    mpfr_init2 (yy, 53);
     333    for (d = -5.0; d <= 5.0; d += 0.25)
     334      {
     335        mpfr_set_d (dd, d, r);
     336        y = (*f)(d);
     337        if (g == (F2) &mpfr_rint)
     338          mpfr_rint (yy, dd, r);
     339        else
     340          (*g)(yy, dd);
     341        mpfr_set_d (dd, y, r);
     342        if (mpfr_cmp (yy, dd))
     343          {
     344            printf ("test_against_libc: incorrect result for %s, rnd = %s,"
     345                    " d = %g\ngot ", s, mpfr_print_rnd_mode (r), d);
     346            mpfr_out_str (stdout, 10, 0, yy, MPFR_RNDN);
     347            printf (" instead of %g\n", y);
     348            exit (1);
     349          }
     350      }
     351    mpfr_clear (dd);
     352    mpfr_clear (yy);
     353  }
     354  
     355  #define TEST_FCT(F) test_fct (&F, &mpfr_##F, #F, (mpfr_rnd_t) r)
     356  
     357  static void
     358  test_against_libc (void)
     359  {
     360    int r = MPFR_RNDN;
     361  
     362    (void) r;  /* avoid a warning by using r */
     363  #if HAVE_ROUND
     364    TEST_FCT (round);
     365  #endif
     366  #if HAVE_TRUNC
     367    TEST_FCT (trunc);
     368  #endif
     369  #if HAVE_FLOOR
     370    TEST_FCT (floor);
     371  #endif
     372  #if HAVE_CEIL
     373    TEST_FCT (ceil);
     374  #endif
     375  #if HAVE_NEARBYINT
     376    RND_LOOP (r)
     377      if (mpfr_set_machine_rnd_mode ((mpfr_rnd_t) r) == 0)
     378        test_fct (&nearbyint, (F2) &mpfr_rint, "rint", (mpfr_rnd_t) r);
     379  #endif
     380  }
     381  
     382  #if defined(__GNUC__)
     383  #pragma GCC diagnostic pop
     384  #endif
     385  
     386  #endif
     387  
     388  static void
     389  err (const char *str, mp_size_t s, mpfr_ptr x, mpfr_ptr y, mpfr_prec_t p,
     390       mpfr_rnd_t r, int trint, int inexact)
     391  {
     392    printf ("Error: %s\ns = %u, p = %u, r = %s, trint = %d, inexact = %d\nx = ",
     393            str, (unsigned int) s, (unsigned int) p, mpfr_print_rnd_mode (r),
     394            trint, inexact);
     395    mpfr_dump (x);
     396    printf ("y = ");
     397    mpfr_dump (y);
     398    exit (1);
     399  }
     400  
     401  static void
     402  coverage_03032011 (void)
     403  {
     404    mpfr_t in, out, cmp;
     405    int status;
     406    int precIn;
     407    char strData[(GMP_NUMB_BITS * 4)+256];
     408  
     409    precIn = GMP_NUMB_BITS * 4;
     410  
     411    mpfr_init2 (in, precIn);
     412    mpfr_init2 (out, GMP_NUMB_BITS);
     413    mpfr_init2 (cmp, GMP_NUMB_BITS);
     414  
     415    /* cmp = "0.1EprecIn+2" */
     416    /* The buffer size is sufficient, as precIn is small in practice. */
     417    sprintf (strData, "0.1E%d", precIn+2);
     418    mpfr_set_str_binary (cmp, strData);
     419  
     420    /* in = "0.10...01EprecIn+2" use all (precIn) significand bits */
     421    memset ((void *)strData, '0', precIn+2);
     422    strData[1] = '.';
     423    strData[2] = '1';
     424    sprintf (&strData[precIn+1], "1E%d", precIn+2);
     425    mpfr_set_str_binary (in, strData);
     426  
     427    status = mpfr_rint (out, in, MPFR_RNDN);
     428    if ((mpfr_cmp (out, cmp) != 0) || (status >= 0))
     429      {
     430        printf("mpfr_rint error :\n status is %d instead of 0\n", status);
     431        printf(" out value is ");
     432        mpfr_dump(out);
     433        printf(" instead of   ");
     434        mpfr_dump(cmp);
     435        exit (1);
     436      }
     437  
     438    mpfr_clear (cmp);
     439    mpfr_clear (out);
     440  
     441    mpfr_init2 (out, GMP_NUMB_BITS);
     442    mpfr_init2 (cmp, GMP_NUMB_BITS);
     443  
     444    /* cmp = "0.10...01EprecIn+2" use all (GMP_NUMB_BITS) significand bits */
     445    strcpy (&strData[GMP_NUMB_BITS+1], &strData[precIn+1]);
     446    mpfr_set_str_binary (cmp, strData);
     447  
     448    (MPFR_MANT(in))[2] = MPFR_LIMB_HIGHBIT;
     449    status = mpfr_rint (out, in, MPFR_RNDN);
     450  
     451    if ((mpfr_cmp (out, cmp) != 0) || (status <= 0))
     452      {
     453        printf("mpfr_rint error :\n status is %d instead of 0\n", status);
     454        printf(" out value is\n");
     455        mpfr_dump(out);
     456        printf(" instead of\n");
     457        mpfr_dump(cmp);
     458        exit (1);
     459      }
     460  
     461    mpfr_clear (cmp);
     462    mpfr_clear (out);
     463    mpfr_clear (in);
     464  }
     465  
     466  #define TEST_FUNCTION mpfr_rint_trunc
     467  #define TEST_RANDOM_EMIN -20
     468  #define TEST_RANDOM_ALWAYS_SCALE 1
     469  #define test_generic test_generic_trunc
     470  #include "tgeneric.c"
     471  
     472  #define TEST_FUNCTION mpfr_rint_floor
     473  #define TEST_RANDOM_EMIN -20
     474  #define TEST_RANDOM_ALWAYS_SCALE 1
     475  #define test_generic test_generic_floor
     476  #include "tgeneric.c"
     477  
     478  #define TEST_FUNCTION mpfr_rint_ceil
     479  #define TEST_RANDOM_EMIN -20
     480  #define TEST_RANDOM_ALWAYS_SCALE 1
     481  #define test_generic test_generic_ceil
     482  #include "tgeneric.c"
     483  
     484  #define TEST_FUNCTION mpfr_rint_round
     485  #define TEST_RANDOM_EMIN -20
     486  #define TEST_RANDOM_ALWAYS_SCALE 1
     487  #define test_generic test_generic_round
     488  #include "tgeneric.c"
     489  
     490  #define TEST_FUNCTION mpfr_rint_roundeven
     491  #define TEST_RANDOM_EMIN -20
     492  #define TEST_RANDOM_ALWAYS_SCALE 1
     493  #define test_generic test_generic_roundeven
     494  #include "tgeneric.c"
     495  
     496  int
     497  main (int argc, char *argv[])
     498  {
     499    mp_size_t s;
     500    mpz_t z;
     501    mpfr_prec_t p;
     502    mpfr_t x, y, t, u, v;
     503    int r;
     504    int inexact, sign_t;
     505  
     506    tests_start_mpfr ();
     507  
     508    mpfr_init (x);
     509    mpfr_init (y);
     510    mpz_init (z);
     511    mpfr_init (t);
     512    mpfr_init (u);
     513    mpfr_init (v);
     514    mpz_set_ui (z, 1);
     515    /* the code below works for 1 <= MPFR_PREC_MIN <= 2 */
     516    MPFR_ASSERTN(1 <= MPFR_PREC_MIN && MPFR_PREC_MIN <= 2);
     517    for (s = MPFR_PREC_MIN; s < 100; s++)
     518      {
     519        if (s > 1)
     520          {
     521            mpz_mul_2exp (z, z, 1);
     522            if (RAND_BOOL ())
     523              mpz_add_ui (z, z, 1);
     524          }
     525        /* now 2^(s-1) <= z < 2^s */
     526        mpfr_set_prec (x, s);
     527        mpfr_set_prec (t, s);
     528        mpfr_set_prec (u, s);
     529        if (mpfr_set_z (x, z, MPFR_RNDN))
     530          {
     531  #ifndef MPFR_USE_MINI_GMP
     532            gmp_printf ("Error: mpfr_set_z should be exact (z = %Zd, s = %u)\n",
     533                        z, (unsigned int) s);
     534  #else /* mini-gmp has no gmp_printf (at least in gmp-6.1.2) */
     535            printf ("mpfr_set_z should be exact\n");
     536  #endif
     537            exit (1);
     538          }
     539        if (RAND_BOOL ())
     540          mpfr_neg (x, x, MPFR_RNDN);
     541        if (RAND_BOOL ())
     542          mpfr_div_2ui (x, x, randlimb () % s, MPFR_RNDN);
     543        for (p = MPFR_PREC_MIN; p < 100; p++)
     544          {
     545            int trint;
     546            mpfr_set_prec (y, p);
     547            mpfr_set_prec (v, p);
     548            RND_LOOP (r)
     549              for (trint = 0; trint < 4; trint++)
     550                {
     551                  if (trint == 2)
     552                    inexact = mpfr_rint (y, x, (mpfr_rnd_t) r);
     553                  else if (trint == 3)
     554                    {
     555                      if (r != MPFR_RNDN)
     556                        continue;
     557                      inexact = mpfr_round (y, x);
     558                    }
     559                  else if (r == MPFR_RNDN)
     560                    inexact = (trint ? mpfr_roundeven (y, x) :
     561                               mpfr_rint_roundeven (y, x, MPFR_RNDZ));
     562                  else if (r == MPFR_RNDZ)
     563                    inexact = (trint ? mpfr_trunc (y, x) :
     564                               mpfr_rint_trunc (y, x, MPFR_RNDZ));
     565                  else if (r == MPFR_RNDU)
     566                    inexact = (trint ? mpfr_ceil (y, x) :
     567                               mpfr_rint_ceil (y, x, MPFR_RNDU));
     568                  else if (r == MPFR_RNDD)
     569                    inexact = (trint ? mpfr_floor (y, x) :
     570                               mpfr_rint_floor (y, x, MPFR_RNDD));
     571                  else
     572                    {
     573                      MPFR_ASSERTN (r == MPFR_RNDA || r == MPFR_RNDF);
     574                      continue;
     575                    }
     576                  if (mpfr_sub (t, y, x, MPFR_RNDN))
     577                    err ("subtraction 1 should be exact", s, x, y, p,
     578                         (mpfr_rnd_t) r, trint, inexact);
     579                  sign_t = mpfr_cmp_ui (t, 0);
     580                  if (trint != 0 &&
     581                      (((inexact == 0) && (sign_t != 0)) ||
     582                       ((inexact < 0) && (sign_t >= 0)) ||
     583                       ((inexact > 0) && (sign_t <= 0))))
     584                    err ("wrong inexact flag", s, x, y, p,
     585                         (mpfr_rnd_t) r, trint, inexact);
     586                  if (inexact == 0)
     587                    continue; /* end of the test for exact results */
     588  
     589                  if (((r == MPFR_RNDD || (r == MPFR_RNDZ && MPFR_IS_POS (x)))
     590                       && inexact > 0) ||
     591                      ((r == MPFR_RNDU || (r == MPFR_RNDZ && MPFR_IS_NEG (x)))
     592                       && inexact < 0))
     593                    err ("wrong rounding direction", s, x, y, p,
     594                         (mpfr_rnd_t) r, trint, inexact);
     595                  if (inexact < 0)
     596                    {
     597                      mpfr_add_ui (v, y, 1, MPFR_RNDU);
     598                      if (mpfr_cmp (v, x) <= 0)
     599                        err ("representable integer between x and "
     600                             "its rounded value", s, x, y, p,
     601                             (mpfr_rnd_t) r, trint, inexact);
     602                    }
     603                  else
     604                    {
     605                      mpfr_sub_ui (v, y, 1, MPFR_RNDD);
     606                      if (mpfr_cmp (v, x) >= 0)
     607                        err ("representable integer between x and "
     608                             "its rounded value", s, x, y, p,
     609                             (mpfr_rnd_t) r, trint, inexact);
     610                    }
     611                  if (r == MPFR_RNDN && trint != 0)
     612                    {
     613                      int cmp;
     614                      if (mpfr_sub (u, v, x, MPFR_RNDN))
     615                        err ("subtraction 2 should be exact", s, x, y, p,
     616                             (mpfr_rnd_t) r, trint, inexact);
     617                      cmp = mpfr_cmpabs (t, u);
     618                      if (cmp > 0)
     619                        err ("faithful rounding, but not the nearest integer",
     620                             s, x, y, p, (mpfr_rnd_t) r, trint, inexact);
     621                      if (cmp < 0)
     622                        continue;
     623                      /* |t| = |u|: x is the middle of two consecutive
     624                         representable integers. */
     625                      if (trint == 2)
     626                        {
     627                          /* halfway case for mpfr_rint in MPFR_RNDN rounding
     628                             mode: round to an even integer or significand. */
     629                          mpfr_div_2ui (y, y, 1, MPFR_RNDZ);
     630                          if (!mpfr_integer_p (y))
     631                            err ("halfway case for mpfr_rint, result isn't "
     632                                 "an even integer", s, x, y, p,
     633                                 (mpfr_rnd_t) r, trint, inexact);
     634                          if (p > 1)
     635                            {
     636                              /* For p > 1, if floor(x) and ceil(x) aren't
     637                                 both representable integers, the significand
     638                                 must be even. */
     639                              mpfr_sub (v, v, y, MPFR_RNDN);
     640                              mpfr_abs (v, v, MPFR_RNDN);
     641                              if (mpfr_cmp_ui (v, 1) != 0)
     642                                {
     643                                  mpfr_div_2si (y, y, MPFR_EXP (y) -
     644                                                MPFR_PREC (y) + 1, MPFR_RNDN);
     645                                  if (!mpfr_integer_p (y))
     646                                    err ("halfway case for mpfr_rint, "
     647                                         "significand isn't even", s, x, y, p,
     648                                         (mpfr_rnd_t) r, trint, inexact);
     649                                }
     650                            }
     651                        }
     652                      else if (trint == 3)
     653                        { /* halfway case for mpfr_round: x must have been
     654                             rounded away from zero. */
     655                          if ((MPFR_IS_POS (x) && inexact < 0) ||
     656                              (MPFR_IS_NEG (x) && inexact > 0))
     657                            err ("halfway case for mpfr_round, "
     658                                 "bad rounding direction", s, x, y, p,
     659                                 (mpfr_rnd_t) r, trint, inexact);
     660                        }
     661                    }
     662                }
     663          }
     664      }
     665    mpfr_clear (x);
     666    mpfr_clear (y);
     667    mpz_clear (z);
     668    mpfr_clear (t);
     669    mpfr_clear (u);
     670    mpfr_clear (v);
     671  
     672    special ();
     673    basic_tests ();
     674    coverage_03032011 ();
     675  
     676    test_generic_trunc (MPFR_PREC_MIN, 300, 20);
     677    test_generic_floor (MPFR_PREC_MIN, 300, 20);
     678    test_generic_ceil (MPFR_PREC_MIN, 300, 20);
     679    test_generic_round (MPFR_PREC_MIN, 300, 20);
     680    test_generic_roundeven (MPFR_PREC_MIN, 300, 20);
     681  
     682  #if __MPFR_STDC (199901L)
     683    if (argc > 1 && strcmp (argv[1], "-s") == 0)
     684      test_against_libc ();
     685  #endif
     686  
     687    tests_end_mpfr ();
     688    return 0;
     689  }