(root)/
mpfr-4.2.1/
tests/
tset.c
       1  /* Test file for mpfr_set.
       2  
       3  Copyright 2001-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 int error;
      26  
      27  #define PRINT_ERROR_IF(condition, text)         \
      28    do {                                          \
      29      if (condition)                              \
      30        {                                         \
      31          printf ("%s", text);                    \
      32          error = 1;                              \
      33        }                                         \
      34    } while (0)
      35  
      36  
      37  /* Maybe better create its own test file? */
      38  static void
      39  check_neg_special (void)
      40  {
      41    mpfr_t x, y;
      42    int inexact;
      43    int s1, s2, s3;
      44  
      45    mpfr_inits2 (53, x, y, (mpfr_ptr) 0);
      46  
      47    MPFR_SET_NAN (x);
      48    s1 = mpfr_signbit (x) != 0;
      49  
      50    mpfr_clear_nanflag ();
      51    inexact = mpfr_neg (y, x, MPFR_RNDN);
      52    s2 = mpfr_signbit (y) != 0;
      53    PRINT_ERROR_IF (!mpfr_nanflag_p (),
      54                    "ERROR: neg (NaN) doesn't set Nan flag (1).\n");
      55    PRINT_ERROR_IF (!mpfr_nan_p (y) || inexact != 0,
      56                    "ERROR: neg (NaN) failed to set variable to NaN (1).\n");
      57    PRINT_ERROR_IF (s1 == s2,
      58                    "ERROR: neg (NaN) doesn't correctly flip sign bit (1).\n");
      59  
      60    mpfr_clear_nanflag ();
      61    inexact = mpfr_neg (x, x, MPFR_RNDN);
      62    s2 = mpfr_signbit (x) != 0;
      63    PRINT_ERROR_IF (!mpfr_nanflag_p (),
      64                    "ERROR: neg (NaN) doesn't set Nan flag (2).\n");
      65    PRINT_ERROR_IF (!mpfr_nan_p (x) || inexact != 0,
      66                    "ERROR: neg (NaN) failed to set variable to NaN (2).\n");
      67    /* check following "bug" is fixed:
      68       https://sympa.inria.fr/sympa/arc/mpfr/2017-11/msg00003.html */
      69    PRINT_ERROR_IF (s1 == s2,
      70                    "ERROR: neg (NaN) doesn't correctly flip sign bit (2).\n");
      71  
      72    mpfr_clear_nanflag ();
      73    inexact = mpfr_neg (y, x, MPFR_RNDN);
      74    s3 = mpfr_signbit (y) != 0;
      75    PRINT_ERROR_IF (!mpfr_nanflag_p (),
      76                    "ERROR: neg (NaN) doesn't set Nan flag (3).\n");
      77    PRINT_ERROR_IF (!mpfr_nan_p (y) || inexact != 0,
      78                    "ERROR: neg (NaN) failed to set variable to NaN (3).\n");
      79    PRINT_ERROR_IF (s2 == s3,
      80                    "ERROR: neg (NaN) doesn't correctly flip sign bit (3).\n");
      81  
      82    mpfr_clear_nanflag ();
      83    inexact = mpfr_neg (x, x, MPFR_RNDN);
      84    s3 = mpfr_signbit (x) != 0;
      85    PRINT_ERROR_IF (!mpfr_nanflag_p (),
      86                    "ERROR: neg (NaN) doesn't set Nan flag (4).\n");
      87    PRINT_ERROR_IF (!mpfr_nan_p (x) || inexact != 0,
      88                    "ERROR: neg (NaN) failed to set variable to NaN (4).\n");
      89    PRINT_ERROR_IF (s2 == s3,
      90                    "ERROR: neg (NaN) doesn't correctly flip sign bit (4).\n");
      91  
      92    mpfr_clears (x, y, (mpfr_ptr) 0);
      93  }
      94  
      95  static void
      96  check_special (void)
      97  {
      98    mpfr_t x, y;
      99    int inexact;
     100    int s1, s2;
     101  
     102    mpfr_inits2 (53, x, y, (mpfr_ptr) 0);
     103  
     104    mpfr_set_inf (x, 1);
     105    PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) < 0,
     106                    "ERROR: mpfr_set_inf failed to set variable to +inf [1].\n");
     107    mpfr_set_inf (x, INT_MAX);
     108    PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) < 0,
     109                    "ERROR: mpfr_set_inf failed to set variable to +inf [2].\n");
     110    mpfr_set_inf (x, 0);
     111    PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) < 0,
     112                    "ERROR: mpfr_set_inf failed to set variable to +inf [3].\n");
     113    inexact = mpfr_set (y, x, MPFR_RNDN);
     114    PRINT_ERROR_IF (!mpfr_inf_p (y) || mpfr_sgn (y) < 0 || inexact != 0,
     115                    "ERROR: mpfr_set failed to set variable to +infinity.\n");
     116  
     117    inexact = mpfr_set_ui (y, 0, MPFR_RNDN);
     118    PRINT_ERROR_IF (MPFR_NOTZERO (y) || MPFR_IS_NEG (y) || inexact != 0,
     119                    "ERROR: mpfr_set_ui failed to set variable to +0.\n");
     120  
     121    mpfr_set_inf (x, -1);
     122    PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) > 0,
     123                    "ERROR: mpfr_set_inf failed to set variable to -inf [1].\n");
     124    mpfr_set_inf (x, INT_MIN);
     125    PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) > 0,
     126                    "ERROR: mpfr_set_inf failed to set variable to -inf [2].\n");
     127    inexact = mpfr_set (y, x, MPFR_RNDN);
     128    PRINT_ERROR_IF (!mpfr_inf_p (y) || mpfr_sgn (y) > 0 || inexact != 0,
     129                    "ERROR: mpfr_set failed to set variable to -infinity.\n");
     130  
     131    mpfr_set_zero (x, 1);
     132    PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_NEG (x),
     133                    "ERROR: mpfr_set_zero failed to set variable to +0 [1].\n");
     134    mpfr_set_zero (x, INT_MAX);
     135    PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_NEG (x),
     136                    "ERROR: mpfr_set_zero failed to set variable to +0 [2].\n");
     137    mpfr_set_zero (x, 0);
     138    PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_NEG (x),
     139                    "ERROR: mpfr_set_zero failed to set variable to +0 [3].\n");
     140    inexact = mpfr_set (y, x, MPFR_RNDN);
     141    PRINT_ERROR_IF (MPFR_NOTZERO (y) || MPFR_IS_NEG (y) || inexact != 0,
     142                    "ERROR: mpfr_set failed to set variable to +0.\n");
     143  
     144    mpfr_set_zero (x, -1);
     145    PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_POS (x),
     146                    "ERROR: mpfr_set_zero failed to set variable to -0 [1].\n");
     147    mpfr_set_zero (x, INT_MIN);
     148    PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_POS (x),
     149                    "ERROR: mpfr_set_zero failed to set variable to -0 [2].\n");
     150    inexact = mpfr_set (y, x, MPFR_RNDN);
     151    PRINT_ERROR_IF (MPFR_NOTZERO (y) || MPFR_IS_POS (y) || inexact != 0,
     152                    "ERROR: mpfr_set failed to set variable to -0.\n");
     153  
     154    /* NaN tests */
     155  
     156    mpfr_set_nan (x);
     157    PRINT_ERROR_IF (!mpfr_nan_p (x),
     158                    "ERROR: mpfr_set_nan failed to set variable to NaN.\n");
     159    s1 = mpfr_signbit (x) != 0;
     160  
     161    mpfr_clear_nanflag ();
     162    inexact = mpfr_set (y, x, MPFR_RNDN);
     163    s2 = mpfr_signbit (y) != 0;
     164    PRINT_ERROR_IF (!mpfr_nanflag_p (),
     165                    "ERROR: mpfr_set doesn't set Nan flag (1).\n");
     166    PRINT_ERROR_IF (!mpfr_nan_p (y) || inexact != 0,
     167                    "ERROR: mpfr_set failed to set variable to NaN (1).\n");
     168    PRINT_ERROR_IF (s1 != s2,
     169                    "ERROR: mpfr_set doesn't preserve the sign bit (1).\n");
     170  
     171    mpfr_clear_nanflag ();
     172    inexact = mpfr_set (x, x, MPFR_RNDN);
     173    s2 = mpfr_signbit (x) != 0;
     174    PRINT_ERROR_IF (!mpfr_nanflag_p (),
     175                    "ERROR: mpfr_set doesn't set Nan flag (2).\n");
     176    PRINT_ERROR_IF (!mpfr_nan_p (x) || inexact != 0,
     177                    "ERROR: mpfr_set failed to set variable to NaN (2).\n");
     178    PRINT_ERROR_IF (s1 != s2,
     179                    "ERROR: mpfr_set doesn't preserve the sign bit (2).\n");
     180  
     181    MPFR_CHANGE_SIGN (x);
     182    s1 = !s1;
     183  
     184    mpfr_clear_nanflag ();
     185    inexact = mpfr_set (y, x, MPFR_RNDN);
     186    s2 = mpfr_signbit (y) != 0;
     187    PRINT_ERROR_IF (!mpfr_nanflag_p (),
     188                    "ERROR: mpfr_set doesn't set Nan flag (3).\n");
     189    PRINT_ERROR_IF (!mpfr_nan_p (y) || inexact != 0,
     190                    "ERROR: mpfr_set failed to set variable to NaN (3).\n");
     191    PRINT_ERROR_IF (s1 != s2,
     192                    "ERROR: mpfr_set doesn't preserve the sign bit (3).\n");
     193  
     194    mpfr_clear_nanflag ();
     195    inexact = mpfr_set (x, x, MPFR_RNDN);
     196    s2 = mpfr_signbit (x) != 0;
     197    PRINT_ERROR_IF (!mpfr_nanflag_p (),
     198                    "ERROR: mpfr_set doesn't set Nan flag (4).\n");
     199    PRINT_ERROR_IF (!mpfr_nan_p (x) || inexact != 0,
     200                    "ERROR: mpfr_set failed to set variable to NaN (4).\n");
     201    PRINT_ERROR_IF (s1 != s2,
     202                    "ERROR: mpfr_set doesn't preserve the sign bit (4).\n");
     203  
     204    mpfr_clears (x, y, (mpfr_ptr) 0);
     205  }
     206  
     207  static void
     208  check_ternary_value (void)
     209  {
     210    int k, p, q, rnd;
     211    int inexact, cmp;
     212    mpfr_t x, y;
     213  
     214    mpfr_init (x);
     215    mpfr_init (y);
     216    for (p=2; p<500; p++)
     217      {
     218        mpfr_set_prec (x, p);
     219        mpfr_urandomb (x, RANDS);
     220        if (RAND_BOOL ())
     221          mpfr_neg (x, x, MPFR_RNDN);
     222        for (q=2; q<2*p; q++)
     223          {
     224            mpfr_set_prec (y, q);
     225            RND_LOOP (rnd)
     226              {
     227                if (rnd == MPFR_RNDF) /* the test below makes no sense */
     228                  continue;
     229                for (k = 0; k < 3; k++)
     230                  {
     231                    int a = 0, b = 0, c = 0;
     232  
     233                    switch (k)
     234                      {
     235                      case 0:
     236                        inexact = mpfr_set (y, x, (mpfr_rnd_t) rnd);
     237                        break;
     238                      case 1:
     239                        inexact = (mpfr_set) (y, x, (mpfr_rnd_t) rnd);
     240                        break;
     241                      case 2:
     242  #ifdef IGNORE_CPP_COMPAT
     243  #pragma GCC diagnostic push
     244  #pragma GCC diagnostic ignored "-Wc++-compat"
     245  #endif
     246                        inexact = mpfr_set ((a++, VOIDP_CAST(y)),
     247                                            (b++, VOIDP_CAST(x)),
     248                                            (c++, (mpfr_rnd_t) rnd));
     249  #ifdef IGNORE_CPP_COMPAT
     250  #pragma GCC diagnostic pop
     251  #endif
     252                        MPFR_ASSERTN (a == 1);
     253                        MPFR_ASSERTN (b == 1);
     254                        MPFR_ASSERTN (c == 1);
     255                        break;
     256                      }
     257                    cmp = mpfr_cmp (y, x);
     258                    if (((inexact == 0) && (cmp != 0)) ||
     259                        ((inexact > 0) && (cmp <= 0)) ||
     260                        ((inexact < 0) && (cmp >= 0)))
     261                      {
     262                        printf ("Wrong ternary value in mpfr_set for %s (%d):"
     263                                " expected %d, got %d\n",
     264                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
     265                                k, cmp, inexact);
     266                        exit (1);
     267                      }
     268                  }
     269              }
     270          }
     271      }
     272    mpfr_clear (x);
     273    mpfr_clear (y);
     274  }
     275  
     276  static void
     277  test_set_1_2 (void)
     278  {
     279    mpfr_t u, v, zz, z;
     280    int inex;
     281  
     282    /* (8,16)-bit test */
     283    mpfr_inits2 (16, u, v, zz, (mpfr_ptr) 0);
     284    mpfr_init2 (z, 8);
     285    mpfr_set_str_binary (u, "0.1100001100011010E-1");
     286    mpfr_set_str_binary (v, "0.1100010101110010E0");
     287    /* u + v = 1.0010011011111111 */
     288    inex = mpfr_add (zz, u, v, MPFR_RNDN);
     289    MPFR_ASSERTN(inex > 0);
     290    mpfr_set_str_binary (u, "1.001001110000000");
     291    MPFR_ASSERTN(mpfr_equal_p (zz, u));
     292    inex = mpfr_set_1_2 (z, zz, MPFR_RNDN, inex);
     293    /* we should have z = 1.0010011 and inex < 0 */
     294    MPFR_ASSERTN(inex < 0);
     295    mpfr_set_str_binary (u, "1.0010011");
     296    MPFR_ASSERTN(mpfr_equal_p (z, u));
     297    mpfr_clears (u, v, zz, z, (mpfr_ptr) 0);
     298  
     299    /* (16,32)-bit test:
     300     * take for v a random 32-bit number in [1/2,1), here 2859611790/2^32
     301     * take for z a random 16-bit number in [1,2), less than 2*v,
     302     with last bit 0, here we take z = 40900/2^15
     303     * take u = z-v-1/2^16-1/2^32 */
     304    mpfr_inits2 (32, u, v, zz, (mpfr_ptr) 0);
     305    mpfr_init2 (z, 16);
     306    mpfr_set_str_binary (u, "0.10010101000101001100100101110001");
     307    mpfr_set_str_binary (v, "0.10101010011100100011011010001110");
     308    /* u + v = 1.00111111100001101111111111111111 */
     309    inex = mpfr_add (zz, u, v, MPFR_RNDN);
     310    MPFR_ASSERTN(inex > 0);
     311    mpfr_set_str_binary (u, "1.0011111110000111");
     312    MPFR_ASSERTN(mpfr_equal_p (zz, u));
     313    inex = mpfr_set_1_2 (z, zz, MPFR_RNDN, inex);
     314    /* we should have z = 1.001111111000011 and inex < 0 */
     315    MPFR_ASSERTN(inex < 0);
     316    mpfr_set_str_binary (u, "1.001111111000011");
     317    MPFR_ASSERTN(mpfr_equal_p (z, u));
     318    mpfr_clears (u, v, zz, z, (mpfr_ptr) 0);
     319  
     320    /* (32,64)-bit test:
     321     * take for v a random 64-bit number in [1/2,1),
     322       here v = 13687985014345662879/2^64
     323     * take for z a random 32-bit number in [1,2), less than 2*v,
     324       with last bit 0, here we take z = 2871078774/2^31
     325     * take u = z-v-1/2^32-1/2^64 */
     326    mpfr_inits2 (64, u, v, zz, (mpfr_ptr) 0);
     327    mpfr_init2 (z, 32);
     328    mpfr_set_str_binary (u, "0.10011000010011001110000100010001110010010000111001111110011");
     329    mpfr_set_str_binary (v, "0.1011110111110101011111011101100100110110111100011000000110011111");
     330    /* u + v = 1.0101011001000010010111101110101011111111111111111111111111111111 */
     331    inex = mpfr_add (zz, u, v, MPFR_RNDN);
     332    MPFR_ASSERTN(inex > 0);
     333    mpfr_set_str_binary (u, "1.01010110010000100101111011101011");
     334    MPFR_ASSERTN(mpfr_equal_p (zz, u));
     335    inex = mpfr_set_1_2 (z, zz, MPFR_RNDN, inex);
     336    /* we should have z = 1.0101011001000010010111101110101 and inex < 0 */
     337    MPFR_ASSERTN(inex < 0);
     338    mpfr_set_str_binary (u, "1.0101011001000010010111101110101");
     339    MPFR_ASSERTN(mpfr_equal_p (z, u));
     340    mpfr_clears (u, v, zz, z, (mpfr_ptr) 0);
     341  
     342    /* (64,128)-bit test:
     343     * take for v a random 128-bit number in [1/2,1),
     344       here v = 322263811942091240216761391118876232409/2^128
     345     * take for z a random 64-bit number in [1,2), less than 2*v,
     346       with last bit 0, here we take z = 16440347967874738276/2^63
     347     * take u = z-v-1/2^64-1/2^128 */
     348    mpfr_inits2 (128, u, v, zz, (mpfr_ptr) 0);
     349    mpfr_init2 (z, 64);
     350    mpfr_set_str_binary (u, "0.1101010111011101111100100001011111111000010011011001000101111010110101101101011011100110101001010001101011011110101101010010011");
     351    mpfr_set_str_binary (v, "0.11110010011100011100000010100110100010011010110010111111010011000010100100101001000110010101101011100101001000010100101011011001");
     352    inex = mpfr_add (zz, u, v, MPFR_RNDN);
     353    MPFR_ASSERTN(inex > 0);
     354    mpfr_set_str_binary (u, "1.1100100001001111101100101011111010000001111110100101000011000111");
     355    MPFR_ASSERTN(mpfr_equal_p (zz, u));
     356    inex = mpfr_set_1_2 (z, zz, MPFR_RNDN, inex);
     357    MPFR_ASSERTN(inex < 0);
     358    mpfr_set_str_binary (u, "1.1100100001001111101100101011111010000001111110100101000011000110");
     359    MPFR_ASSERTN(mpfr_equal_p (z, u));
     360    mpfr_clears (u, v, zz, z, (mpfr_ptr) 0);
     361  }
     362  
     363  #define TEST_FUNCTION mpfr_set
     364  #include "tgeneric.c"
     365  
     366  int
     367  main (void)
     368  {
     369    mpfr_t x, y, z, u;
     370    int inexact;
     371    mpfr_exp_t emax;
     372  
     373    tests_start_mpfr ();
     374  
     375    test_set_1_2 ();
     376  
     377    /* Default : no error */
     378    error = 0;
     379  
     380    /* check prototypes of mpfr_init_set_* */
     381    inexact = mpfr_init_set_si (x, -1, MPFR_RNDN);
     382    MPFR_ASSERTN (inexact == 0);
     383    inexact = mpfr_init_set (y, x, MPFR_RNDN);
     384    MPFR_ASSERTN (inexact == 0);
     385    inexact = mpfr_init_set_ui (z, 1, MPFR_RNDN);
     386    MPFR_ASSERTN (inexact == 0);
     387    inexact = mpfr_init_set_d (u, 1.0, MPFR_RNDN);
     388    MPFR_ASSERTN (inexact == 0);
     389  
     390    emax = mpfr_get_emax ();
     391    set_emax (0);
     392    mpfr_set_prec (x, 3);
     393    mpfr_set_str_binary (x, "0.111");
     394    mpfr_set_prec (y, 2);
     395    mpfr_set (y, x, MPFR_RNDU);
     396    if (!(MPFR_IS_INF (y) && MPFR_IS_POS (y)))
     397      {
     398        printf ("Error for y=x=0.111 with px=3, py=2 and emax=0\nx=");
     399        mpfr_dump (x);
     400        printf ("y=");
     401        mpfr_dump (y);
     402        exit (1);
     403      }
     404  
     405    set_emax (emax);
     406  
     407    mpfr_set_prec (y, 11);
     408    mpfr_set_str_binary (y, "0.11111111100E-8");
     409    mpfr_set_prec (x, 2);
     410    mpfr_set (x, y, MPFR_RNDN);
     411    mpfr_set_str_binary (y, "1.0E-8");
     412    if (mpfr_cmp (x, y))
     413      {
     414        printf ("Error for y=0.11111111100E-8, prec=2, rnd=MPFR_RNDN\n");
     415        exit (1);
     416      }
     417  
     418    mpfr_clear (x);
     419    mpfr_clear (y);
     420    mpfr_clear (z);
     421    mpfr_clear (u);
     422  
     423    check_ternary_value ();
     424    check_special ();
     425    check_neg_special ();
     426  
     427    test_generic (MPFR_PREC_MIN, 1000, 10);
     428  
     429    tests_end_mpfr ();
     430    return error;
     431  }