(root)/
mpfr-4.2.1/
tests/
tget_f.c
       1  /* Test file for mpfr_get_f.
       2  
       3  Copyright 2005-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_MPF_INTERNALS
      24  #include "mpfr-test.h"
      25  
      26  #ifndef MPFR_USE_MINI_GMP
      27  
      28  /* Test that there is no lost of accuracy when converting a mpfr_t number
      29     into a mpf_t number (test with various precisions and exponents). */
      30  static void
      31  prec_test (void)
      32  {
      33    int px, py;
      34  
      35    for (py = 3; py <= 136; py++)
      36      {
      37        mpfr_t y1, y2, y3;
      38  
      39        mpfr_init2 (y1, py);
      40        mpfr_init2 (y2, py);
      41        mpfr_init2 (y3, py);
      42  
      43        for (px = 32; px <= 160; px += 32)
      44          {
      45            mpf_t x1, x2, x3;
      46            int e;
      47  
      48            mpf_init (x1);
      49            mpf_init (x2);
      50            mpf_init (x3);
      51            mpfr_set_ui_2exp (y1, 1, py - 1, MPFR_RNDN);
      52            mpfr_get_f (x1, y1, MPFR_RNDN);  /* exact (power of 2) */
      53            mpf_set (x2, x1);
      54            mpfr_set (y2, y1, MPFR_RNDN);
      55  
      56            for (e = py - 2; e >= 0; e--)
      57              {
      58                int inex;
      59                mpf_div_2exp (x2, x2, 1);
      60                mpf_add (x1, x1, x2);
      61                mpfr_div_2ui (y2, y2, 1, MPFR_RNDN);
      62                inex = mpfr_add (y1, y1, y2, MPFR_RNDN);
      63                MPFR_ASSERTN (inex == 0);
      64                mpfr_set_f (y3, x1, MPFR_RNDN);
      65                if (! mpfr_equal_p (y1, y3))
      66                  break;
      67                inex = mpfr_get_f (x3, y3, MPFR_RNDN);
      68                if (mpf_cmp (x1, x3) != 0)
      69                  {
      70                    printf ("Error in prec_test (px = %d, py = %d, e = %d)\n",
      71                            px, py, e);
      72                    printf ("x1 = ");
      73                    mpf_out_str (stdout, 16, 0, x1);
      74                    printf ("\nx2 = ");
      75                    mpf_out_str (stdout, 16, 0, x2);
      76                    printf ("\n");
      77                    exit (1);
      78                  }
      79                if (inex != 0)
      80                  {
      81                    printf ("Error in prec_test (px = %d, py = %d, e = %d)\n",
      82                            px, py, e);
      83                    printf ("wrong ternary value got: %+d, expected: 0\n",
      84                            inex);
      85                    exit (1);
      86                  }
      87              }
      88  
      89            mpf_clear (x1);
      90            mpf_clear (x2);
      91            mpf_clear (x3);
      92          }
      93  
      94        mpfr_clear (y1);
      95        mpfr_clear (y2);
      96        mpfr_clear (y3);
      97      }
      98  }
      99  
     100  static void
     101  special_test (void)
     102  {
     103    int inex;
     104    mpf_t x;
     105    mpfr_t y;
     106  
     107    mpfr_init (y);
     108    mpf_init (x);
     109  
     110    mpfr_set_nan (y);
     111    mpfr_clear_flags ();
     112    mpfr_get_f (x, y, MPFR_RNDN);
     113    if (! mpfr_erangeflag_p ())
     114      {
     115        printf ("Error: mpfr_get_f(NaN) should raise erange flag\n");
     116        exit (1);
     117      }
     118  
     119    mpfr_set_inf (y, +1);
     120    mpfr_clear_flags ();
     121    inex = mpfr_get_f (x, y, MPFR_RNDN);
     122    if (inex >= 0)
     123      {
     124        printf ("Error: mpfr_get_f(+Inf) should return a negative ternary"
     125                "value\n");
     126        exit (1);
     127      }
     128    if (! mpfr_erangeflag_p ())
     129      {
     130        printf ("Error: mpfr_get_f(+Inf) should raise erange flag\n");
     131        exit (1);
     132      }
     133  
     134    mpfr_set_inf (y, -1);
     135    mpfr_clear_flags ();
     136    inex = mpfr_get_f (x, y, MPFR_RNDN);
     137    if (inex <= 0)
     138      {
     139        printf ("Error: mpfr_get_f(-Inf) should return a positive ternary"
     140                "value\n");
     141        exit (1);
     142      }
     143    if (! mpfr_erangeflag_p ())
     144      {
     145        printf ("Error: mpfr_get_f(-Inf) should raise erange flag\n");
     146        exit (1);
     147      }
     148  
     149    mpfr_set_ui (y, 0, MPFR_RNDN);
     150    if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, 0))
     151      {
     152        printf ("Error: mpfr_get_f(+0) fails\n");
     153        exit (1);
     154      }
     155  
     156    mpfr_set_ui (y, 0, MPFR_RNDN);
     157    mpfr_neg (y, y, MPFR_RNDN);
     158    if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, 0))
     159      {
     160        printf ("Error: mpfr_get_f(-0) fails\n");
     161        exit (1);
     162      }
     163  
     164    mpfr_clear (y);
     165    mpf_clear (x);
     166  }
     167  
     168  static void
     169  ternary_test (void)
     170  {
     171    int prec;
     172    int rnd;
     173    int inex, expected_inex;
     174    mpf_t x;
     175    mpfr_t y;
     176  
     177    mpf_init2 (x, 256);
     178    mpfr_init2 (y, 256);
     179  
     180    for (prec = MPFR_PREC_MIN; prec <= 256; prec++)
     181      {
     182  
     183        mpf_set_prec (x, prec);
     184        mpfr_set_prec (y, PREC (x) * GMP_NUMB_BITS + 1);
     185  
     186        /* y == 1 */
     187        mpfr_set_ui_2exp (y, 1, prec, MPFR_RNDN);
     188  
     189        RND_LOOP_NO_RNDF (rnd)
     190          {
     191            inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
     192  
     193            if (inex != 0 || mpfr_cmp_f (y, x) != 0)
     194              {
     195                printf ("Error (1) in mpfr_get_f (x, y, %s)\nx = ",
     196                        mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     197                mpf_out_str (stdout, 2, 0, x);
     198                printf ("\ny = ");
     199                mpfr_dump (y);
     200                if (inex != 0)
     201                  printf ("got ternary value = %+d, expected: 0\n", inex);
     202  
     203                exit (1);
     204              }
     205          }
     206  
     207        /* y == 1 + epsilon */
     208        mpfr_nextbelow (y);
     209  
     210        RND_LOOP_NO_RNDF (rnd)
     211          {
     212            switch (rnd)
     213              {
     214              case MPFR_RNDU: case MPFR_RNDA:
     215              case MPFR_RNDN:
     216                expected_inex = +1;
     217                break;
     218              default :
     219                expected_inex = -1;
     220              }
     221  
     222            inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
     223  
     224            if (! SAME_SIGN (expected_inex, inex)
     225                || SAME_SIGN (expected_inex, mpfr_cmp_f (y, x)))
     226              {
     227                printf ("Error (2) in mpfr_get_f (x, y, %s)\nx = ",
     228                        mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     229                mpf_out_str (stdout, 2, 0, x);
     230                printf ("\ny = ");
     231                mpfr_dump (y);
     232                if (! SAME_SIGN (expected_inex, inex))
     233                  printf ("got ternary value = %+d, expected: %+d\n",
     234                          inex, expected_inex);
     235  
     236                exit (1);
     237              }
     238          }
     239  
     240        /* y == positive random float */
     241        mpfr_random2 (y, MPFR_LIMB_SIZE (y), 1024, RANDS);
     242  
     243        RND_LOOP_NO_RNDF (rnd)
     244          {
     245            inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
     246  
     247            if (! SAME_SIGN (inex, -mpfr_cmp_f (y, x)))
     248              {
     249                printf ("Error (3) in mpfr_get_f (x, y, %s)\nx = ",
     250                        mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     251                mpf_out_str (stdout, 2, 0, x);
     252                printf ("\ny = ");
     253                mpfr_dump (y);
     254                printf ("got ternary value = %+d, expected: %+d\n",
     255                        inex, -mpfr_cmp_f (y, x));
     256  
     257                exit (1);
     258              }
     259          }
     260      }
     261  
     262    mpf_clear (x);
     263    mpfr_clear (y);
     264  }
     265  
     266  int
     267  main (void)
     268  {
     269    mpf_t x;
     270    mpfr_t y, z;
     271    unsigned long i;
     272    mpfr_exp_t e;
     273    int inex;
     274  
     275    tests_start_mpfr ();
     276  
     277    mpfr_init (y);
     278    mpfr_init (z);
     279    mpf_init (x);
     280  
     281    i = 1;
     282    while (i)
     283      {
     284        mpfr_set_ui (y, i, MPFR_RNDN);
     285        if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, i))
     286          {
     287            printf ("Error: mpfr_get_f(%lu) fails\n", i);
     288            exit (1);
     289          }
     290        if (i <= - (unsigned long) LONG_MIN)
     291          {
     292            long j = i < - (unsigned long) LONG_MIN ? - (long) i : LONG_MIN;
     293            mpfr_set_si (y, j, MPFR_RNDN);
     294            if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_si (x, j))
     295              {
     296                printf ("Error: mpfr_get_f(-%lu) fails\n", i);
     297                exit (1);
     298              }
     299          }
     300        i *= 2;
     301      }
     302  
     303    /* same tests, but with a larger precision for y, which requires to
     304       round it */
     305    mpfr_set_prec (y, 100);
     306    i = 1;
     307    while (i)
     308      {
     309        mpfr_set_ui (y, i, MPFR_RNDN);
     310        inex = mpfr_get_f (x, y, MPFR_RNDN);
     311        if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x)) || mpf_cmp_ui (x, i))
     312          {
     313            printf ("Error: mpfr_get_f(%lu) fails\n", i);
     314            exit (1);
     315          }
     316        mpfr_set_si (y, (signed long) -i, MPFR_RNDN);
     317        inex = mpfr_get_f (x, y, MPFR_RNDN);
     318        if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x))
     319            || mpf_cmp_si (x, (signed long) -i))
     320          {
     321            printf ("Error: mpfr_get_f(-%lu) fails\n", i);
     322            exit (1);
     323          }
     324        i *= 2;
     325      }
     326  
     327    /* bug reported by Jim White */
     328    for (e = 0; e <= 2 * GMP_NUMB_BITS; e++)
     329      {
     330        /* test with 2^(-e) */
     331        mpfr_set_ui (y, 1, MPFR_RNDN);
     332        mpfr_div_2ui (y, y, e, MPFR_RNDN);
     333        inex = mpfr_get_f (x, y, MPFR_RNDN);
     334        mpf_mul_2exp (x, x, e);
     335        if (inex != 0 || mpf_cmp_ui (x, 1) != 0)
     336          {
     337            printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n");
     338            printf ("y=");
     339            mpfr_dump (y);
     340            printf ("x=");
     341            mpf_div_2exp (x, x, e);
     342            mpf_out_str (stdout, 2, 0, x);
     343            exit (1);
     344          }
     345  
     346        /* test with 2^(e) */
     347        mpfr_set_ui (y, 1, MPFR_RNDN);
     348        mpfr_mul_2ui (y, y, e, MPFR_RNDN);
     349        inex = mpfr_get_f (x, y, MPFR_RNDN);
     350        mpf_div_2exp (x, x, e);
     351        if (inex != 0 || mpf_cmp_ui (x, 1) != 0)
     352          {
     353            printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n");
     354            printf ("y=");
     355            mpfr_dump (y);
     356            printf ("x=");
     357            mpf_mul_2exp (x, x, e);
     358            mpf_out_str (stdout, 2, 0, x);
     359            exit (1);
     360          }
     361      }
     362  
     363    /* Bug reported by Yury Lukach on 2006-04-05 */
     364    mpfr_set_prec (y, 32);
     365    mpfr_set_prec (z, 32);
     366    mpf_set_prec (x, 32);
     367    mpfr_set_ui_2exp (y, 0xc1234567, -30, MPFR_RNDN);
     368    mpfr_get_f (x, y, MPFR_RNDN);
     369    inex = mpfr_set_f (z, x, MPFR_RNDN);
     370    if (inex != 0 || ! mpfr_equal_p (y, z))
     371      {
     372        printf ("Error in mpfr_get_f:\n  inex = %d, y = ", inex);
     373        mpfr_dump (z);
     374        printf ("Expected:\n  inex = 0, y = ");
     375        mpfr_dump (y);
     376        exit (1);
     377      }
     378  
     379    mpfr_clear (y);
     380    mpfr_clear (z);
     381    mpf_clear (x);
     382  
     383    special_test ();
     384    prec_test ();
     385    ternary_test ();
     386  
     387    tests_end_mpfr ();
     388    return 0;
     389  }
     390  
     391  #else
     392  
     393  int
     394  main (void)
     395  {
     396    return 77;
     397  }
     398  
     399  #endif