Home | History | Annotate | Line # | Download | only in tests
tcan_round.c revision 1.1.1.3.4.1
      1      1.1.1.3       mrg /* Test file for mpfr_can_round and mpfr_round_p.
      2          1.1       mrg 
      3  1.1.1.3.4.1  christos Copyright 1999, 2001-2018 Free Software Foundation, Inc.
      4      1.1.1.3       mrg Contributed by the AriC and Caramba projects, INRIA.
      5          1.1       mrg 
      6          1.1       mrg This file is part of the GNU MPFR Library.
      7          1.1       mrg 
      8          1.1       mrg The GNU MPFR Library is free software; you can redistribute it and/or modify
      9          1.1       mrg it under the terms of the GNU Lesser General Public License as published by
     10          1.1       mrg the Free Software Foundation; either version 3 of the License, or (at your
     11          1.1       mrg option) any later version.
     12          1.1       mrg 
     13          1.1       mrg The GNU MPFR Library is distributed in the hope that it will be useful, but
     14          1.1       mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15          1.1       mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     16          1.1       mrg License for more details.
     17          1.1       mrg 
     18          1.1       mrg You should have received a copy of the GNU Lesser General Public License
     19          1.1       mrg along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
     20          1.1       mrg http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
     21          1.1       mrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
     22          1.1       mrg 
     23          1.1       mrg #include "mpfr-test.h"
     24          1.1       mrg 
     25      1.1.1.3       mrg /* Simple cases where err - prec is large enough.
     26      1.1.1.3       mrg    One can get failures as a consequence of r9883. */
     27      1.1.1.3       mrg static void
     28      1.1.1.3       mrg test_simple (void)
     29      1.1.1.3       mrg {
     30      1.1.1.3       mrg   int t[4] = { 2, 3, -2, -3 };  /* test powers of 2 and non-powers of 2 */
     31      1.1.1.3       mrg   int i;
     32      1.1.1.3       mrg   int r1, r2;
     33      1.1.1.3       mrg 
     34      1.1.1.3       mrg   for (i = 0; i < 4; i++)
     35      1.1.1.3       mrg     RND_LOOP (r1)
     36      1.1.1.3       mrg       RND_LOOP (r2)
     37      1.1.1.3       mrg         {
     38      1.1.1.3       mrg           mpfr_t b;
     39      1.1.1.3       mrg           int p, err, prec, inex, c;
     40      1.1.1.3       mrg 
     41  1.1.1.3.4.1  christos           if (r2 == MPFR_RNDF)
     42  1.1.1.3.4.1  christos             continue;
     43      1.1.1.3       mrg           p = 12 + (randlimb() % (2 * GMP_NUMB_BITS));
     44      1.1.1.3       mrg           err = p - 3;
     45      1.1.1.3       mrg           prec = 4;
     46      1.1.1.3       mrg           mpfr_init2 (b, p);
     47      1.1.1.3       mrg           inex = mpfr_set_si (b, t[i], MPFR_RNDN);
     48      1.1.1.3       mrg           MPFR_ASSERTN (inex == 0);
     49      1.1.1.3       mrg           c = mpfr_can_round (b, err, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, prec);
     50      1.1.1.3       mrg           /* If r1 == r2, we can round.
     51  1.1.1.3.4.1  christos              Note: For r1, RNDF is equivalent to RNDN.
     52      1.1.1.3       mrg              TODO: complete this test for r1 != r2. */
     53  1.1.1.3.4.1  christos           if ((r1 == MPFR_RNDF ? MPFR_RNDN : r1) == r2 && !c)
     54      1.1.1.3       mrg             {
     55      1.1.1.3       mrg               printf ("Error in test_simple for i=%d,"
     56      1.1.1.3       mrg                       " err=%d r1=%s, r2=%s, p=%d\n", i, err,
     57      1.1.1.3       mrg                       mpfr_print_rnd_mode ((mpfr_rnd_t) r1),
     58      1.1.1.3       mrg                       mpfr_print_rnd_mode ((mpfr_rnd_t) r2), p);
     59      1.1.1.3       mrg               printf ("b="); mpfr_dump (b);
     60      1.1.1.3       mrg               exit (1);
     61      1.1.1.3       mrg             }
     62      1.1.1.3       mrg           mpfr_clear (b);
     63      1.1.1.3       mrg         }
     64      1.1.1.3       mrg }
     65      1.1.1.3       mrg 
     66          1.1       mrg #define MAX_LIMB_SIZE 100
     67          1.1       mrg 
     68          1.1       mrg static void
     69          1.1       mrg check_round_p (void)
     70          1.1       mrg {
     71          1.1       mrg   mp_limb_t buf[MAX_LIMB_SIZE];
     72          1.1       mrg   mp_size_t n, i;
     73          1.1       mrg   mpfr_prec_t p;
     74          1.1       mrg   mpfr_exp_t err;
     75          1.1       mrg   int r1, r2;
     76          1.1       mrg 
     77          1.1       mrg   for (n = 2 ; n <= MAX_LIMB_SIZE ; n++)
     78          1.1       mrg     {
     79          1.1       mrg       /* avoid mpn_random which leaks memory */
     80          1.1       mrg       for (i = 0; i < n; i++)
     81          1.1       mrg         buf[i] = randlimb ();
     82      1.1.1.3       mrg       /* force the number to be normalized */
     83      1.1.1.3       mrg       buf[n - 1] |= MPFR_LIMB_HIGHBIT;
     84          1.1       mrg       p = randlimb() % ((n-1) * GMP_NUMB_BITS) + MPFR_PREC_MIN;
     85          1.1       mrg       err = p + randlimb () % GMP_NUMB_BITS;
     86          1.1       mrg       r1 = mpfr_round_p (buf, n, err, p);
     87          1.1       mrg       r2 = mpfr_can_round_raw (buf, n, MPFR_SIGN_POS, err,
     88          1.1       mrg                                MPFR_RNDN, MPFR_RNDZ, p);
     89          1.1       mrg       if (r1 != r2)
     90          1.1       mrg         {
     91          1.1       mrg           printf ("mpfr_round_p(%d) != mpfr_can_round(%d)!\n"
     92          1.1       mrg                   "bn = %ld, err0 = %ld, prec = %lu\nbp = ",
     93      1.1.1.2       mrg                   r1, r2, n, (long) err, (unsigned long) p);
     94  1.1.1.3.4.1  christos #ifndef MPFR_USE_MINI_GMP
     95          1.1       mrg           gmp_printf ("%NX\n", buf, n);
     96  1.1.1.3.4.1  christos #endif
     97          1.1       mrg           exit (1);
     98          1.1       mrg         }
     99          1.1       mrg     }
    100          1.1       mrg }
    101          1.1       mrg 
    102      1.1.1.3       mrg /* check x=2^i with precision px, error at most 1, and target precision prec */
    103      1.1.1.3       mrg static void
    104      1.1.1.3       mrg test_pow2 (mpfr_exp_t i, mpfr_prec_t px, mpfr_rnd_t r1, mpfr_rnd_t r2,
    105      1.1.1.3       mrg            mpfr_prec_t prec)
    106      1.1.1.3       mrg {
    107      1.1.1.3       mrg   mpfr_t x;
    108      1.1.1.3       mrg   int b, expected_b, b2;
    109      1.1.1.3       mrg 
    110      1.1.1.3       mrg   mpfr_init2 (x, px);
    111      1.1.1.3       mrg   mpfr_set_ui_2exp (x, 1, i, MPFR_RNDN);
    112  1.1.1.3.4.1  christos   /* for mpfr_can_round, r1=RNDF is equivalent to r1=RNDN (the sign of the
    113  1.1.1.3.4.1  christos      error is not known) */
    114      1.1.1.3       mrg   b = !!mpfr_can_round (x, i+1, r1, r2, prec);
    115      1.1.1.3       mrg   /* Note: If mpfr_can_round succeeds for both
    116      1.1.1.3       mrg      (r1,r2) = (MPFR_RNDD,MPFR_RNDN) and
    117      1.1.1.3       mrg      (r1,r2) = (MPFR_RNDU,MPFR_RNDN), then it should succeed for
    118      1.1.1.3       mrg      (r1,r2) = (MPFR_RNDN,MPFR_RNDN). So, the condition on prec below
    119      1.1.1.3       mrg      for r1 = MPFR_RNDN should be the most restrictive between those
    120      1.1.1.3       mrg      for r1 = any directed rounding mode.
    121      1.1.1.3       mrg      For r1 like MPFR_RNDA, the unrounded, unknown number may be anyone
    122      1.1.1.3       mrg      in [2^i-1,i]. As both 2^i-1 and 2^i fit on i bits, one cannot round
    123      1.1.1.3       mrg      in any precision >= i bits, hence the condition prec < i; prec = i-1
    124      1.1.1.3       mrg      will work here for r2 = MPFR_RNDN thanks to the even-rounding rule
    125      1.1.1.3       mrg      (and also with rounding ties away from zero). */
    126      1.1.1.3       mrg   expected_b =
    127      1.1.1.3       mrg     MPFR_IS_LIKE_RNDD (r1, MPFR_SIGN_POS) ?
    128      1.1.1.3       mrg     (MPFR_IS_LIKE_RNDU (r2, MPFR_SIGN_POS) ? 0 : prec <= i) :
    129      1.1.1.3       mrg     MPFR_IS_LIKE_RNDU (r1, MPFR_SIGN_POS) ?
    130      1.1.1.3       mrg     (MPFR_IS_LIKE_RNDD (r2, MPFR_SIGN_POS) ? 0 : prec < i) :
    131      1.1.1.3       mrg     (r2 != MPFR_RNDN ? 0 : prec < i);
    132      1.1.1.3       mrg   if (b != expected_b)
    133      1.1.1.3       mrg     {
    134      1.1.1.3       mrg       printf ("Error for x=2^%d, px=%lu, err=%d, r1=%s, r2=%s, prec=%d\n",
    135      1.1.1.3       mrg               (int) i, (unsigned long) px, (int) i + 1,
    136      1.1.1.3       mrg               mpfr_print_rnd_mode (r1), mpfr_print_rnd_mode (r2), (int) prec);
    137      1.1.1.3       mrg       printf ("Expected %d, got %d\n", expected_b, b);
    138      1.1.1.3       mrg       exit (1);
    139      1.1.1.3       mrg     }
    140      1.1.1.3       mrg 
    141      1.1.1.3       mrg   if (r1 == MPFR_RNDN && r2 == MPFR_RNDZ)
    142      1.1.1.3       mrg     {
    143      1.1.1.3       mrg       /* Similar test to the one done in src/round_p.c
    144      1.1.1.3       mrg          for MPFR_WANT_ASSERT >= 2. */
    145      1.1.1.3       mrg       b2 = !!mpfr_round_p (MPFR_MANT(x), MPFR_LIMB_SIZE(x), i+1, prec);
    146      1.1.1.3       mrg       if (b2 != b)
    147      1.1.1.3       mrg         {
    148      1.1.1.3       mrg           printf ("Error for x=2^%d, px=%lu, err=%d, prec=%d\n",
    149      1.1.1.3       mrg                   (int) i, (unsigned long) px, (int) i + 1, (int) prec);
    150      1.1.1.3       mrg           printf ("mpfr_can_round gave %d, mpfr_round_p gave %d\n", b, b2);
    151      1.1.1.3       mrg           exit (1);
    152      1.1.1.3       mrg         }
    153      1.1.1.3       mrg     }
    154      1.1.1.3       mrg 
    155      1.1.1.3       mrg   mpfr_clear (x);
    156      1.1.1.3       mrg }
    157      1.1.1.3       mrg 
    158      1.1.1.3       mrg static void
    159      1.1.1.3       mrg check_can_round (void)
    160      1.1.1.3       mrg {
    161      1.1.1.3       mrg   mpfr_t x, xinf, xsup, yinf, ysup;
    162      1.1.1.3       mrg   int precx, precy, err;
    163      1.1.1.3       mrg   int rnd1, rnd2;
    164      1.1.1.3       mrg   int i, u[3] = { 0, 1, 256 };
    165      1.1.1.3       mrg   int inex;
    166      1.1.1.3       mrg   int expected, got;
    167      1.1.1.3       mrg 
    168      1.1.1.3       mrg   mpfr_inits2 (4 * GMP_NUMB_BITS, x, xinf, xsup, yinf, ysup, (mpfr_ptr) 0);
    169      1.1.1.3       mrg 
    170      1.1.1.3       mrg   for (precx = 3 * GMP_NUMB_BITS - 3; precx <= 3 * GMP_NUMB_BITS + 3; precx++)
    171      1.1.1.3       mrg     {
    172      1.1.1.3       mrg       mpfr_set_prec (x, precx);
    173      1.1.1.3       mrg       for (precy = precx - 4; precy <= precx + 4; precy++)
    174      1.1.1.3       mrg         {
    175      1.1.1.3       mrg           mpfr_set_prec (yinf, precy);
    176      1.1.1.3       mrg           mpfr_set_prec (ysup, precy);
    177      1.1.1.3       mrg 
    178      1.1.1.3       mrg           for (i = 0; i <= 3; i++)
    179      1.1.1.3       mrg             {
    180      1.1.1.3       mrg               if (i <= 2)
    181      1.1.1.3       mrg                 {
    182      1.1.1.3       mrg                   /* Test x = 2^(precx - 1) + u */
    183      1.1.1.3       mrg                   mpfr_set_ui_2exp (x, 1, precx - 1, MPFR_RNDN);
    184      1.1.1.3       mrg                   mpfr_add_ui (x, x, u[i], MPFR_RNDN);
    185      1.1.1.3       mrg                 }
    186      1.1.1.3       mrg               else
    187      1.1.1.3       mrg                 {
    188      1.1.1.3       mrg                   /* Test x = 2^precx - 1 */
    189      1.1.1.3       mrg                   mpfr_set_ui_2exp (x, 1, precx, MPFR_RNDN);
    190      1.1.1.3       mrg                   mpfr_sub_ui (x, x, 1, MPFR_RNDN);
    191      1.1.1.3       mrg                 }
    192      1.1.1.3       mrg               MPFR_ASSERTN (mpfr_get_exp (x) == precx);
    193      1.1.1.3       mrg 
    194      1.1.1.3       mrg               for (err = precy; err <= precy + 3; err++)
    195      1.1.1.3       mrg                 {
    196      1.1.1.3       mrg                   mpfr_set_ui_2exp (xinf, 1, precx - err, MPFR_RNDN);
    197      1.1.1.3       mrg                   inex = mpfr_add (xsup, x, xinf, MPFR_RNDN);
    198      1.1.1.3       mrg                   MPFR_ASSERTN (inex == 0);
    199      1.1.1.3       mrg                   inex = mpfr_sub (xinf, x, xinf, MPFR_RNDN);
    200      1.1.1.3       mrg                   MPFR_ASSERTN (inex == 0);
    201      1.1.1.3       mrg                   RND_LOOP (rnd1)
    202      1.1.1.3       mrg                     RND_LOOP (rnd2)
    203      1.1.1.3       mrg                       {
    204  1.1.1.3.4.1  christos                         if (rnd2 == MPFR_RNDF)
    205  1.1.1.3.4.1  christos                           continue;
    206      1.1.1.3       mrg                         mpfr_set (yinf, MPFR_IS_LIKE_RNDD (rnd1, 1) ?
    207      1.1.1.3       mrg                                   x : xinf, (mpfr_rnd_t) rnd2);
    208      1.1.1.3       mrg                         mpfr_set (ysup, MPFR_IS_LIKE_RNDU (rnd1, 1) ?
    209      1.1.1.3       mrg                                   x : xsup, (mpfr_rnd_t) rnd2);
    210      1.1.1.3       mrg                         expected = !! mpfr_equal_p (yinf, ysup);
    211      1.1.1.3       mrg                         got = !! mpfr_can_round (x, err, (mpfr_rnd_t) rnd1,
    212      1.1.1.3       mrg                                                  (mpfr_rnd_t) rnd2, precy);
    213      1.1.1.3       mrg                         if (got != expected)
    214      1.1.1.3       mrg                           {
    215      1.1.1.3       mrg                             printf ("Error in check_can_round on:\n"
    216      1.1.1.3       mrg                                     "precx=%d, precy=%d, i=%d, err=%d, "
    217      1.1.1.3       mrg                                     "rnd1=%s, rnd2=%s: got %d\n",
    218      1.1.1.3       mrg                                     precx, precy, i, err,
    219      1.1.1.3       mrg                                     mpfr_print_rnd_mode ((mpfr_rnd_t) rnd1),
    220      1.1.1.3       mrg                                     mpfr_print_rnd_mode ((mpfr_rnd_t) rnd2),
    221      1.1.1.3       mrg                                     got);
    222      1.1.1.3       mrg                             printf ("x="); mpfr_dump (x);
    223      1.1.1.3       mrg                             exit (1);
    224      1.1.1.3       mrg                           }
    225      1.1.1.3       mrg                       }
    226      1.1.1.3       mrg                 }
    227      1.1.1.3       mrg             }
    228      1.1.1.3       mrg         }
    229      1.1.1.3       mrg     }
    230      1.1.1.3       mrg 
    231      1.1.1.3       mrg   mpfr_clears (x, xinf, xsup, yinf, ysup, (mpfr_ptr) 0);
    232      1.1.1.3       mrg }
    233      1.1.1.3       mrg 
    234          1.1       mrg int
    235          1.1       mrg main (void)
    236          1.1       mrg {
    237          1.1       mrg   mpfr_t x;
    238      1.1.1.3       mrg   mpfr_prec_t i, j, k;
    239      1.1.1.3       mrg   int r1, r2;
    240      1.1.1.3       mrg   int n;
    241          1.1       mrg 
    242          1.1       mrg   tests_start_mpfr ();
    243          1.1       mrg 
    244      1.1.1.3       mrg   test_simple ();
    245      1.1.1.3       mrg 
    246          1.1       mrg   /* checks that rounds to nearest sets the last
    247          1.1       mrg      bit to zero in case of equal distance */
    248          1.1       mrg   mpfr_init2 (x, 59);
    249          1.1       mrg   mpfr_set_str_binary (x, "-0.10010001010111000011110010111010111110000000111101100111111E663");
    250  1.1.1.3.4.1  christos   if (mpfr_can_round (x, 54, MPFR_RNDZ, MPFR_RNDZ, 53))
    251          1.1       mrg     {
    252          1.1       mrg       printf ("Error (1) in mpfr_can_round\n");
    253          1.1       mrg       exit (1);
    254          1.1       mrg     }
    255          1.1       mrg 
    256          1.1       mrg   mpfr_set_str_binary (x, "-Inf");
    257  1.1.1.3.4.1  christos   if (mpfr_can_round (x, 2000, MPFR_RNDZ, MPFR_RNDZ, 2000))
    258          1.1       mrg     {
    259          1.1       mrg       printf ("Error (2) in mpfr_can_round\n");
    260          1.1       mrg       exit (1);
    261          1.1       mrg     }
    262          1.1       mrg 
    263          1.1       mrg   mpfr_set_prec (x, 64);
    264          1.1       mrg   mpfr_set_str_binary (x, "0.1011001000011110000110000110001111101011000010001110011000000000");
    265          1.1       mrg   if (mpfr_can_round (x, 65, MPFR_RNDN, MPFR_RNDN, 54))
    266          1.1       mrg     {
    267          1.1       mrg       printf ("Error (3) in mpfr_can_round\n");
    268          1.1       mrg       exit (1);
    269          1.1       mrg     }
    270          1.1       mrg 
    271          1.1       mrg   mpfr_set_prec (x, 137);
    272          1.1       mrg   mpfr_set_str_binary (x, "-0.10111001101001010110011000110100111010011101101010010100101100001110000100111111011101010110001010111100100101110111100001000010000000000E-97");
    273  1.1.1.3.4.1  christos   if (! mpfr_can_round (x, 132, MPFR_RNDU, MPFR_RNDZ, 128))
    274          1.1       mrg     {
    275          1.1       mrg       printf ("Error (4) in mpfr_can_round\n");
    276          1.1       mrg       exit (1);
    277          1.1       mrg     }
    278          1.1       mrg 
    279          1.1       mrg   /* in the following, we can round but cannot determine the inexact flag */
    280          1.1       mrg   mpfr_set_prec (x, 86);
    281          1.1       mrg   mpfr_set_str_binary (x, "-0.11100100010011001111011010100111101010011000000000000000000000000000000000000000000000E-80");
    282  1.1.1.3.4.1  christos   if (! mpfr_can_round (x, 81, MPFR_RNDU, MPFR_RNDZ, 44))
    283          1.1       mrg     {
    284          1.1       mrg       printf ("Error (5) in mpfr_can_round\n");
    285          1.1       mrg       exit (1);
    286          1.1       mrg     }
    287          1.1       mrg 
    288          1.1       mrg   mpfr_set_prec (x, 62);
    289          1.1       mrg   mpfr_set_str (x, "0.ff4ca619c76ba69", 16, MPFR_RNDZ);
    290          1.1       mrg   for (i = 30; i < 99; i++)
    291          1.1       mrg     for (j = 30; j < 99; j++)
    292  1.1.1.3.4.1  christos       RND_LOOP (r1)
    293  1.1.1.3.4.1  christos         RND_LOOP (r2)
    294  1.1.1.3.4.1  christos           if (r2 != MPFR_RNDF)
    295  1.1.1.3.4.1  christos             {
    296  1.1.1.3.4.1  christos               /* test for assertions */
    297  1.1.1.3.4.1  christos               mpfr_can_round (x, i, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, j);
    298  1.1.1.3.4.1  christos             }
    299      1.1.1.3       mrg 
    300      1.1.1.3       mrg   test_pow2 (32, 32, MPFR_RNDN, MPFR_RNDN, 32);
    301      1.1.1.3       mrg   test_pow2 (174, 174, MPFR_RNDN, MPFR_RNDN, 174);
    302      1.1.1.3       mrg   test_pow2 (174, 174, MPFR_RNDU, MPFR_RNDN, 174);
    303      1.1.1.3       mrg   test_pow2 (176, 129, MPFR_RNDU, MPFR_RNDU, 174);
    304      1.1.1.3       mrg   test_pow2 (176, 2, MPFR_RNDZ, MPFR_RNDZ, 174);
    305      1.1.1.3       mrg   test_pow2 (176, 2, MPFR_RNDU, MPFR_RNDU, 176);
    306      1.1.1.3       mrg 
    307      1.1.1.3       mrg   /* Tests for x = 2^i (E(x) = i+1) with error at most 1 = 2^0. */
    308      1.1.1.3       mrg   for (n = 0; n < 100; n++)
    309      1.1.1.3       mrg     {
    310      1.1.1.3       mrg       i = (randlimb() % 200) + 4;
    311      1.1.1.3       mrg       for (j = i - 2; j < i + 2; j++)
    312  1.1.1.3.4.1  christos         RND_LOOP (r1)
    313  1.1.1.3.4.1  christos           RND_LOOP (r2)
    314  1.1.1.3.4.1  christos             if (r2 != MPFR_RNDF)
    315  1.1.1.3.4.1  christos               for (k = MPFR_PREC_MIN; k <= i + 2; k++)
    316  1.1.1.3.4.1  christos                 test_pow2 (i, k, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, j);
    317      1.1.1.3       mrg     }
    318          1.1       mrg 
    319          1.1       mrg   mpfr_clear (x);
    320          1.1       mrg 
    321      1.1.1.3       mrg   check_can_round ();
    322      1.1.1.3       mrg 
    323          1.1       mrg   check_round_p ();
    324          1.1       mrg 
    325          1.1       mrg   tests_end_mpfr ();
    326          1.1       mrg   return 0;
    327          1.1       mrg }
    328