(root)/
mpfr-4.2.1/
tests/
tfms.c
       1  /* Test file for mpfr_fms.
       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  /* When a * b is exact, the FMS is equivalent to the separate operations. */
      26  static void
      27  test_exact (void)
      28  {
      29    const char *val[] =
      30      { "@NaN@", "-@Inf@", "-2", "-1", "-0", "0", "1", "2", "@Inf@" };
      31    int sv = numberof (val);
      32    int i, j, k;
      33    int rnd;
      34    mpfr_t a, b, c, r1, r2;
      35  
      36    mpfr_inits2 (8, a, b, c, r1, r2, (mpfr_ptr) 0);
      37  
      38    for (i = 0; i < sv; i++)
      39      for (j = 0; j < sv; j++)
      40        for (k = 0; k < sv; k++)
      41          RND_LOOP (rnd)
      42            {
      43              if (mpfr_set_str (a, val[i], 10, MPFR_RNDN) ||
      44                  mpfr_set_str (b, val[j], 10, MPFR_RNDN) ||
      45                  mpfr_set_str (c, val[k], 10, MPFR_RNDN) ||
      46                  mpfr_mul (r1, a, b, (mpfr_rnd_t) rnd) ||
      47                  mpfr_sub (r1, r1, c, (mpfr_rnd_t) rnd))
      48                {
      49                  if (rnd == MPFR_RNDF)
      50                    break;
      51                  printf ("test_exact internal error for (%d,%d,%d,%d,%s)\n",
      52                          i, j, k, rnd, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
      53                  exit (1);
      54                }
      55              if (mpfr_fms (r2, a, b, c, (mpfr_rnd_t) rnd))
      56                {
      57                  printf ("test_exact(%d,%d,%d,%d): mpfr_fms should be exact\n",
      58                          i, j, k, rnd);
      59                  exit (1);
      60                }
      61              if (MPFR_IS_NAN (r1))
      62                {
      63                  if (MPFR_IS_NAN (r2))
      64                    continue;
      65                  printf ("test_exact(%d,%d,%d,%d): mpfr_fms should be NaN\n",
      66                          i, j, k, rnd);
      67                  exit (1);
      68                }
      69              if (! mpfr_equal_p (r1, r2) || MPFR_SIGN (r1) != MPFR_SIGN (r2))
      70                {
      71                  printf ("test_exact(%d,%d,%d,%d):\nexpected ", i, j, k, rnd);
      72                  mpfr_out_str (stdout, 10, 0, r1, MPFR_RNDN);
      73                  printf ("\n     got ");
      74                  mpfr_out_str (stdout, 10, 0, r2, MPFR_RNDN);
      75                  printf ("\n");
      76                  exit (1);
      77                }
      78            }
      79  
      80    mpfr_clears (a, b, c, r1, r2, (mpfr_ptr) 0);
      81  }
      82  
      83  static void
      84  test_overflow1 (void)
      85  {
      86    mpfr_t x, y, z, r;
      87    int inex;
      88  
      89    mpfr_inits2 (8, x, y, z, r, (mpfr_ptr) 0);
      90    MPFR_SET_POS (x);
      91    mpfr_setmax (x, mpfr_get_emax ());  /* x = 2^emax - ulp */
      92    mpfr_set_ui (y, 2, MPFR_RNDN);       /* y = 2 */
      93    mpfr_set (z, x, MPFR_RNDN);          /* z = x = 2^emax - ulp */
      94    mpfr_clear_flags ();
      95    /* The intermediate multiplication x * y overflows, but x * y - z = x
      96       is representable. */
      97    inex = mpfr_fms (r, x, y, z, MPFR_RNDN);
      98    if (inex || ! mpfr_equal_p (r, x))
      99      {
     100        printf ("Error in test_overflow1\nexpected ");
     101        mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
     102        printf (" with inex = 0\n     got ");
     103        mpfr_out_str (stdout, 2, 0, r, MPFR_RNDN);
     104        printf (" with inex = %d\n", inex);
     105        exit (1);
     106      }
     107    if (mpfr_overflow_p ())
     108      {
     109        printf ("Error in test_overflow1: overflow flag set\n");
     110        exit (1);
     111      }
     112    mpfr_clears (x, y, z, r, (mpfr_ptr) 0);
     113  }
     114  
     115  static void
     116  test_overflow2 (void)
     117  {
     118    mpfr_t x, y, z, r;
     119    int i, inex, rnd, err = 0;
     120  
     121    mpfr_inits2 (8, x, y, z, r, (mpfr_ptr) 0);
     122  
     123    MPFR_SET_POS (x);
     124    mpfr_setmin (x, mpfr_get_emax ());  /* x = 0.1@emax */
     125    mpfr_set_si (y, -2, MPFR_RNDN);      /* y = -2 */
     126    /* The intermediate multiplication x * y will overflow. */
     127  
     128    for (i = -9; i <= 9; i++)
     129      RND_LOOP_NO_RNDF (rnd)
     130        {
     131          int inf, overflow;
     132  
     133          inf = rnd == MPFR_RNDN || rnd == MPFR_RNDD || rnd == MPFR_RNDA;
     134          overflow = inf || i <= 0;
     135  
     136          inex = mpfr_set_si_2exp (z, -i, mpfr_get_emin (), MPFR_RNDN);
     137          MPFR_ASSERTN (inex == 0);
     138  
     139          mpfr_clear_flags ();
     140          /* One has: x * y = -1@emax exactly (but not representable). */
     141          inex = mpfr_fms (r, x, y, z, (mpfr_rnd_t) rnd);
     142          if (overflow ^ (mpfr_overflow_p () != 0))
     143            {
     144              printf ("Error in test_overflow2 (i = %d, %s): wrong overflow"
     145                      " flag (should be %d)\n", i,
     146                      mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), overflow);
     147              err = 1;
     148            }
     149          if (mpfr_nanflag_p ())
     150            {
     151              printf ("Error in test_overflow2 (i = %d, %s): NaN flag should"
     152                      " not be set\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     153              err = 1;
     154            }
     155          if (mpfr_nan_p (r))
     156            {
     157              printf ("Error in test_overflow2 (i = %d, %s): got NaN\n",
     158                      i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     159              err = 1;
     160            }
     161          else if (MPFR_IS_POS (r))
     162            {
     163              printf ("Error in test_overflow2 (i = %d, %s): wrong sign "
     164                      "(+ instead of -)\n", i,
     165                      mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     166              err = 1;
     167            }
     168          else if (inf && ! mpfr_inf_p (r))
     169            {
     170              printf ("Error in test_overflow2 (i = %d, %s): expected -Inf,"
     171                      " got\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     172              mpfr_dump (r);
     173              err = 1;
     174            }
     175          else if (!inf && (mpfr_inf_p (r) ||
     176                            (mpfr_nextbelow (r), ! mpfr_inf_p (r))))
     177            {
     178              printf ("Error in test_overflow2 (i = %d, %s): expected -MAX,"
     179                      " got\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     180              mpfr_dump (r);
     181              err = 1;
     182            }
     183          if (inf ? inex >= 0 : inex <= 0)
     184            {
     185              printf ("Error in test_overflow2 (i = %d, %s): wrong inexact"
     186                      " flag (got %d)\n", i,
     187                      mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), inex);
     188              err = 1;
     189            }
     190  
     191        }
     192  
     193    if (err)
     194      exit (1);
     195    mpfr_clears (x, y, z, r, (mpfr_ptr) 0);
     196  }
     197  
     198  static void
     199  test_underflow1 (void)
     200  {
     201    mpfr_t x, y, z, r;
     202    int inex, signy, signz, rnd, err = 0;
     203  
     204    mpfr_inits2 (8, x, y, z, r, (mpfr_ptr) 0);
     205  
     206    MPFR_SET_POS (x);
     207    mpfr_setmin (x, mpfr_get_emin ());  /* x = 0.1@emin */
     208  
     209    for (signy = -1; signy <= 1; signy += 2)
     210      {
     211        mpfr_set_si_2exp (y, signy, -1, MPFR_RNDN);  /* |y| = 1/2 */
     212        for (signz = -3; signz <= 3; signz += 2)
     213          {
     214            RND_LOOP (rnd)
     215              {
     216                mpfr_set_si (z, signz, MPFR_RNDN);
     217                if (ABS (signz) != 1)
     218                  mpfr_setmax (z, mpfr_get_emax ());
     219                /* |z| = 1 or 2^emax - ulp */
     220                mpfr_clear_flags ();
     221                inex = mpfr_fms (r, x, y, z, (mpfr_rnd_t) rnd);
     222  #define STRTU1 "Error in test_underflow1 (signy = %d, signz = %d, %s)\n  "
     223                if (mpfr_nanflag_p ())
     224                  {
     225                    printf (STRTU1 "NaN flag is set\n", signy, signz,
     226                            mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     227                    err = 1;
     228                  }
     229                mpfr_neg (z, z, MPFR_RNDN);
     230                if (signy < 0 && MPFR_IS_LIKE_RNDD(rnd, -signz))
     231                  mpfr_nextbelow (z);
     232                if (signy > 0 && MPFR_IS_LIKE_RNDU(rnd, -signz))
     233                  mpfr_nextabove (z);
     234                if ((mpfr_overflow_p () != 0) ^ (mpfr_inf_p (z) != 0))
     235                  {
     236                    printf (STRTU1 "wrong overflow flag\n", signy, signz,
     237                            mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     238                    err = 1;
     239                  }
     240                if (mpfr_underflow_p ())
     241                  {
     242                    printf (STRTU1 "underflow flag is set\n", signy, signz,
     243                            mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     244                    err = 1;
     245                  }
     246                if (! mpfr_equal_p (r, z))
     247                  {
     248                    printf (STRTU1 "got        ", signy, signz,
     249                            mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
     250                    mpfr_dump (r);
     251                    printf ("  instead of ");
     252                    mpfr_dump (z);
     253                    err = 1;
     254                  }
     255                if (inex >= 0 && (rnd == MPFR_RNDD ||
     256                                  (rnd == MPFR_RNDZ && signz < 0) ||
     257                                  (rnd == MPFR_RNDN && signy > 0)))
     258                  {
     259                    printf (STRTU1 "ternary value = %d instead of < 0\n",
     260                            signy, signz, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
     261                            inex);
     262                    err = 1;
     263                  }
     264                if (inex <= 0 && (rnd == MPFR_RNDU ||
     265                                  (rnd == MPFR_RNDZ && signz > 0) ||
     266                                  (rnd == MPFR_RNDN && signy < 0)))
     267                  {
     268                    printf (STRTU1 "ternary value = %d instead of > 0\n",
     269                            signy, signz, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
     270                            inex);
     271                    err = 1;
     272                  }
     273              }
     274          }
     275      }
     276  
     277    if (err)
     278      exit (1);
     279    mpfr_clears (x, y, z, r, (mpfr_ptr) 0);
     280  }
     281  
     282  static void
     283  test_underflow2 (void)
     284  {
     285    mpfr_t x, y, z, r;
     286    int b, i, inex, same, err = 0;
     287  
     288    mpfr_inits2 (32, x, y, z, r, (mpfr_ptr) 0);
     289  
     290    mpfr_set_si_2exp (z, -1, mpfr_get_emin (), MPFR_RNDN);  /* z = -2^emin */
     291    mpfr_set_si_2exp (x, 1, mpfr_get_emin (), MPFR_RNDN);   /* x = 2^emin */
     292  
     293    for (b = 0; b <= 1; b++)
     294      {
     295        for (i = 15; i <= 17; i++)
     296          {
     297            mpfr_set_si_2exp (y, i, -4 - MPFR_PREC (z), MPFR_RNDN);
     298            /*  z = -1.000...00b
     299             * xy =             01111
     300             *   or             10000
     301             *   or             10001
     302             */
     303            mpfr_clear_flags ();
     304            inex = mpfr_fms (r, x, y, z, MPFR_RNDN);
     305  #define STRTU2 "Error in test_underflow2 (b = %d, i = %d)\n  "
     306            if (__gmpfr_flags != MPFR_FLAGS_INEXACT)
     307              {
     308                printf (STRTU2 "flags = %u instead of %u\n", b, i,
     309                        (unsigned int) __gmpfr_flags,
     310                        (unsigned int) MPFR_FLAGS_INEXACT);
     311                err = 1;
     312              }
     313            same = i == 15 || (i == 16 && b == 0);
     314            if (same ? (inex >= 0) : (inex <= 0))
     315              {
     316                printf (STRTU2 "incorrect ternary value (%d instead of %c 0)\n",
     317                        b, i, inex, same ? '<' : '>');
     318                err = 1;
     319              }
     320            mpfr_neg (y, z, MPFR_RNDN);
     321            if (!same)
     322              mpfr_nextabove (y);
     323            if (! mpfr_equal_p (r, y))
     324              {
     325                printf (STRTU2 "expected ", b, i);
     326                mpfr_dump (y);
     327                printf ("  got      ");
     328                mpfr_dump (r);
     329                err = 1;
     330              }
     331          }
     332        mpfr_nextbelow (z);
     333      }
     334  
     335    if (err)
     336      exit (1);
     337    mpfr_clears (x, y, z, r, (mpfr_ptr) 0);
     338  }
     339  
     340  int
     341  main (int argc, char *argv[])
     342  {
     343    mpfr_t x, y, z, s;
     344    MPFR_SAVE_EXPO_DECL (expo);
     345  
     346    tests_start_mpfr ();
     347  
     348    mpfr_init (x);
     349    mpfr_init (s);
     350    mpfr_init (y);
     351    mpfr_init (z);
     352  
     353    /* check special cases */
     354    mpfr_set_prec (x, 2);
     355    mpfr_set_prec (y, 2);
     356    mpfr_set_prec (z, 2);
     357    mpfr_set_prec (s, 2);
     358    mpfr_set_str (x, "-0.75", 10, MPFR_RNDN);
     359    mpfr_set_str (y, "0.5", 10, MPFR_RNDN);
     360    mpfr_set_str (z, "-0.375", 10, MPFR_RNDN);
     361    mpfr_fms (s, x, y, z, MPFR_RNDU); /* result is 0 */
     362    if (mpfr_cmp_ui (s, 0))
     363      {
     364        printf ("Error: -0.75 * 0.5 - -0.375 should be equal to 0 for prec=2\n");
     365        printf ("got instead ");
     366        mpfr_dump (s);
     367        exit (1);
     368      }
     369  
     370    mpfr_set_prec (x, 27);
     371    mpfr_set_prec (y, 27);
     372    mpfr_set_prec (z, 27);
     373    mpfr_set_prec (s, 27);
     374    mpfr_set_str_binary (x, "1.11111111111111111111111111e-1");
     375    mpfr_set (y, x, MPFR_RNDN);
     376    mpfr_set_str_binary (z, "1.00011110100011001011001001e-1");
     377    if (mpfr_fms (s, x, y, z, MPFR_RNDN) >= 0)
     378      {
     379        printf ("Wrong inexact flag for x=y=1-2^(-27)\n");
     380        exit (1);
     381      }
     382  
     383    mpfr_set_nan (x);
     384    mpfr_urandomb (y, RANDS);
     385    mpfr_urandomb (z, RANDS);
     386    mpfr_fms (s, x, y, z, MPFR_RNDN);
     387    if (!mpfr_nan_p (s))
     388      {
     389        printf ("evaluation of function in x=NAN does not return NAN\n");
     390        exit (1);
     391      }
     392  
     393    mpfr_set_nan (y);
     394    mpfr_urandomb (x, RANDS);
     395    mpfr_urandomb (z, RANDS);
     396    mpfr_fms (s, x, y, z, MPFR_RNDN);
     397    if (!mpfr_nan_p(s))
     398      {
     399        printf ("evaluation of function in y=NAN does not return NAN\n");
     400        exit (1);
     401      }
     402  
     403    mpfr_set_nan (z);
     404    mpfr_urandomb (y, RANDS);
     405    mpfr_urandomb (x, RANDS);
     406    mpfr_fms (s, x, y, z, MPFR_RNDN);
     407    if (!mpfr_nan_p (s))
     408      {
     409        printf ("evaluation of function in z=NAN does not return NAN\n");
     410        exit (1);
     411      }
     412  
     413    mpfr_set_inf (x, 1);
     414    mpfr_set_inf (y, 1);
     415    mpfr_set_inf (z, -1);
     416    mpfr_fms (s, x, y, z, MPFR_RNDN);
     417    if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0)
     418      {
     419        printf ("Error for (+inf) * (+inf) - (-inf)\n");
     420        exit (1);
     421      }
     422  
     423    mpfr_set_inf (x, -1);
     424    mpfr_set_inf (y, -1);
     425    mpfr_set_inf (z, -1);
     426    mpfr_fms (s, x, y, z, MPFR_RNDN);
     427    if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0)
     428      {
     429        printf ("Error for (-inf) * (-inf) - (-inf)\n");
     430        exit (1);
     431      }
     432  
     433    mpfr_set_inf (x, 1);
     434    mpfr_set_inf (y, -1);
     435    mpfr_set_inf (z, 1);
     436    mpfr_fms (s, x, y, z, MPFR_RNDN);
     437    if (!mpfr_inf_p (s) || mpfr_sgn (s) > 0)
     438      {
     439        printf ("Error for (+inf) * (-inf) - (+inf)\n");
     440        exit (1);
     441      }
     442  
     443    mpfr_set_inf (x, -1);
     444    mpfr_set_inf (y, 1);
     445    mpfr_set_inf (z, 1);
     446    mpfr_fms (s, x, y, z, MPFR_RNDN);
     447    if (!mpfr_inf_p (s) || mpfr_sgn (s) > 0)
     448      {
     449        printf ("Error for (-inf) * (+inf) - (+inf)\n");
     450        exit (1);
     451      }
     452  
     453    mpfr_set_inf (x, 1);
     454    mpfr_set_ui (y, 0, MPFR_RNDN);
     455    mpfr_urandomb (z, RANDS);
     456    mpfr_fms (s, x, y, z, MPFR_RNDN);
     457    if (!mpfr_nan_p (s))
     458      {
     459        printf ("evaluation of function in x=INF y=0  does not return NAN\n");
     460        exit (1);
     461      }
     462  
     463    mpfr_set_inf (y, 1);
     464    mpfr_set_ui (x, 0, MPFR_RNDN);
     465    mpfr_urandomb (z, RANDS);
     466    mpfr_fms (s, x, y, z, MPFR_RNDN);
     467    if (!mpfr_nan_p (s))
     468      {
     469        printf ("evaluation of function in x=0 y=INF does not return NAN\n");
     470        exit (1);
     471      }
     472  
     473    mpfr_set_inf (x, 1);
     474    mpfr_urandomb (y, RANDS); /* always positive */
     475    mpfr_set_inf (z, 1);
     476    mpfr_fms (s, x, y, z, MPFR_RNDN);
     477    if (!mpfr_nan_p (s))
     478      {
     479        printf ("evaluation of function in x=INF y>0 z=INF does not return NAN\n");
     480        exit (1);
     481      }
     482  
     483    mpfr_set_inf (y, 1);
     484    mpfr_urandomb (x, RANDS);
     485    mpfr_set_inf (z, 1);
     486    mpfr_fms (s, x, y, z, MPFR_RNDN);
     487    if (!mpfr_nan_p (s))
     488      {
     489        printf ("evaluation of function in x>0 y=INF z=INF does not return NAN\n");
     490        exit (1);
     491      }
     492  
     493    mpfr_set_inf (x, 1);
     494    do mpfr_urandomb (y, RANDS); while (MPFR_IS_ZERO(y));
     495    mpfr_urandomb (z, RANDS);
     496    mpfr_fms (s, x, y, z, MPFR_RNDN);
     497    if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0)
     498      {
     499        printf ("evaluation of function at x=INF does not return INF\n");
     500        exit (1);
     501      }
     502  
     503    mpfr_set_inf (y, 1);
     504    do mpfr_urandomb (x, RANDS); while (MPFR_IS_ZERO(x));
     505    mpfr_urandomb (z, RANDS);
     506    mpfr_fms (s, x, y, z, MPFR_RNDN);
     507    if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0)
     508      {
     509        printf ("evaluation of function at y=INF does not return INF\n");
     510        exit (1);
     511      }
     512  
     513    mpfr_set_inf (z, -1);
     514    mpfr_urandomb (x, RANDS);
     515    mpfr_urandomb (y, RANDS);
     516    mpfr_fms (s, x, y, z, MPFR_RNDN);
     517    if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0)
     518      {
     519        printf ("evaluation of function in z=-INF does not return INF\n");
     520        exit (1);
     521      }
     522  
     523    mpfr_set_ui (x, 0, MPFR_RNDN);
     524    mpfr_urandomb (y, RANDS);
     525    mpfr_urandomb (z, RANDS);
     526    mpfr_fms (s, x, y, z, MPFR_RNDN);
     527    mpfr_neg (z, z, MPFR_RNDN);
     528    if (! mpfr_equal_p (s, z))
     529      {
     530        printf ("evaluation of function in x=0 does not return -z\n");
     531        exit (1);
     532      }
     533  
     534    mpfr_set_ui (y, 0, MPFR_RNDN);
     535    mpfr_urandomb (x, RANDS);
     536    mpfr_urandomb (z, RANDS);
     537    mpfr_fms (s, x, y, z, MPFR_RNDN);
     538    mpfr_neg (z, z, MPFR_RNDN);
     539    if (! mpfr_equal_p (s, z))
     540      {
     541        printf ("evaluation of function in y=0 does not return -z\n");
     542        exit (1);
     543      }
     544  
     545    {
     546      mpfr_prec_t prec;
     547      mpfr_t t, slong;
     548      mpfr_rnd_t rnd;
     549      int inexact, compare;
     550      unsigned int n;
     551  
     552      mpfr_prec_t p0 = 2, p1 = 200;
     553      unsigned int N = 200;
     554  
     555      mpfr_init (t);
     556      mpfr_init (slong);
     557  
     558      /* generic test */
     559      for (prec = p0; prec <= p1; prec++)
     560        {
     561          mpfr_set_prec (x, prec);
     562          mpfr_set_prec (y, prec);
     563          mpfr_set_prec (z, prec);
     564          mpfr_set_prec (s, prec);
     565          mpfr_set_prec (t, prec);
     566  
     567          for (n = 0; n < N; n++)
     568            {
     569              mpfr_urandomb (x, RANDS);
     570              mpfr_urandomb (y, RANDS);
     571              mpfr_urandomb (z, RANDS);
     572  
     573              if (RAND_BOOL ())
     574                mpfr_neg (x, x, MPFR_RNDN);
     575              if (RAND_BOOL ())
     576                mpfr_neg (y, y, MPFR_RNDN);
     577              if (RAND_BOOL ())
     578                mpfr_neg (z, z, MPFR_RNDN);
     579  
     580              rnd = RND_RAND_NO_RNDF ();
     581              mpfr_set_prec (slong, 2 * prec);
     582              if (mpfr_mul (slong, x, y, rnd))
     583                {
     584                  printf ("x*y should be exact\n");
     585                  exit (1);
     586                }
     587              compare = mpfr_sub (t, slong, z, rnd);
     588              inexact = mpfr_fms (s, x, y, z, rnd);
     589              if (! mpfr_equal_p (s, t))
     590                {
     591                  printf ("results differ for\n");
     592                  printf ("  x=");
     593                  mpfr_dump (x);
     594                  printf ("  y=");
     595                  mpfr_dump (y);
     596                  printf ("  z=");
     597                  mpfr_dump (z);
     598                  printf ("  with prec=%u rnd_mode=%s\n", (unsigned int) prec,
     599                          mpfr_print_rnd_mode (rnd));
     600                  printf ("got      ");
     601                  mpfr_dump (s);
     602                  printf ("expected ");
     603                  mpfr_dump (t);
     604                  printf ("approx   ");
     605                  mpfr_dump (slong);
     606                  exit (1);
     607                }
     608              if (! SAME_SIGN (inexact, compare))
     609                {
     610                  printf ("Wrong inexact flag for rnd=%s: expected %d, got %d\n",
     611                          mpfr_print_rnd_mode (rnd), compare, inexact);
     612                  printf (" x="); mpfr_dump (x);
     613                  printf (" y="); mpfr_dump (y);
     614                  printf (" z="); mpfr_dump (z);
     615                  printf (" s="); mpfr_dump (s);
     616                  exit (1);
     617                }
     618            }
     619        }
     620      mpfr_clear (t);
     621      mpfr_clear (slong);
     622  
     623    }
     624    mpfr_clear (x);
     625    mpfr_clear (y);
     626    mpfr_clear (z);
     627    mpfr_clear (s);
     628  
     629    test_exact ();
     630  
     631    MPFR_SAVE_EXPO_MARK (expo);
     632    test_overflow1 ();
     633    test_overflow2 ();
     634    test_underflow1 ();
     635    test_underflow2 ();
     636    MPFR_SAVE_EXPO_FREE (expo);
     637  
     638    tests_end_mpfr ();
     639    return 0;
     640  }