(root)/
mpfr-4.2.1/
tests/
tget_z.c
       1  /* Test file for mpz_set_fr / mpfr_get_z / mpfr_get_z_2exp.
       2  
       3  Copyright 2004, 2006-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  #include "mpfr-test.h"
      24  
      25  static void
      26  check_diff (void)
      27  {
      28    int inex;
      29    mpfr_t x;
      30    mpz_t  z;
      31    mpfr_exp_t emin;
      32  
      33    mpz_init   (z);
      34    mpfr_init2 (x, 2);
      35  
      36    mpfr_set_ui (x, 2047, MPFR_RNDU);
      37    mpz_set_fr (z, x, MPFR_RNDN);
      38    if (mpz_cmp_ui (z, 2048) != 0)
      39      {
      40        printf ("get_z RU 2048 failed\n");
      41        exit (1);
      42      }
      43  
      44    mpfr_set_prec (x, 6);
      45    mpfr_set_str (x, "17.5", 10, MPFR_RNDN);
      46    inex = mpfr_get_z (z, x, MPFR_RNDN);
      47    if (inex <= 0 || mpz_cmp_ui (z, 18) != 0)
      48      {
      49        printf ("get_z RN 17.5 failed\n");
      50        exit (1);
      51      }
      52  
      53    /* save default emin */
      54    emin = mpfr_get_emin ();;
      55  
      56    set_emin (17);
      57    mpfr_set_ui (x, 0, MPFR_RNDN);
      58    inex = mpfr_get_z (z, x, MPFR_RNDN);
      59    if (inex != 0 || mpz_cmp_ui (z, 0) != 0)
      60      {
      61        printf ("get_z 0 failed\n");
      62        exit (1);
      63      }
      64  
      65    /* restore default emin */
      66    set_emin (emin);
      67  
      68    mpfr_clear (x);
      69    mpz_clear  (z);
      70  }
      71  
      72  static void
      73  check_one (mpz_ptr z)
      74  {
      75    mpfr_exp_t emin, emax;
      76    int    inex;
      77    int    sh, neg;
      78    mpfr_t f;
      79    mpz_t  got, ex, t;
      80  
      81    emin = mpfr_get_emin ();
      82    emax = mpfr_get_emax ();
      83  
      84    mpfr_init2 (f, MAX (mpz_sizeinbase (z, 2), MPFR_PREC_MIN));
      85    mpz_init (got);
      86    mpz_init (ex);
      87    mpz_init (t);
      88  
      89    for (sh = -2*GMP_NUMB_BITS ; sh < 2*GMP_NUMB_BITS ; sh++)
      90      {
      91        inex = mpfr_set_z (f, z, MPFR_RNDN);  /* exact */
      92        MPFR_ASSERTN (inex == 0);
      93  
      94        inex = sh < 0 ?
      95          mpfr_div_2ui (f, f, -sh, MPFR_RNDN) :
      96          mpfr_mul_2ui (f, f, sh, MPFR_RNDN);
      97        MPFR_ASSERTN (inex == 0);
      98  
      99        for (neg = 0; neg <= 1; neg++)
     100          {
     101            int rnd;
     102  
     103            /* Test (-1)^neg * z * 2^sh */
     104  
     105            RND_LOOP_NO_RNDF (rnd)
     106              {
     107                int ex_inex, same;
     108                int d, fi, e;
     109                mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
     110                                          MPFR_FLAGS_ALL }, ex_flags, gt_flags;
     111  
     112                if (neg)
     113                  mpz_neg (ex, z);
     114                else
     115                  mpz_set (ex, z);
     116  
     117                if (sh < 0)
     118                  switch (rnd)
     119                    {
     120                    case MPFR_RNDN:
     121                      mpz_set_si (t, neg ? -1 : 1);
     122                      mpz_mul_2exp (t, t, -sh - 1);
     123                      mpz_add (ex, ex, t);
     124                      /* d = mpz_divisible_2exp_p (ex, -sh); */
     125                      d = mpz_scan1 (ex, 0) >= -sh;
     126                      mpz_tdiv_q_2exp (ex, ex, -sh);
     127                      if (d && mpz_tstbit (ex, 0) != 0)  /* even rounding */
     128                        {
     129                          if (neg)
     130                            mpz_add_ui (ex, ex, 1);
     131                          else
     132                            mpz_sub_ui (ex, ex, 1);
     133                        }
     134                      break;
     135                    case MPFR_RNDZ:
     136                      mpz_tdiv_q_2exp (ex, ex, -sh);
     137                      break;
     138                    case MPFR_RNDU:
     139                      mpz_cdiv_q_2exp (ex, ex, -sh);
     140                      break;
     141                    case MPFR_RNDD:
     142                      mpz_fdiv_q_2exp (ex, ex, -sh);
     143                      break;
     144                    case MPFR_RNDA:
     145                      if (neg)
     146                        mpz_fdiv_q_2exp (ex, ex, -sh);
     147                      else
     148                        mpz_cdiv_q_2exp (ex, ex, -sh);
     149                      break;
     150                    default:
     151                      MPFR_ASSERTN (0);
     152                    }
     153                else
     154                  mpz_mul_2exp (ex, ex, sh);
     155  
     156                ex_inex = - mpfr_cmp_z (f, ex);
     157                ex_inex = VSIGN (ex_inex);
     158  
     159                for (fi = 0; fi < numberof (flags); fi++)
     160                  for (e = 0; e < 2; e++)
     161                    {
     162                      if (e)
     163                        {
     164                          mpfr_exp_t ef;
     165  
     166                          if (MPFR_IS_ZERO (f))
     167                            break;
     168                          ef = MPFR_GET_EXP (f);
     169                          set_emin (ef);
     170                          set_emax (ef);
     171                        }
     172                      ex_flags = __gmpfr_flags = flags[fi];
     173                      if (ex_inex != 0)
     174                        ex_flags |= MPFR_FLAGS_INEXACT;
     175                      inex = mpfr_get_z (got, f, (mpfr_rnd_t) rnd);
     176                      inex = VSIGN (inex);
     177                      gt_flags = __gmpfr_flags;
     178                      set_emin (emin);
     179                      set_emax (emax);
     180                      same = SAME_SIGN (inex, ex_inex);
     181  
     182                      if (mpz_cmp (got, ex) != 0 ||
     183                          !same || gt_flags != ex_flags)
     184                        {
     185                          printf ("Error in check_one for sh=%d, fi=%d, %s%s\n",
     186                                  sh, fi,
     187                                  mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
     188                                  e ? ", reduced exponent range" : "");
     189                          printf ("     f = "); mpfr_dump (f);
     190                          printf ("expected "); mpz_out_str (stdout, 10, ex);
     191                          printf ("\n     got "); mpz_out_str (stdout, 10, got);
     192                          printf ("\nExpected inex ~ %d, got %d (%s)\n",
     193                                  ex_inex, inex, same ? "OK" : "wrong");
     194                          printf ("Flags:\n");
     195                          printf ("      in"); flags_out (flags[fi]);
     196                          printf ("expected"); flags_out (ex_flags);
     197                          printf ("     got"); flags_out (gt_flags);
     198                          exit (1);
     199                        }
     200                    }
     201              }
     202  
     203            mpfr_neg (f, f, MPFR_RNDN);
     204          }
     205      }
     206  
     207    mpfr_clear (f);
     208    mpz_clear (got);
     209    mpz_clear (ex);
     210    mpz_clear (t);
     211  }
     212  
     213  static void
     214  check (void)
     215  {
     216    mpz_t  z;
     217  
     218    mpz_init (z);
     219  
     220    mpz_set_ui (z, 0L);
     221    check_one (z);
     222  
     223    mpz_set_si (z, 17L);
     224    check_one (z);
     225  
     226    mpz_set_si (z, 123L);
     227    check_one (z);
     228  
     229    mpz_rrandomb (z, RANDS, 2*GMP_NUMB_BITS);
     230    check_one (z);
     231  
     232    mpz_rrandomb (z, RANDS, 5*GMP_NUMB_BITS);
     233    check_one (z);
     234  
     235    mpz_clear (z);
     236  }
     237  
     238  static void
     239  special (void)
     240  {
     241    int inex;
     242    mpfr_t x;
     243    mpz_t z;
     244    int i, fi;
     245    int rnd;
     246    mpfr_exp_t e;
     247    mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
     248                              MPFR_FLAGS_ALL }, ex_flags, gt_flags;
     249  
     250    mpfr_init2 (x, 2);
     251    mpz_init (z);
     252  
     253    RND_LOOP (rnd)
     254      for (i = -1; i <= 1; i++)
     255        for (fi = 0; fi < numberof (flags); fi++)
     256          {
     257            ex_flags = flags[fi] | MPFR_FLAGS_ERANGE;
     258            if (i != 0)
     259              mpfr_set_nan (x);
     260            else
     261              mpfr_set_inf (x, i);
     262            __gmpfr_flags = flags[fi];
     263            inex = mpfr_get_z (z, x, (mpfr_rnd_t) rnd);
     264            gt_flags = __gmpfr_flags;
     265            if (gt_flags != ex_flags || inex != 0 || mpz_cmp_ui (z, 0) != 0)
     266              {
     267                printf ("special() failed on mpfr_get_z"
     268                        " for %s, i = %d, fi = %d\n",
     269                        mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), i, fi);
     270                printf ("Expected z = 0, inex = 0,");
     271                flags_out (ex_flags);
     272                printf ("Got      z = ");
     273                mpz_out_str (stdout, 10, z);
     274                printf (", inex = %d,", inex);
     275                flags_out (gt_flags);
     276                exit (1);
     277              }
     278            __gmpfr_flags = flags[fi];
     279            e = mpfr_get_z_2exp (z, x);
     280            gt_flags = __gmpfr_flags;
     281            if (gt_flags != ex_flags || e != __gmpfr_emin ||
     282                mpz_cmp_ui (z, 0) != 0)
     283              {
     284                printf ("special() failed on mpfr_get_z_2exp"
     285                        " for %s, i = %d, fi = %d\n",
     286                        mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), i, fi);
     287                printf ("Expected z = 0, e = %" MPFR_EXP_FSPEC "d,",
     288                        (mpfr_eexp_t) __gmpfr_emin);
     289                flags_out (ex_flags);
     290                printf ("Got      z = ");
     291                mpz_out_str (stdout, 10, z);
     292                printf (", e = %" MPFR_EXP_FSPEC "d,", (mpfr_eexp_t) e);
     293                flags_out (gt_flags);
     294                exit (1);
     295              }
     296          }
     297  
     298    mpfr_clear (x);
     299    mpz_clear (z);
     300  }
     301  
     302  int
     303  main (void)
     304  {
     305    tests_start_mpfr ();
     306  
     307    check ();
     308    check_diff ();
     309    special ();
     310  
     311    tests_end_mpfr ();
     312    return 0;
     313  }