Home | History | Annotate | Line # | Download | only in tests
tcan_round.c revision 1.1.1.3
      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  mrg Copyright 1999, 2001-2016 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 <stdio.h>
     24      1.1  mrg #include <stdlib.h>
     25      1.1  mrg 
     26      1.1  mrg #include "mpfr-test.h"
     27      1.1  mrg 
     28  1.1.1.3  mrg /* Simple cases where err - prec is large enough.
     29  1.1.1.3  mrg    One can get failures as a consequence of r9883. */
     30  1.1.1.3  mrg static void
     31  1.1.1.3  mrg test_simple (void)
     32  1.1.1.3  mrg {
     33  1.1.1.3  mrg   int t[4] = { 2, 3, -2, -3 };  /* test powers of 2 and non-powers of 2 */
     34  1.1.1.3  mrg   int i;
     35  1.1.1.3  mrg   int r1, r2;
     36  1.1.1.3  mrg 
     37  1.1.1.3  mrg   for (i = 0; i < 4; i++)
     38  1.1.1.3  mrg     RND_LOOP (r1)
     39  1.1.1.3  mrg       RND_LOOP (r2)
     40  1.1.1.3  mrg         {
     41  1.1.1.3  mrg           mpfr_t b;
     42  1.1.1.3  mrg           int p, err, prec, inex, c;
     43  1.1.1.3  mrg 
     44  1.1.1.3  mrg           p = 12 + (randlimb() % (2 * GMP_NUMB_BITS));
     45  1.1.1.3  mrg           err = p - 3;
     46  1.1.1.3  mrg           prec = 4;
     47  1.1.1.3  mrg           mpfr_init2 (b, p);
     48  1.1.1.3  mrg           inex = mpfr_set_si (b, t[i], MPFR_RNDN);
     49  1.1.1.3  mrg           MPFR_ASSERTN (inex == 0);
     50  1.1.1.3  mrg           c = mpfr_can_round (b, err, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, prec);
     51  1.1.1.3  mrg           /* If r1 == r2, we can round.
     52  1.1.1.3  mrg              TODO: complete this test for r1 != r2. */
     53  1.1.1.3  mrg           if (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  mrg           gmp_printf ("%NX\n", buf, n);
     95      1.1  mrg           exit (1);
     96      1.1  mrg         }
     97      1.1  mrg     }
     98      1.1  mrg }
     99      1.1  mrg 
    100  1.1.1.3  mrg /* check x=2^i with precision px, error at most 1, and target precision prec */
    101  1.1.1.3  mrg static void
    102  1.1.1.3  mrg test_pow2 (mpfr_exp_t i, mpfr_prec_t px, mpfr_rnd_t r1, mpfr_rnd_t r2,
    103  1.1.1.3  mrg            mpfr_prec_t prec)
    104  1.1.1.3  mrg {
    105  1.1.1.3  mrg   mpfr_t x;
    106  1.1.1.3  mrg   int b, expected_b, b2;
    107  1.1.1.3  mrg 
    108  1.1.1.3  mrg   mpfr_init2 (x, px);
    109  1.1.1.3  mrg   mpfr_set_ui_2exp (x, 1, i, MPFR_RNDN);
    110  1.1.1.3  mrg   b = !!mpfr_can_round (x, i+1, r1, r2, prec);
    111  1.1.1.3  mrg   /* Note: If mpfr_can_round succeeds for both
    112  1.1.1.3  mrg      (r1,r2) = (MPFR_RNDD,MPFR_RNDN) and
    113  1.1.1.3  mrg      (r1,r2) = (MPFR_RNDU,MPFR_RNDN), then it should succeed for
    114  1.1.1.3  mrg      (r1,r2) = (MPFR_RNDN,MPFR_RNDN). So, the condition on prec below
    115  1.1.1.3  mrg      for r1 = MPFR_RNDN should be the most restrictive between those
    116  1.1.1.3  mrg      for r1 = any directed rounding mode.
    117  1.1.1.3  mrg      For r1 like MPFR_RNDA, the unrounded, unknown number may be anyone
    118  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
    119  1.1.1.3  mrg      in any precision >= i bits, hence the condition prec < i; prec = i-1
    120  1.1.1.3  mrg      will work here for r2 = MPFR_RNDN thanks to the even-rounding rule
    121  1.1.1.3  mrg      (and also with rounding ties away from zero). */
    122  1.1.1.3  mrg   expected_b =
    123  1.1.1.3  mrg     MPFR_IS_LIKE_RNDD (r1, MPFR_SIGN_POS) ?
    124  1.1.1.3  mrg     (MPFR_IS_LIKE_RNDU (r2, MPFR_SIGN_POS) ? 0 : prec <= i) :
    125  1.1.1.3  mrg     MPFR_IS_LIKE_RNDU (r1, MPFR_SIGN_POS) ?
    126  1.1.1.3  mrg     (MPFR_IS_LIKE_RNDD (r2, MPFR_SIGN_POS) ? 0 : prec < i) :
    127  1.1.1.3  mrg     (r2 != MPFR_RNDN ? 0 : prec < i);
    128  1.1.1.3  mrg   if (b != expected_b)
    129  1.1.1.3  mrg     {
    130  1.1.1.3  mrg       printf ("Error for x=2^%d, px=%lu, err=%d, r1=%s, r2=%s, prec=%d\n",
    131  1.1.1.3  mrg               (int) i, (unsigned long) px, (int) i + 1,
    132  1.1.1.3  mrg               mpfr_print_rnd_mode (r1), mpfr_print_rnd_mode (r2), (int) prec);
    133  1.1.1.3  mrg       printf ("Expected %d, got %d\n", expected_b, b);
    134  1.1.1.3  mrg       exit (1);
    135  1.1.1.3  mrg     }
    136  1.1.1.3  mrg 
    137  1.1.1.3  mrg   if (r1 == MPFR_RNDN && r2 == MPFR_RNDZ)
    138  1.1.1.3  mrg     {
    139  1.1.1.3  mrg       /* Similar test to the one done in src/round_p.c
    140  1.1.1.3  mrg          for MPFR_WANT_ASSERT >= 2. */
    141  1.1.1.3  mrg       b2 = !!mpfr_round_p (MPFR_MANT(x), MPFR_LIMB_SIZE(x), i+1, prec);
    142  1.1.1.3  mrg       if (b2 != b)
    143  1.1.1.3  mrg         {
    144  1.1.1.3  mrg           printf ("Error for x=2^%d, px=%lu, err=%d, prec=%d\n",
    145  1.1.1.3  mrg                   (int) i, (unsigned long) px, (int) i + 1, (int) prec);
    146  1.1.1.3  mrg           printf ("mpfr_can_round gave %d, mpfr_round_p gave %d\n", b, b2);
    147  1.1.1.3  mrg           exit (1);
    148  1.1.1.3  mrg         }
    149  1.1.1.3  mrg     }
    150  1.1.1.3  mrg 
    151  1.1.1.3  mrg   mpfr_clear (x);
    152  1.1.1.3  mrg }
    153  1.1.1.3  mrg 
    154  1.1.1.3  mrg static void
    155  1.1.1.3  mrg check_can_round (void)
    156  1.1.1.3  mrg {
    157  1.1.1.3  mrg   mpfr_t x, xinf, xsup, yinf, ysup;
    158  1.1.1.3  mrg   int precx, precy, err;
    159  1.1.1.3  mrg   int rnd1, rnd2;
    160  1.1.1.3  mrg   int i, u[3] = { 0, 1, 256 };
    161  1.1.1.3  mrg   int inex;
    162  1.1.1.3  mrg   int expected, got;
    163  1.1.1.3  mrg 
    164  1.1.1.3  mrg   mpfr_inits2 (4 * GMP_NUMB_BITS, x, xinf, xsup, yinf, ysup, (mpfr_ptr) 0);
    165  1.1.1.3  mrg 
    166  1.1.1.3  mrg   for (precx = 3 * GMP_NUMB_BITS - 3; precx <= 3 * GMP_NUMB_BITS + 3; precx++)
    167  1.1.1.3  mrg     {
    168  1.1.1.3  mrg       mpfr_set_prec (x, precx);
    169  1.1.1.3  mrg       for (precy = precx - 4; precy <= precx + 4; precy++)
    170  1.1.1.3  mrg         {
    171  1.1.1.3  mrg           mpfr_set_prec (yinf, precy);
    172  1.1.1.3  mrg           mpfr_set_prec (ysup, precy);
    173  1.1.1.3  mrg 
    174  1.1.1.3  mrg           for (i = 0; i <= 3; i++)
    175  1.1.1.3  mrg             {
    176  1.1.1.3  mrg               if (i <= 2)
    177  1.1.1.3  mrg                 {
    178  1.1.1.3  mrg                   /* Test x = 2^(precx - 1) + u */
    179  1.1.1.3  mrg                   mpfr_set_ui_2exp (x, 1, precx - 1, MPFR_RNDN);
    180  1.1.1.3  mrg                   mpfr_add_ui (x, x, u[i], MPFR_RNDN);
    181  1.1.1.3  mrg                 }
    182  1.1.1.3  mrg               else
    183  1.1.1.3  mrg                 {
    184  1.1.1.3  mrg                   /* Test x = 2^precx - 1 */
    185  1.1.1.3  mrg                   mpfr_set_ui_2exp (x, 1, precx, MPFR_RNDN);
    186  1.1.1.3  mrg                   mpfr_sub_ui (x, x, 1, MPFR_RNDN);
    187  1.1.1.3  mrg                 }
    188  1.1.1.3  mrg               MPFR_ASSERTN (mpfr_get_exp (x) == precx);
    189  1.1.1.3  mrg 
    190  1.1.1.3  mrg               for (err = precy; err <= precy + 3; err++)
    191  1.1.1.3  mrg                 {
    192  1.1.1.3  mrg                   mpfr_set_ui_2exp (xinf, 1, precx - err, MPFR_RNDN);
    193  1.1.1.3  mrg                   inex = mpfr_add (xsup, x, xinf, MPFR_RNDN);
    194  1.1.1.3  mrg                   MPFR_ASSERTN (inex == 0);
    195  1.1.1.3  mrg                   inex = mpfr_sub (xinf, x, xinf, MPFR_RNDN);
    196  1.1.1.3  mrg                   MPFR_ASSERTN (inex == 0);
    197  1.1.1.3  mrg                   RND_LOOP (rnd1)
    198  1.1.1.3  mrg                     RND_LOOP (rnd2)
    199  1.1.1.3  mrg                       {
    200  1.1.1.3  mrg                         mpfr_set (yinf, MPFR_IS_LIKE_RNDD (rnd1, 1) ?
    201  1.1.1.3  mrg                                   x : xinf, (mpfr_rnd_t) rnd2);
    202  1.1.1.3  mrg                         mpfr_set (ysup, MPFR_IS_LIKE_RNDU (rnd1, 1) ?
    203  1.1.1.3  mrg                                   x : xsup, (mpfr_rnd_t) rnd2);
    204  1.1.1.3  mrg                         expected = !! mpfr_equal_p (yinf, ysup);
    205  1.1.1.3  mrg                         got = !! mpfr_can_round (x, err, (mpfr_rnd_t) rnd1,
    206  1.1.1.3  mrg                                                  (mpfr_rnd_t) rnd2, precy);
    207  1.1.1.3  mrg                         if (got != expected)
    208  1.1.1.3  mrg                           {
    209  1.1.1.3  mrg                             printf ("Error in check_can_round on:\n"
    210  1.1.1.3  mrg                                     "precx=%d, precy=%d, i=%d, err=%d, "
    211  1.1.1.3  mrg                                     "rnd1=%s, rnd2=%s: got %d\n",
    212  1.1.1.3  mrg                                     precx, precy, i, err,
    213  1.1.1.3  mrg                                     mpfr_print_rnd_mode ((mpfr_rnd_t) rnd1),
    214  1.1.1.3  mrg                                     mpfr_print_rnd_mode ((mpfr_rnd_t) rnd2),
    215  1.1.1.3  mrg                                     got);
    216  1.1.1.3  mrg                             printf ("x="); mpfr_dump (x);
    217  1.1.1.3  mrg                             exit (1);
    218  1.1.1.3  mrg                           }
    219  1.1.1.3  mrg                       }
    220  1.1.1.3  mrg                 }
    221  1.1.1.3  mrg             }
    222  1.1.1.3  mrg         }
    223  1.1.1.3  mrg     }
    224  1.1.1.3  mrg 
    225  1.1.1.3  mrg   mpfr_clears (x, xinf, xsup, yinf, ysup, (mpfr_ptr) 0);
    226  1.1.1.3  mrg }
    227  1.1.1.3  mrg 
    228      1.1  mrg int
    229      1.1  mrg main (void)
    230      1.1  mrg {
    231      1.1  mrg   mpfr_t x;
    232  1.1.1.3  mrg   mpfr_prec_t i, j, k;
    233  1.1.1.3  mrg   int r1, r2;
    234  1.1.1.3  mrg   int n;
    235      1.1  mrg 
    236      1.1  mrg   tests_start_mpfr ();
    237      1.1  mrg 
    238  1.1.1.3  mrg   test_simple ();
    239  1.1.1.3  mrg 
    240      1.1  mrg   /* checks that rounds to nearest sets the last
    241      1.1  mrg      bit to zero in case of equal distance */
    242      1.1  mrg   mpfr_init2 (x, 59);
    243      1.1  mrg   mpfr_set_str_binary (x, "-0.10010001010111000011110010111010111110000000111101100111111E663");
    244      1.1  mrg   if (mpfr_can_round (x, 54, MPFR_RNDZ, MPFR_RNDZ, 53) != 0)
    245      1.1  mrg     {
    246      1.1  mrg       printf ("Error (1) in mpfr_can_round\n");
    247      1.1  mrg       exit (1);
    248      1.1  mrg     }
    249      1.1  mrg 
    250      1.1  mrg   mpfr_set_str_binary (x, "-Inf");
    251      1.1  mrg   if (mpfr_can_round (x, 2000, MPFR_RNDZ, MPFR_RNDZ, 2000) != 0)
    252      1.1  mrg     {
    253      1.1  mrg       printf ("Error (2) in mpfr_can_round\n");
    254      1.1  mrg       exit (1);
    255      1.1  mrg     }
    256      1.1  mrg 
    257      1.1  mrg   mpfr_set_prec (x, 64);
    258      1.1  mrg   mpfr_set_str_binary (x, "0.1011001000011110000110000110001111101011000010001110011000000000");
    259      1.1  mrg   if (mpfr_can_round (x, 65, MPFR_RNDN, MPFR_RNDN, 54))
    260      1.1  mrg     {
    261      1.1  mrg       printf ("Error (3) in mpfr_can_round\n");
    262      1.1  mrg       exit (1);
    263      1.1  mrg     }
    264      1.1  mrg 
    265      1.1  mrg   mpfr_set_prec (x, 137);
    266      1.1  mrg   mpfr_set_str_binary (x, "-0.10111001101001010110011000110100111010011101101010010100101100001110000100111111011101010110001010111100100101110111100001000010000000000E-97");
    267      1.1  mrg   if (mpfr_can_round (x, 132, MPFR_RNDU, MPFR_RNDZ, 128) == 0)
    268      1.1  mrg     {
    269      1.1  mrg       printf ("Error (4) in mpfr_can_round\n");
    270      1.1  mrg       exit (1);
    271      1.1  mrg     }
    272      1.1  mrg 
    273      1.1  mrg   /* in the following, we can round but cannot determine the inexact flag */
    274      1.1  mrg   mpfr_set_prec (x, 86);
    275      1.1  mrg   mpfr_set_str_binary (x, "-0.11100100010011001111011010100111101010011000000000000000000000000000000000000000000000E-80");
    276      1.1  mrg   if (mpfr_can_round (x, 81, MPFR_RNDU, MPFR_RNDZ, 44) == 0)
    277      1.1  mrg     {
    278      1.1  mrg       printf ("Error (5) in mpfr_can_round\n");
    279      1.1  mrg       exit (1);
    280      1.1  mrg     }
    281      1.1  mrg 
    282      1.1  mrg   mpfr_set_prec (x, 62);
    283      1.1  mrg   mpfr_set_str (x, "0.ff4ca619c76ba69", 16, MPFR_RNDZ);
    284      1.1  mrg   for (i = 30; i < 99; i++)
    285      1.1  mrg     for (j = 30; j < 99; j++)
    286  1.1.1.3  mrg       for (r1 = 0; r1 < MPFR_RND_MAX; r1++)
    287  1.1.1.3  mrg         for (r2 = 0; r2 < MPFR_RND_MAX; r2++)
    288  1.1.1.3  mrg           {
    289  1.1.1.3  mrg             /* test for assertions */
    290  1.1.1.3  mrg             mpfr_can_round (x, i, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, j);
    291  1.1.1.3  mrg           }
    292  1.1.1.3  mrg 
    293  1.1.1.3  mrg   test_pow2 (32, 32, MPFR_RNDN, MPFR_RNDN, 32);
    294  1.1.1.3  mrg   test_pow2 (174, 174, MPFR_RNDN, MPFR_RNDN, 174);
    295  1.1.1.3  mrg   test_pow2 (174, 174, MPFR_RNDU, MPFR_RNDN, 174);
    296  1.1.1.3  mrg   test_pow2 (176, 129, MPFR_RNDU, MPFR_RNDU, 174);
    297  1.1.1.3  mrg   test_pow2 (176, 2, MPFR_RNDZ, MPFR_RNDZ, 174);
    298  1.1.1.3  mrg   test_pow2 (176, 2, MPFR_RNDU, MPFR_RNDU, 176);
    299  1.1.1.3  mrg 
    300  1.1.1.3  mrg   /* Tests for x = 2^i (E(x) = i+1) with error at most 1 = 2^0. */
    301  1.1.1.3  mrg   for (n = 0; n < 100; n++)
    302  1.1.1.3  mrg     {
    303  1.1.1.3  mrg       i = (randlimb() % 200) + 4;
    304  1.1.1.3  mrg       for (j = i - 2; j < i + 2; j++)
    305  1.1.1.3  mrg         for (r1 = 0; r1 < MPFR_RND_MAX; r1++)
    306  1.1.1.3  mrg           for (r2 = 0; r2 < MPFR_RND_MAX; r2++)
    307  1.1.1.3  mrg             for (k = MPFR_PREC_MIN; k <= i + 2; k++)
    308  1.1.1.3  mrg               test_pow2 (i, k, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, j);
    309  1.1.1.3  mrg     }
    310      1.1  mrg 
    311      1.1  mrg   mpfr_clear (x);
    312      1.1  mrg 
    313  1.1.1.3  mrg   check_can_round ();
    314  1.1.1.3  mrg 
    315      1.1  mrg   check_round_p ();
    316      1.1  mrg 
    317      1.1  mrg   tests_end_mpfr ();
    318      1.1  mrg   return 0;
    319      1.1  mrg }
    320