Home | History | Annotate | Line # | Download | only in tests
      1      1.1  mrg /* Test file for mpfr_ui_sub.
      2      1.1  mrg 
      3  1.1.1.6  mrg Copyright 2000-2023 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.1.5  mrg https://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 <float.h>
     24      1.1  mrg 
     25      1.1  mrg #include "mpfr-test.h"
     26      1.1  mrg 
     27      1.1  mrg static void
     28      1.1  mrg special (void)
     29      1.1  mrg {
     30      1.1  mrg   mpfr_t x, y, res;
     31      1.1  mrg   int inexact;
     32      1.1  mrg 
     33      1.1  mrg   mpfr_init (x);
     34      1.1  mrg   mpfr_init (y);
     35      1.1  mrg   mpfr_init (res);
     36      1.1  mrg 
     37      1.1  mrg   mpfr_set_prec (x, 24);
     38      1.1  mrg   mpfr_set_prec (y, 24);
     39      1.1  mrg   mpfr_set_str_binary (y, "0.111100110001011010111");
     40      1.1  mrg   inexact = mpfr_ui_sub (x, 1, y, MPFR_RNDN);
     41      1.1  mrg   if (inexact)
     42      1.1  mrg     {
     43      1.1  mrg       printf ("Wrong inexact flag: got %d, expected 0\n", inexact);
     44      1.1  mrg       exit (1);
     45      1.1  mrg     }
     46      1.1  mrg 
     47      1.1  mrg   mpfr_set_prec (x, 24);
     48      1.1  mrg   mpfr_set_prec (y, 24);
     49      1.1  mrg   mpfr_set_str_binary (y, "0.111100110001011010111");
     50      1.1  mrg   if ((inexact = mpfr_ui_sub (x, 38181761, y, MPFR_RNDN)) >= 0)
     51      1.1  mrg     {
     52      1.1  mrg       printf ("Wrong inexact flag: got %d, expected -1\n", inexact);
     53      1.1  mrg       exit (1);
     54      1.1  mrg     }
     55      1.1  mrg 
     56      1.1  mrg   mpfr_set_prec (x, 63);
     57      1.1  mrg   mpfr_set_prec (y, 63);
     58      1.1  mrg   mpfr_set_str_binary (y, "0.111110010010100100110101101010001001100101110001000101110111111E-1");
     59      1.1  mrg   if ((inexact = mpfr_ui_sub (x, 1541116494, y, MPFR_RNDN)) <= 0)
     60      1.1  mrg     {
     61      1.1  mrg       printf ("Wrong inexact flag: got %d, expected +1\n", inexact);
     62      1.1  mrg       exit (1);
     63      1.1  mrg     }
     64      1.1  mrg 
     65      1.1  mrg   mpfr_set_prec (x, 32);
     66      1.1  mrg   mpfr_set_prec (y, 32);
     67      1.1  mrg   mpfr_set_str_binary (y, "0.11011000110111010001011100011100E-1");
     68      1.1  mrg   if ((inexact = mpfr_ui_sub (x, 2000375416, y, MPFR_RNDN)) >= 0)
     69      1.1  mrg     {
     70      1.1  mrg       printf ("Wrong inexact flag: got %d, expected -1\n", inexact);
     71      1.1  mrg       exit (1);
     72      1.1  mrg     }
     73      1.1  mrg 
     74      1.1  mrg   mpfr_set_prec (x, 24);
     75      1.1  mrg   mpfr_set_prec (y, 24);
     76      1.1  mrg   mpfr_set_str_binary (y, "0.110011011001010011110111E-2");
     77      1.1  mrg   if ((inexact = mpfr_ui_sub (x, 927694848, y, MPFR_RNDN)) <= 0)
     78      1.1  mrg     {
     79      1.1  mrg       printf ("Wrong inexact flag: got %d, expected +1\n", inexact);
     80      1.1  mrg       exit (1);
     81      1.1  mrg     }
     82      1.1  mrg 
     83      1.1  mrg   /* bug found by Mathieu Dutour, 12 Apr 2001 */
     84      1.1  mrg   mpfr_set_prec (x, 5);
     85      1.1  mrg   mpfr_set_prec (y, 5);
     86      1.1  mrg   mpfr_set_prec (res, 5);
     87      1.1  mrg   mpfr_set_str_binary (x, "1e-12");
     88      1.1  mrg 
     89      1.1  mrg   mpfr_ui_sub (y, 1, x, MPFR_RNDD);
     90      1.1  mrg   mpfr_set_str_binary (res, "0.11111");
     91      1.1  mrg   if (mpfr_cmp (y, res))
     92      1.1  mrg     {
     93      1.1  mrg       printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDD) for x=2^(-12)\nexpected 1.1111e-1, got ");
     94      1.1  mrg       mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
     95      1.1  mrg       printf ("\n");
     96      1.1  mrg       exit (1);
     97      1.1  mrg     }
     98      1.1  mrg 
     99      1.1  mrg   mpfr_ui_sub (y, 1, x, MPFR_RNDU);
    100      1.1  mrg   mpfr_set_str_binary (res, "1.0");
    101      1.1  mrg   if (mpfr_cmp (y, res))
    102      1.1  mrg     {
    103      1.1  mrg       printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDU) for x=2^(-12)\n"
    104      1.1  mrg               "expected 1.0, got ");
    105      1.1  mrg       mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
    106      1.1  mrg       printf ("\n");
    107      1.1  mrg       exit (1);
    108      1.1  mrg     }
    109      1.1  mrg 
    110      1.1  mrg   mpfr_ui_sub (y, 1, x, MPFR_RNDN);
    111      1.1  mrg   mpfr_set_str_binary (res, "1.0");
    112      1.1  mrg   if (mpfr_cmp (y, res))
    113      1.1  mrg     {
    114      1.1  mrg       printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDN) for x=2^(-12)\n"
    115      1.1  mrg               "expected 1.0, got ");
    116      1.1  mrg       mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
    117      1.1  mrg       printf ("\n");
    118      1.1  mrg       exit (1);
    119      1.1  mrg     }
    120      1.1  mrg 
    121      1.1  mrg   mpfr_set_prec (x, 10);
    122      1.1  mrg   mpfr_set_prec (y, 10);
    123      1.1  mrg   mpfr_urandomb (x, RANDS);
    124      1.1  mrg   mpfr_ui_sub (y, 0, x, MPFR_RNDN);
    125      1.1  mrg   if (MPFR_IS_ZERO(x))
    126      1.1  mrg     MPFR_ASSERTN(MPFR_IS_ZERO(y));
    127      1.1  mrg   else
    128      1.1  mrg     MPFR_ASSERTN(mpfr_cmpabs (x, y) == 0 && mpfr_sgn (x) != mpfr_sgn (y));
    129      1.1  mrg 
    130      1.1  mrg   mpfr_set_prec (x, 73);
    131      1.1  mrg   mpfr_set_str_binary (x, "0.1101111010101011011011100011010000000101110001011111001011011000101111101E-99");
    132      1.1  mrg   mpfr_ui_sub (x, 1, x, MPFR_RNDZ);
    133      1.1  mrg   mpfr_nextabove (x);
    134      1.1  mrg   MPFR_ASSERTN(mpfr_cmp_ui (x, 1) == 0);
    135      1.1  mrg 
    136      1.1  mrg   mpfr_clear (x);
    137      1.1  mrg   mpfr_clear (y);
    138      1.1  mrg   mpfr_clear (res);
    139      1.1  mrg }
    140      1.1  mrg 
    141      1.1  mrg /* checks that (y-x) gives the right results with 53 bits of precision */
    142      1.1  mrg static void
    143      1.1  mrg check (unsigned long y, const char *xs, mpfr_rnd_t rnd_mode, const char *zs)
    144      1.1  mrg {
    145      1.1  mrg   mpfr_t xx, zz;
    146      1.1  mrg 
    147      1.1  mrg   mpfr_inits2 (53, xx, zz, (mpfr_ptr) 0);
    148      1.1  mrg   mpfr_set_str1 (xx, xs);
    149      1.1  mrg   mpfr_ui_sub (zz, y, xx, rnd_mode);
    150      1.1  mrg   if (mpfr_cmp_str1 (zz, zs) )
    151      1.1  mrg     {
    152      1.1  mrg       printf ("expected difference is %s, got\n",zs);
    153      1.1  mrg       mpfr_out_str(stdout, 10, 0, zz, MPFR_RNDN);
    154      1.1  mrg       printf ("mpfr_ui_sub failed for y=%lu x=%s with rnd_mode=%s\n",
    155      1.1  mrg               y, xs, mpfr_print_rnd_mode (rnd_mode));
    156      1.1  mrg       exit (1);
    157      1.1  mrg     }
    158      1.1  mrg   mpfr_clears (xx, zz, (mpfr_ptr) 0);
    159      1.1  mrg }
    160      1.1  mrg 
    161      1.1  mrg /* if u = o(x-y), v = o(u-x), w = o(v+y), then x-y = u-w */
    162      1.1  mrg static void
    163      1.1  mrg check_two_sum (mpfr_prec_t p)
    164      1.1  mrg {
    165      1.1  mrg   unsigned int x;
    166      1.1  mrg   mpfr_t y, u, v, w;
    167      1.1  mrg   mpfr_rnd_t rnd;
    168  1.1.1.3  mrg   int inexact, cmp;
    169      1.1  mrg 
    170      1.1  mrg   mpfr_inits2 (p, y, u, v, w, (mpfr_ptr) 0);
    171      1.1  mrg   do
    172      1.1  mrg     {
    173      1.1  mrg       x = randlimb ();
    174      1.1  mrg     }
    175      1.1  mrg   while (x < 1);
    176      1.1  mrg   mpfr_urandomb (y, RANDS);
    177      1.1  mrg   rnd = MPFR_RNDN;
    178      1.1  mrg   inexact = mpfr_ui_sub (u, x, y, rnd);
    179      1.1  mrg   mpfr_sub_ui (v, u, x, rnd);
    180      1.1  mrg   mpfr_add (w, v, y, rnd);
    181  1.1.1.3  mrg   cmp = mpfr_cmp_ui (w, 0);
    182      1.1  mrg   /* as u = (x-y) + w, we should have inexact and w of same sign */
    183  1.1.1.3  mrg   if (! SAME_SIGN (inexact, cmp))
    184      1.1  mrg     {
    185      1.1  mrg       printf ("Wrong inexact flag for prec=%u, rnd=%s\n",
    186      1.1  mrg               (unsigned int) p, mpfr_print_rnd_mode (rnd));
    187  1.1.1.3  mrg       printf ("x = %u\n", x);
    188  1.1.1.3  mrg       printf ("y = "); mpfr_dump (y);
    189  1.1.1.3  mrg       printf ("u = "); mpfr_dump (u);
    190  1.1.1.3  mrg       printf ("v = "); mpfr_dump (v);
    191  1.1.1.3  mrg       printf ("w = "); mpfr_dump (w);
    192      1.1  mrg       printf ("inexact = %d\n", inexact);
    193      1.1  mrg       exit (1);
    194      1.1  mrg     }
    195      1.1  mrg   mpfr_clears (y, u, v, w, (mpfr_ptr) 0);
    196      1.1  mrg }
    197      1.1  mrg 
    198      1.1  mrg static void
    199      1.1  mrg check_nans (void)
    200      1.1  mrg {
    201      1.1  mrg   mpfr_t  x, y;
    202      1.1  mrg 
    203      1.1  mrg   mpfr_init2 (x, 123L);
    204      1.1  mrg   mpfr_init2 (y, 123L);
    205      1.1  mrg 
    206      1.1  mrg   /* 1 - nan == nan */
    207      1.1  mrg   mpfr_set_nan (x);
    208      1.1  mrg   mpfr_ui_sub (y, 1L, x, MPFR_RNDN);
    209      1.1  mrg   MPFR_ASSERTN (mpfr_nan_p (y));
    210      1.1  mrg 
    211      1.1  mrg   /* 1 - +inf == -inf */
    212      1.1  mrg   mpfr_set_inf (x, 1);
    213      1.1  mrg   mpfr_ui_sub (y, 1L, x, MPFR_RNDN);
    214      1.1  mrg   MPFR_ASSERTN (mpfr_inf_p (y));
    215      1.1  mrg   MPFR_ASSERTN (mpfr_sgn (y) < 0);
    216      1.1  mrg 
    217      1.1  mrg   /* 1 - -inf == +inf */
    218      1.1  mrg   mpfr_set_inf (x, -1);
    219      1.1  mrg   mpfr_ui_sub (y, 1L, x, MPFR_RNDN);
    220      1.1  mrg   MPFR_ASSERTN (mpfr_inf_p (y));
    221      1.1  mrg   MPFR_ASSERTN (mpfr_sgn (y) > 0);
    222      1.1  mrg 
    223      1.1  mrg   mpfr_clear (x);
    224      1.1  mrg   mpfr_clear (y);
    225      1.1  mrg }
    226      1.1  mrg 
    227      1.1  mrg /* Check mpfr_ui_sub with u = 0 (unsigned). */
    228      1.1  mrg static void check_neg (void)
    229      1.1  mrg {
    230      1.1  mrg   mpfr_t x, yneg, ysub;
    231      1.1  mrg   int i, s;
    232      1.1  mrg   int r;
    233      1.1  mrg 
    234      1.1  mrg   mpfr_init2 (x, 64);
    235      1.1  mrg   mpfr_init2 (yneg, 32);
    236      1.1  mrg   mpfr_init2 (ysub, 32);
    237      1.1  mrg 
    238      1.1  mrg   for (i = 0; i <= 25; i++)
    239      1.1  mrg     {
    240      1.1  mrg       mpfr_sqrt_ui (x, i, MPFR_RNDN);
    241      1.1  mrg       for (s = 0; s <= 1; s++)
    242      1.1  mrg         {
    243      1.1  mrg           RND_LOOP (r)
    244      1.1  mrg             {
    245      1.1  mrg               int tneg, tsub;
    246      1.1  mrg 
    247      1.1  mrg               tneg = mpfr_neg (yneg, x, (mpfr_rnd_t) r);
    248      1.1  mrg               tsub = mpfr_ui_sub (ysub, 0, x, (mpfr_rnd_t) r);
    249      1.1  mrg               MPFR_ASSERTN (mpfr_equal_p (yneg, ysub));
    250      1.1  mrg               MPFR_ASSERTN (!(MPFR_IS_POS (yneg) ^ MPFR_IS_POS (ysub)));
    251      1.1  mrg               MPFR_ASSERTN (tneg == tsub);
    252      1.1  mrg             }
    253      1.1  mrg           mpfr_neg (x, x, MPFR_RNDN);
    254      1.1  mrg         }
    255      1.1  mrg     }
    256      1.1  mrg 
    257      1.1  mrg   mpfr_clear (x);
    258      1.1  mrg   mpfr_clear (yneg);
    259      1.1  mrg   mpfr_clear (ysub);
    260      1.1  mrg }
    261      1.1  mrg 
    262  1.1.1.3  mrg static void
    263  1.1.1.3  mrg check_overflow (void)
    264  1.1.1.3  mrg {
    265  1.1.1.3  mrg   mpfr_exp_t emin, emax;
    266  1.1.1.3  mrg   mpfr_t x, y1, y2;
    267  1.1.1.3  mrg   int inex1, inex2, rnd_mode;
    268  1.1.1.4  mrg   mpfr_flags_t flags1, flags2;
    269  1.1.1.3  mrg 
    270  1.1.1.3  mrg   emin = mpfr_get_emin ();
    271  1.1.1.3  mrg   emax = mpfr_get_emax ();
    272  1.1.1.3  mrg   set_emin (MPFR_EMIN_MIN);
    273  1.1.1.3  mrg   set_emax (MPFR_EMAX_MAX);
    274  1.1.1.3  mrg 
    275  1.1.1.3  mrg   mpfr_inits2 (32, x, y1, y2, (mpfr_ptr) 0);
    276  1.1.1.3  mrg   mpfr_setmax (x, MPFR_EMAX_MAX);
    277  1.1.1.3  mrg   mpfr_neg (x, x, MPFR_RNDN);
    278  1.1.1.4  mrg   RND_LOOP_NO_RNDF (rnd_mode)
    279  1.1.1.4  mrg     {
    280  1.1.1.4  mrg       if (rnd_mode == MPFR_RNDU || rnd_mode == MPFR_RNDA)
    281  1.1.1.4  mrg         {
    282  1.1.1.4  mrg           inex1 = mpfr_overflow (y1, (mpfr_rnd_t) rnd_mode, 1);
    283  1.1.1.4  mrg           flags1 = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT;
    284  1.1.1.4  mrg         }
    285  1.1.1.4  mrg       else
    286  1.1.1.4  mrg         {
    287  1.1.1.4  mrg           mpfr_neg (y1, x, MPFR_RNDN);
    288  1.1.1.4  mrg           inex1 = -1;
    289  1.1.1.4  mrg           flags1 = MPFR_FLAGS_INEXACT;
    290  1.1.1.4  mrg         }
    291  1.1.1.4  mrg       mpfr_clear_flags ();
    292  1.1.1.4  mrg       inex2 = mpfr_ui_sub (y2, 1, x, (mpfr_rnd_t) rnd_mode);
    293  1.1.1.4  mrg       flags2 = __gmpfr_flags;
    294  1.1.1.4  mrg       if (!(mpfr_equal_p (y1, y2) &&
    295  1.1.1.4  mrg             SAME_SIGN (inex1, inex2) &&
    296  1.1.1.4  mrg             flags1 == flags2))
    297  1.1.1.4  mrg         {
    298  1.1.1.4  mrg           printf ("Error in check_overflow for %s\n",
    299  1.1.1.4  mrg                   mpfr_print_rnd_mode ((mpfr_rnd_t) rnd_mode));
    300  1.1.1.4  mrg           printf ("Expected ");
    301  1.1.1.4  mrg           mpfr_dump (y1);
    302  1.1.1.4  mrg           printf ("  with inex = %d, flags =", inex1);
    303  1.1.1.4  mrg           flags_out (flags1);
    304  1.1.1.4  mrg           printf ("Got      ");
    305  1.1.1.4  mrg           mpfr_dump (y2);
    306  1.1.1.4  mrg           printf ("  with inex = %d, flags =", inex2);
    307  1.1.1.4  mrg           flags_out (flags2);
    308  1.1.1.4  mrg           exit (1);
    309  1.1.1.4  mrg         }
    310  1.1.1.4  mrg     }
    311  1.1.1.3  mrg   mpfr_clears (x, y1, y2, (mpfr_ptr) 0);
    312  1.1.1.3  mrg 
    313  1.1.1.3  mrg   set_emin (emin);
    314  1.1.1.3  mrg   set_emax (emax);
    315  1.1.1.3  mrg }
    316  1.1.1.3  mrg 
    317  1.1.1.3  mrg #define TEST_FUNCTION mpfr_ui_sub
    318  1.1.1.3  mrg #define ULONG_ARG1
    319  1.1.1.3  mrg #include "tgeneric.c"
    320  1.1.1.3  mrg 
    321      1.1  mrg int
    322      1.1  mrg main (int argc, char *argv[])
    323      1.1  mrg {
    324      1.1  mrg   mpfr_prec_t p;
    325      1.1  mrg   unsigned k;
    326      1.1  mrg 
    327      1.1  mrg   tests_start_mpfr ();
    328      1.1  mrg 
    329      1.1  mrg   check_nans ();
    330      1.1  mrg 
    331      1.1  mrg   special ();
    332      1.1  mrg   for (p=2; p<100; p++)
    333      1.1  mrg     for (k=0; k<100; k++)
    334      1.1  mrg       check_two_sum (p);
    335      1.1  mrg 
    336      1.1  mrg   check(1196426492, "1.4218093058435347e-3", MPFR_RNDN,
    337      1.1  mrg         "1.1964264919985781e9");
    338      1.1  mrg   check(1092583421, "-1.0880649218158844e9", MPFR_RNDN,
    339      1.1  mrg         "2.1806483428158845901e9");
    340      1.1  mrg   check(948002822, "1.22191250737771397120e+20", MPFR_RNDN,
    341      1.1  mrg         "-1.2219125073682338611e20");
    342      1.1  mrg   check(832100416, "4.68311314939691330000e-215", MPFR_RNDD,
    343      1.1  mrg         "8.3210041599999988079e8");
    344      1.1  mrg   check(1976245324, "1.25296395864546893357e+232", MPFR_RNDZ,
    345      1.1  mrg         "-1.2529639586454686577e232");
    346      1.1  mrg   check(2128997392, "-1.08496826129284207724e+187", MPFR_RNDU,
    347      1.1  mrg         "1.0849682612928422704e187");
    348      1.1  mrg   check(293607738, "-1.9967571564050541e-5", MPFR_RNDU,
    349      1.1  mrg         "2.9360773800002003e8");
    350      1.1  mrg   check(354270183, "2.9469161763489528e3", MPFR_RNDN,
    351      1.1  mrg         "3.5426723608382362e8");
    352  1.1.1.3  mrg   check_overflow ();
    353      1.1  mrg 
    354      1.1  mrg   check_neg ();
    355      1.1  mrg 
    356  1.1.1.4  mrg   test_generic (MPFR_PREC_MIN, 1000, 100);
    357  1.1.1.3  mrg 
    358      1.1  mrg   tests_end_mpfr ();
    359      1.1  mrg   return 0;
    360      1.1  mrg }
    361