(root)/
mpfr-4.2.1/
tests/
tget_sj.c
       1  /* Test file for mpfr_get_sj and mpfr_get_uj.
       2  
       3  Copyright 2004-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  #define MPFR_NEED_INTMAX_H
      24  #include "mpfr-test.h"
      25  
      26  #ifndef _MPFR_H_HAVE_INTMAX_T
      27  
      28  int
      29  main (void)
      30  {
      31    return 77;
      32  }
      33  
      34  #else
      35  
      36  #ifndef NPRINTF_J
      37  #define PRMAX(SPEC,V) printf (" %j" SPEC ",", V)
      38  #else
      39  #define PRMAX(SPEC,V) (void) 0
      40  #endif
      41  
      42  static void
      43  check_sj (intmax_t s, mpfr_ptr x)
      44  {
      45    mpfr_exp_t emin, emax;
      46    mpfr_t y;
      47    int i;
      48  
      49    mpfr_init2 (y, MPFR_PREC (x) + 2);
      50  
      51    emin = mpfr_get_emin ();
      52    emax = mpfr_get_emax ();
      53  
      54    for (i = -1; i <= 1; i++)
      55      {
      56        int rnd;
      57        int inex;
      58        int fi, e;
      59        mpfr_flags_t flags[2] = { 0, MPFR_FLAGS_ALL }, ex_flags, gt_flags;
      60  
      61        inex = mpfr_set_si_2exp (y, i, -2, MPFR_RNDN);
      62        MPFR_ASSERTN (inex == 0);
      63        inex = mpfr_add (y, y, x, MPFR_RNDN);
      64        MPFR_ASSERTN (inex == 0);
      65        /* y = x + i/4, with -1 <= i <= 1 */
      66        RND_LOOP (rnd)
      67          for (fi = 0; fi < numberof (flags); fi++)
      68            {
      69              intmax_t r;
      70  
      71              if (rnd == MPFR_RNDZ && i < 0 && s >= 0)
      72                continue;
      73              if (rnd == MPFR_RNDZ && i > 0 && s <= 0)
      74                continue;
      75              if (rnd == MPFR_RNDD && i < 0)
      76                continue;
      77              if (rnd == MPFR_RNDU && i > 0)
      78                continue;
      79              if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) ||
      80                                       (MPFR_IS_NEG(y) && i < 0)))
      81                continue;
      82  
      83              for (e = 0; e < 2; e++)
      84                {
      85                  if (e)
      86                    {
      87                      mpfr_exp_t ey;
      88  
      89                      if (MPFR_IS_ZERO (y))
      90                        break;
      91                      ey = MPFR_GET_EXP (y);
      92                      set_emin (ey);
      93                      set_emax (ey);
      94                    }
      95                  /* rint (y) == x == s */
      96                  __gmpfr_flags = ex_flags = flags[fi];
      97                  if (i != 0)
      98                    ex_flags |= MPFR_FLAGS_INEXACT;
      99                  r = mpfr_get_sj (y, (mpfr_rnd_t) rnd);
     100                  gt_flags = __gmpfr_flags;
     101                  set_emin (emin);
     102                  set_emax (emax);
     103                  if ((r != s || gt_flags != ex_flags) && rnd != MPFR_RNDF)
     104                    {
     105                      printf ("Error in check_sj for fi = %d, y = ", fi);
     106                      mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
     107                      printf (" in %s%s\n",
     108                              mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
     109                              e ? ", reduced exponent range" : "");
     110                      printf ("Expected:");
     111                      PRMAX ("d", s);
     112                      flags_out (ex_flags);
     113                      printf ("Got:     ");
     114                      PRMAX ("d", r);
     115                      flags_out (gt_flags);
     116                      exit (1);
     117                    }
     118                }
     119            }
     120      }
     121  
     122    mpfr_clear (y);
     123  }
     124  
     125  static void
     126  check_uj (uintmax_t u, mpfr_ptr x)
     127  {
     128    mpfr_exp_t emin, emax;
     129    mpfr_t y;
     130    int i;
     131  
     132    mpfr_init2 (y, MPFR_PREC (x) + 2);
     133  
     134    emin = mpfr_get_emin ();
     135    emax = mpfr_get_emax ();
     136  
     137    for (i = -1; i <= 1; i++)
     138      {
     139        int rnd;
     140        int inex;
     141        int fi, e;
     142        mpfr_flags_t flags[2] = { 0, MPFR_FLAGS_ALL }, ex_flags, gt_flags;
     143  
     144        inex = mpfr_set_si_2exp (y, i, -2, MPFR_RNDN);
     145        MPFR_ASSERTN (inex == 0);
     146        inex = mpfr_add (y, y, x, MPFR_RNDN);
     147        MPFR_ASSERTN (inex == 0);
     148        /* y = x + i/4, with -1 <= i <= 1 */
     149        RND_LOOP (rnd)
     150          for (fi = 0; fi < numberof (flags); fi++)
     151            {
     152              uintmax_t r;
     153  
     154              if (rnd == MPFR_RNDZ && i < 0)
     155                continue;
     156              if (rnd == MPFR_RNDD && i < 0)
     157                continue;
     158              if (rnd == MPFR_RNDU && i > 0)
     159                continue;
     160              if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) ||
     161                                       (MPFR_IS_NEG(y) && i < 0)))
     162                continue;
     163  
     164              for (e = 0; e < 2; e++)
     165                {
     166                  if (e)
     167                    {
     168                      mpfr_exp_t ey;
     169  
     170                      if (MPFR_IS_ZERO (y))
     171                        break;
     172                      ey = MPFR_GET_EXP (y);
     173                      set_emin (ey);
     174                      set_emax (ey);
     175                    }
     176                  /* rint (y) == x == u */
     177                  __gmpfr_flags = ex_flags = flags[fi];
     178                  if (i != 0)
     179                    ex_flags |= MPFR_FLAGS_INEXACT;
     180                  r = mpfr_get_uj (y, (mpfr_rnd_t) rnd);
     181                  gt_flags = __gmpfr_flags;
     182                  set_emin (emin);
     183                  set_emax (emax);
     184                  if ((r != u || gt_flags != ex_flags) && rnd != MPFR_RNDF)
     185                    {
     186                      printf ("Error in check_uj for fi = %d, y = ", fi);
     187                      mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
     188                      printf (" in %s%s\n",
     189                              mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
     190                              e ? ", reduced exponent range" : "");
     191                      printf ("Expected:");
     192                      PRMAX ("u", u);
     193                      flags_out (ex_flags);
     194                      printf ("Got:     ");
     195                      PRMAX ("u", r);
     196                      flags_out (gt_flags);
     197                      exit (1);
     198                    }
     199                }
     200            }
     201      }
     202  
     203    mpfr_clear (y);
     204  }
     205  
     206  #define CHECK_ERANGE(F,FMT,RES,INPUT,VALUE,E)                           \
     207    do                                                                    \
     208      {                                                                   \
     209        __gmpfr_flags = ex_flags = flags[fi];                             \
     210        RES = F (x, (mpfr_rnd_t) rnd);                                    \
     211        gt_flags = __gmpfr_flags;                                         \
     212        if (E)                                                            \
     213          ex_flags |= MPFR_FLAGS_ERANGE;                                  \
     214        if (RES == VALUE && gt_flags == ex_flags)                         \
     215          continue;                                                       \
     216        printf ("Error in check_erange for %s, %s, fi = %d on %s\n",      \
     217                #F, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), fi, INPUT);   \
     218        printf ("Expected:");                                             \
     219        PRMAX (FMT, VALUE);                                               \
     220        flags_out (ex_flags);                                             \
     221        printf ("Got:     ");                                             \
     222        PRMAX (FMT, RES);                                                 \
     223        flags_out (gt_flags);                                             \
     224        exit (1);                                                         \
     225      }                                                                   \
     226    while (0)
     227  
     228  #define CHECK_ERANGE_U(INPUT,VALUE,E) \
     229    CHECK_ERANGE (mpfr_get_uj, "u", u, INPUT, (uintmax_t) VALUE, E)
     230  #define CHECK_ERANGE_S(INPUT,VALUE,E) \
     231    CHECK_ERANGE (mpfr_get_sj, "d", d, INPUT, (intmax_t) VALUE, E)
     232  
     233  static void
     234  check_erange (void)
     235  {
     236    mpfr_t x;
     237    uintmax_t u;
     238    intmax_t d;
     239    int rnd;
     240    int fi;
     241    mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
     242                              MPFR_FLAGS_ALL }, ex_flags, gt_flags;
     243  
     244    /* Test for ERANGE flag + correct behavior if overflow */
     245  
     246    mpfr_init2 (x, 256);
     247  
     248    RND_LOOP (rnd)
     249      for (fi = 0; fi < numberof (flags); fi++)
     250        {
     251          mpfr_set_uj (x, UINTMAX_MAX, MPFR_RNDN);
     252          CHECK_ERANGE_U ("UINTMAX_MAX", UINTMAX_MAX, 0);
     253          mpfr_add_ui (x, x, 1, MPFR_RNDN);
     254          CHECK_ERANGE_U ("UINTMAX_MAX+1", UINTMAX_MAX, 1);
     255          mpfr_set_sj (x, -1, MPFR_RNDN);
     256          CHECK_ERANGE_U ("-1", 0, 1);
     257          mpfr_set_sj (x, INTMAX_MAX, MPFR_RNDN);
     258          CHECK_ERANGE_S ("INTMAX_MAX", INTMAX_MAX, 0);
     259          mpfr_add_ui (x, x, 1, MPFR_RNDN);
     260          CHECK_ERANGE_S ("INTMAX_MAX+1", INTMAX_MAX, 1);
     261          mpfr_set_sj (x, INTMAX_MIN, MPFR_RNDN);
     262          CHECK_ERANGE_S ("INTMAX_MIN", INTMAX_MIN, 0);
     263          mpfr_sub_ui (x, x, 1, MPFR_RNDN);
     264          CHECK_ERANGE_S ("INTMAX_MIN-1", INTMAX_MIN, 1);
     265          mpfr_set_nan (x);
     266          CHECK_ERANGE_U ("NaN", 0, 1);
     267          CHECK_ERANGE_S ("NaN", 0, 1);
     268        }
     269  
     270    mpfr_clear (x);
     271  }
     272  
     273  static void
     274  test_get_uj_smallneg (void)
     275  {
     276    mpfr_t x;
     277    int i;
     278  
     279    mpfr_init2 (x, 64);
     280  
     281    for (i = 1; i <= 4; i++)
     282      {
     283        int r;
     284  
     285        mpfr_set_si_2exp (x, -i, -2, MPFR_RNDN);
     286        RND_LOOP (r)
     287          {
     288            intmax_t s;
     289            uintmax_t u;
     290  
     291            mpfr_clear_erangeflag ();
     292            s = mpfr_get_sj (x, r != MPFR_RNDF ? (mpfr_rnd_t) r : MPFR_RNDA);
     293            if (mpfr_erangeflag_p ())
     294              {
     295                printf ("ERROR for get_sj + ERANGE + small negative op"
     296                        " for rnd = %s and x = -%d/4\n",
     297                        mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
     298                exit (1);
     299              }
     300            u = mpfr_get_uj (x, (mpfr_rnd_t) r);
     301            if (u != 0)
     302              {
     303                printf ("ERROR for get_uj + ERANGE + small negative op"
     304                        " for rnd = %s and x = -%d/4\n",
     305                        mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
     306  #ifndef NPRINTF_J
     307                printf ("Expected 0, got %ju\n", u);
     308  #endif
     309                exit (1);
     310              }
     311            if ((s == 0) ^ !mpfr_erangeflag_p ())
     312              {
     313                const char *Not = s == 0 ? "" : " not";
     314  
     315                printf ("ERROR for get_uj + ERANGE + small negative op"
     316                        " for rnd = %s and x = -%d/4\n",
     317                        mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
     318                printf ("The rounded integer ");
     319  #ifndef NPRINTF_J
     320                printf("(%jd) ", s);
     321  #endif
     322                printf("is%s representable in unsigned long,\n"
     323                       "but the erange flag is%s set.\n", Not, Not);
     324                exit (1);
     325              }
     326          }
     327      }
     328  
     329    mpfr_clear (x);
     330  }
     331  
     332  int
     333  main (void)
     334  {
     335    mpfr_prec_t prec;
     336    mpfr_t x, y;
     337    intmax_t s;
     338    uintmax_t u;
     339  
     340    tests_start_mpfr ();
     341  
     342    for (u = UINTMAX_MAX, prec = 0; u != 0; u /= 2, prec++)
     343      { }
     344  
     345    mpfr_init2 (x, prec + 4);
     346    mpfr_init2 (y, prec + 4);
     347  
     348    mpfr_set_ui (x, 0, MPFR_RNDN);
     349    check_sj (0, x);
     350    check_uj (0, x);
     351  
     352    mpfr_set_ui (x, 1, MPFR_RNDN);
     353    check_sj (1, x);
     354    check_uj (1, x);
     355  
     356    mpfr_neg (x, x, MPFR_RNDN);
     357    check_sj (-1, x);
     358  
     359    mpfr_set_si_2exp (x, 1, prec, MPFR_RNDN);
     360    mpfr_sub_ui (x, x, 1, MPFR_RNDN); /* UINTMAX_MAX */
     361  
     362    mpfr_div_ui (y, x, 2, MPFR_RNDZ);
     363    mpfr_trunc (y, y); /* INTMAX_MAX */
     364    for (s = INTMAX_MAX; s != 0; s /= 17)
     365      {
     366        check_sj (s, y);
     367        mpfr_div_ui (y, y, 17, MPFR_RNDZ);
     368        mpfr_trunc (y, y);
     369      }
     370  
     371    mpfr_div_ui (y, x, 2, MPFR_RNDZ);
     372    mpfr_trunc (y, y); /* INTMAX_MAX */
     373    mpfr_neg (y, y, MPFR_RNDN);
     374    if (INTMAX_MIN + INTMAX_MAX != 0)
     375      mpfr_sub_ui (y, y, 1, MPFR_RNDN); /* INTMAX_MIN */
     376    for (s = INTMAX_MIN; s != 0; s /= 17)
     377      {
     378        check_sj (s, y);
     379        mpfr_div_ui (y, y, 17, MPFR_RNDZ);
     380        mpfr_trunc (y, y);
     381      }
     382  
     383    for (u = UINTMAX_MAX; u != 0; u /= 17)
     384      {
     385        check_uj (u, x);
     386        mpfr_div_ui (x, x, 17, MPFR_RNDZ);
     387        mpfr_trunc (x, x);
     388      }
     389  
     390    mpfr_clear (x);
     391    mpfr_clear (y);
     392  
     393    check_erange ();
     394    test_get_uj_smallneg ();
     395  
     396    tests_end_mpfr ();
     397    return 0;
     398  }
     399  
     400  #endif