示例#1
0
文件: tadd.c 项目: SESA/EbbRT-mpfr
static void
check_overflow (void)
{
  mpfr_t a, b, c;
  mpfr_prec_t prec_a;
  int r;

  mpfr_init2 (a, 256);
  mpfr_init2 (b, 256);
  mpfr_init2 (c, 256);

  mpfr_set_ui (b, 1, MPFR_RNDN);
  mpfr_setmax (b, mpfr_get_emax ());
  mpfr_set_ui (c, 1, MPFR_RNDN);
  mpfr_set_exp (c, mpfr_get_emax () - 192);
  RND_LOOP(r)
    for (prec_a = 128; prec_a < 512; prec_a += 64)
      {
        mpfr_set_prec (a, prec_a);
        mpfr_clear_overflow ();
        test_add (a, b, c, (mpfr_rnd_t) r);
        if (!mpfr_overflow_p ())
          {
            printf ("No overflow in check_overflow\n");
            exit (1);
          }
      }

  mpfr_set_exp (c, mpfr_get_emax () - 512);
  mpfr_set_prec (a, 256);
  mpfr_clear_overflow ();
  test_add (a, b, c, MPFR_RNDU);
  if (!mpfr_overflow_p ())
    {
      printf ("No overflow in check_overflow\n");
      exit (1);
    }

  mpfr_clear (a);
  mpfr_clear (b);
  mpfr_clear (c);
}
示例#2
0
int
mpfr_overflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign)
{
  int inex;

  MPFR_ASSERT_SIGN(sign);
  if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0))
    {
      mpfr_setmax (x, __gmpfr_emax);
      inex = -1;
    }
  else
    {
      MPFR_SET_INF(x);
      inex = 1;
    }
  MPFR_SET_SIGN(x,sign);
  __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW;
  return sign > 0 ? inex : -inex;
}
示例#3
0
int
mpfr_overflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign)
{
  int inex;

  MPFR_ASSERT_SIGN(sign);
  MPFR_CLEAR_FLAGS(x);
  if (rnd_mode == GMP_RNDN
      || MPFR_IS_RNDUTEST_OR_RNDDNOTTEST(rnd_mode, sign > 0))
    {
      MPFR_SET_INF(x);
      inex = 1;
    }
  else
    {
      mpfr_setmax (x, __gmpfr_emax);
      inex = -1;
    }
  MPFR_SET_SIGN(x,sign);
  __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW;
  return sign > 0 ? inex : -inex;
}
示例#4
0
文件: tsum.c 项目: BrianGladman/mpfr
/* TODO: A test with more inputs (but can't be compared to mpfr_add). */
static void
check_extreme (void)
{
  mpfr_t u, v, w, x, y;
  mpfr_ptr t[2];
  int i, inex1, inex2, r;

  t[0] = u;
  t[1] = v;

  mpfr_inits2 (32, u, v, w, x, y, (mpfr_ptr) 0);
  mpfr_setmin (u, mpfr_get_emax ());
  mpfr_setmax (v, mpfr_get_emin ());
  mpfr_setmin (w, mpfr_get_emax () - 40);
  RND_LOOP (r)
    for (i = 0; i < 2; i++)
      {
        mpfr_set_prec (x, 64);
        inex1 = mpfr_add (x, u, w, MPFR_RNDN);
        MPFR_ASSERTN (inex1 == 0);
        inex1 = mpfr_prec_round (x, 32, (mpfr_rnd_t) r);
        inex2 = mpfr_sum (y, t, 2, (mpfr_rnd_t) r);
        if (!(mpfr_equal_p (x, y) && SAME_SIGN (inex1, inex2)))
          {
            printf ("Error in check_extreme (%s, i = %d)\n",
                    mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
            printf ("Expected ");
            mpfr_dump (x);
            printf ("with inex = %d\n", inex1);
            printf ("Got      ");
            mpfr_dump (y);
            printf ("with inex = %d\n", inex2);
            exit (1);
          }
        mpfr_neg (v, v, MPFR_RNDN);
        mpfr_neg (w, w, MPFR_RNDN);
      }
  mpfr_clears (u, v, w, x, y, (mpfr_ptr) 0);
}
示例#5
0
文件: thypot.c 项目: Kirija/XPIR
static void
check_overflow (void)
{
  mpfr_t x, y;
  int inex, r;

  mpfr_inits2 (8, x, y, (mpfr_ptr) 0);
  mpfr_set_ui (x, 1, MPFR_RNDN);
  mpfr_setmax (x, mpfr_get_emax ());

  RND_LOOP(r)
    {
      mpfr_clear_overflow ();
      inex = mpfr_hypot (y, x, x, (mpfr_rnd_t) r);
      if (!mpfr_overflow_p ())
        {
          printf ("No overflow in check_overflow for %s%s\n",
                  mpfr_print_rnd_mode ((mpfr_rnd_t) r),
                  ext ? ", extended exponent range" : "");
          exit (1);
        }
      MPFR_ASSERTN (MPFR_IS_POS (y));
      if (r == MPFR_RNDZ || r == MPFR_RNDD)
        {
          MPFR_ASSERTN (inex < 0);
          MPFR_ASSERTN (!mpfr_inf_p (y));
          mpfr_nexttoinf (y);
        }
      else
        {
          MPFR_ASSERTN (inex > 0);
        }
      MPFR_ASSERTN (mpfr_inf_p (y));
    }

  mpfr_clears (x, y, (mpfr_ptr) 0);
}
示例#6
0
static int
my_setstr (mpfr_ptr t, const char *s)
{
  if (strcmp (s, "min") == 0)
    {
      mpfr_setmin (t, mpfr_get_emin ());
      MPFR_SET_POS (t);
      return 0;
    }
  if (strcmp (s, "min+") == 0)
    {
      mpfr_setmin (t, mpfr_get_emin ());
      MPFR_SET_POS (t);
      mpfr_nextabove (t);
      return 0;
    }
  if (strcmp (s, "max") == 0)
    {
      mpfr_setmax (t, mpfr_get_emax ());
      MPFR_SET_POS (t);
      return 0;
    }
  return mpfr_set_str (t, s, 10, MPFR_RNDN);
}
int
mpfr_exp (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  mpfr_exp_t expx;
  mpfr_prec_t precy;
  int inexact;
  MPFR_SAVE_EXPO_DECL (expo);

  MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
                 ("y[%#R]=%R inexact=%d", y, y, inexact));

  if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(x) ))
    {
      if (MPFR_IS_NAN(x))
        {
          MPFR_SET_NAN(y);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF(x))
        {
          if (MPFR_IS_POS(x))
            MPFR_SET_INF(y);
          else
            MPFR_SET_ZERO(y);
          MPFR_SET_POS(y);
          MPFR_RET(0);
        }
      else
        {
          MPFR_ASSERTD(MPFR_IS_ZERO(x));
          return mpfr_set_ui (y, 1, rnd_mode);
        }
    }

  /* First, let's detect most overflow and underflow cases. */
  {
    mpfr_t e, bound;

    /* We must extended the exponent range and save the flags now. */
    MPFR_SAVE_EXPO_MARK (expo);

    mpfr_init2 (e, sizeof (mpfr_exp_t) * CHAR_BIT);
    mpfr_init2 (bound, 32);

    inexact = mpfr_set_exp_t (e, expo.saved_emax, MPFR_RNDN);
    MPFR_ASSERTD (inexact == 0);
    mpfr_const_log2 (bound, expo.saved_emax < 0 ? MPFR_RNDD : MPFR_RNDU);
    mpfr_mul (bound, bound, e, MPFR_RNDU);
    if (MPFR_UNLIKELY (mpfr_cmp (x, bound) >= 0))
      {
        /* x > log(2^emax), thus exp(x) > 2^emax */
        mpfr_clears (e, bound, (mpfr_ptr) 0);
        MPFR_SAVE_EXPO_FREE (expo);
        return mpfr_overflow (y, rnd_mode, 1);
      }

    inexact = mpfr_set_exp_t (e, expo.saved_emin, MPFR_RNDN);
    MPFR_ASSERTD (inexact == 0);
    inexact = mpfr_sub_ui (e, e, 2, MPFR_RNDN);
    MPFR_ASSERTD (inexact == 0);
    mpfr_const_log2 (bound, expo.saved_emin < 0 ? MPFR_RNDU : MPFR_RNDD);
    mpfr_mul (bound, bound, e, MPFR_RNDD);
    if (MPFR_UNLIKELY (mpfr_cmp (x, bound) <= 0))
      {
        /* x < log(2^(emin - 2)), thus exp(x) < 2^(emin - 2) */
        mpfr_clears (e, bound, (mpfr_ptr) 0);
        MPFR_SAVE_EXPO_FREE (expo);
        return mpfr_underflow (y, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode,
                               1);
      }

    /* Other overflow/underflow cases must be detected
       by the generic routines. */
    mpfr_clears (e, bound, (mpfr_ptr) 0);
    MPFR_SAVE_EXPO_FREE (expo);
  }

  expx  = MPFR_GET_EXP (x);
  precy = MPFR_PREC (y);

  /* if x < 2^(-precy), then exp(x) i.e. gives 1 +/- 1 ulp(1) */
  if (MPFR_UNLIKELY (expx < 0 && (mpfr_uexp_t) (-expx) > precy))
    {
      mpfr_exp_t emin = __gmpfr_emin;
      mpfr_exp_t emax = __gmpfr_emax;
      int signx = MPFR_SIGN (x);

      MPFR_SET_POS (y);
      if (MPFR_IS_NEG_SIGN (signx) && (rnd_mode == MPFR_RNDD ||
                                       rnd_mode == MPFR_RNDZ))
        {
          __gmpfr_emin = 0;
          __gmpfr_emax = 0;
          mpfr_setmax (y, 0);  /* y = 1 - epsilon */
          inexact = -1;
        }
      else
        {
          __gmpfr_emin = 1;
          __gmpfr_emax = 1;
          mpfr_setmin (y, 1);  /* y = 1 */
          if (MPFR_IS_POS_SIGN (signx) && (rnd_mode == MPFR_RNDU ||
                                           rnd_mode == MPFR_RNDA))
            {
              mp_size_t yn;
              int sh;

              yn = 1 + (MPFR_PREC(y) - 1) / GMP_NUMB_BITS;
              sh = (mpfr_prec_t) yn * GMP_NUMB_BITS - MPFR_PREC(y);
              MPFR_MANT(y)[0] += MPFR_LIMB_ONE << sh;
              inexact = 1;
            }
          else
            inexact = -MPFR_FROM_SIGN_TO_INT(signx);
        }

      __gmpfr_emin = emin;
      __gmpfr_emax = emax;
    }
  else  /* General case */
    {
      if (MPFR_UNLIKELY (precy >= MPFR_EXP_THRESHOLD))
        /* mpfr_exp_3 saves the exponent range and flags itself, otherwise
           the flag changes in mpfr_exp_3 are lost */
        inexact = mpfr_exp_3 (y, x, rnd_mode); /* O(M(n) log(n)^2) */
      else
        {
          MPFR_SAVE_EXPO_MARK (expo);
          inexact = mpfr_exp_2 (y, x, rnd_mode); /* O(n^(1/3) M(n)) */
          MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
          MPFR_SAVE_EXPO_FREE (expo);
        }
    }

  return mpfr_check_range (y, inexact, rnd_mode);
}
示例#8
0
文件: tfma.c 项目: mmanley/Antares
static void
test_underflow1 (void)
{
  mpfr_t x, y, z, r;
  int inex, signy, signz, rnd, err = 0;

  mpfr_inits2 (8, x, y, z, r, (void *) 0);

  MPFR_SET_POS (x);
  mpfr_setmin (x, mpfr_get_emin ());  /* x = 0.1@emin */

  for (signy = -1; signy <= 1; signy += 2)
    {
      mpfr_set_si_2exp (y, signy, -1, GMP_RNDN);  /* |y| = 1/2 */
      for (signz = -3; signz <= 3; signz += 2)
        {
          RND_LOOP (rnd)
            {
              mpfr_set_si (z, signz, GMP_RNDN);
              if (ABS (signz) != 1)
                mpfr_setmax (z, mpfr_get_emax ());
              /* |z| = 1 or 2^emax - ulp */
              mpfr_clear_flags ();
              inex = mpfr_fma (r, x, y, z, rnd);
#define ERRTU1 "Error in test_underflow1 (signy = %d, signz = %d, %s)\n  "
              if (mpfr_nanflag_p ())
                {
                  printf (ERRTU1 "NaN flag is set\n", signy, signz,
                          mpfr_print_rnd_mode (rnd));
                  err = 1;
                }
              if (signy < 0 && (rnd == GMP_RNDD ||
                                (rnd == GMP_RNDZ && signz > 0)))
                mpfr_nextbelow (z);
              if (signy > 0 && (rnd == GMP_RNDU ||
                                (rnd == GMP_RNDZ && signz < 0)))
                mpfr_nextabove (z);
              if ((mpfr_overflow_p () != 0) ^ (mpfr_inf_p (z) != 0))
                {
                  printf (ERRTU1 "wrong overflow flag\n", signy, signz,
                          mpfr_print_rnd_mode (rnd));
                  err = 1;
                }
              if (mpfr_underflow_p ())
                {
                  printf (ERRTU1 "underflow flag is set\n", signy, signz,
                          mpfr_print_rnd_mode (rnd));
                  err = 1;
                }
              if (! mpfr_equal_p (r, z))
                {
                  printf (ERRTU1 "got ", signy, signz,
                          mpfr_print_rnd_mode (rnd));
                  mpfr_print_binary (r);
                  printf (" instead of ");
                  mpfr_print_binary (z);
                  printf ("\n");
                  err = 1;
                }
              if (inex >= 0 && (rnd == GMP_RNDD ||
                                (rnd == GMP_RNDZ && signz > 0) ||
                                (rnd == GMP_RNDN && signy > 0)))
                {
                  printf (ERRTU1 "ternary value = %d instead of < 0\n",
                          signy, signz, mpfr_print_rnd_mode (rnd), inex);
                  err = 1;
                }
              if (inex <= 0 && (rnd == GMP_RNDU ||
                                (rnd == GMP_RNDZ && signz < 0) ||
                                (rnd == GMP_RNDN && signy < 0)))
                {
                  printf (ERRTU1 "ternary value = %d instead of > 0\n",
                          signy, signz, mpfr_print_rnd_mode (rnd), inex);
                  err = 1;
                }
            }
        }
    }

  if (err)
    exit (1);
  mpfr_clears (x, y, z, r, (void *) 0);
}
static void
check_diverse (void)
{
  mpfr_t x, y, z;
  int inexact;

  mpfr_init (x);
  mpfr_init (y);
  mpfr_init (z);

  /* check corner case cancel=0, but add_exp=1 */
  mpfr_set_prec (x, 2);
  mpfr_set_prec (y, 4);
  mpfr_set_prec (z, 2);
  mpfr_setmax (y, __gmpfr_emax);
  mpfr_set_str_binary (z, "0.1E-10"); /* tiny */
  test_sub (x, y, z, MPFR_RNDN); /* should round to 2^emax, i.e. overflow */
  if (!mpfr_inf_p (x) || mpfr_sgn (x) < 0)
    {
      printf ("Error in mpfr_sub(a,b,c,RNDN) for b=maxfloat, prec(a)<prec(b), c tiny\n");
      exit (1);
    }

  /* other coverage test */
  mpfr_set_prec (x, 2);
  mpfr_set_prec (y, 2);
  mpfr_set_prec (z, 2);
  mpfr_set_ui (y, 1, MPFR_RNDN);
  mpfr_set_si (z, -2, MPFR_RNDN);
  test_sub (x, y, z, MPFR_RNDD);
  if (mpfr_cmp_ui (x, 3))
    {
      printf ("Error in mpfr_sub(1,-2,RNDD)\n");
      exit (1);
    }

  mpfr_set_prec (x, 288);
  mpfr_set_prec (y, 288);
  mpfr_set_prec (z, 288);
  mpfr_set_str_binary (y, "0.111000110011000001000111101010111011110011101001101111111110000011100101000001001010110010101010011001010100000001110011110001010101101010001011101110100100001011110100110000101101100011010001001011011010101010000010001101001000110010010111111011110001111101001000101101001100101100101000E80");
  mpfr_set_str_binary (z, "0.100001111111101001011010001100110010100111001110000110011101001011010100001000000100111011010110110010000000000010101101011000010000110001110010100001100101011100100100001011000100011110000001010101000100011101001000010111100000111000111011001000100100011000100000010010111000000100100111E-258");
  inexact = test_sub (x, y, z, MPFR_RNDN);
  if (inexact <= 0)
    {
      printf ("Wrong inexact flag for prec=288\n");
      exit (1);
    }

  mpfr_set_prec (x, 32);
  mpfr_set_prec (y, 63);
  mpfr_set_prec (z, 63);
  mpfr_set_str_binary (x, "0.101101111011011100100100100111E31");
  mpfr_set_str_binary (y, "0.111110010010100100110101101010001001100101110001000101110111111E-1");
  test_sub (z, x, y, MPFR_RNDN);
  mpfr_set_str_binary (y, "0.1011011110110111001001001001101100000110110101101100101001011E31");
  if (mpfr_cmp (z, y))
    {
      printf ("Error in mpfr_sub (5)\n");
      printf ("expected "); mpfr_print_binary (y); puts ("");
      printf ("got      "); mpfr_print_binary (z); puts ("");
      exit (1);
    }

  mpfr_set_prec (y, 63);
  mpfr_set_prec (z, 63);
  mpfr_set_str_binary (y, "0.1011011110110111001001001001101100000110110101101100101001011E31");
  mpfr_sub_ui (z, y, 1541116494, MPFR_RNDN);
  mpfr_set_str_binary (y, "-0.11111001001010010011010110101E-1");
  if (mpfr_cmp (z, y))
    {
      printf ("Error in mpfr_sub (7)\n");
      printf ("expected "); mpfr_print_binary (y); puts ("");
      printf ("got      "); mpfr_print_binary (z); puts ("");
      exit (1);
    }

  mpfr_set_prec (y, 63);
  mpfr_set_prec (z, 63);
  mpfr_set_str_binary (y, "0.1011011110110111001001001001101100000110110101101100101001011E31");
  mpfr_sub_ui (z, y, 1541116494, MPFR_RNDN);
  mpfr_set_str_binary (y, "-0.11111001001010010011010110101E-1");
  if (mpfr_cmp (z, y))
    {
      printf ("Error in mpfr_sub (6)\n");
      printf ("expected "); mpfr_print_binary (y); puts ("");
      printf ("got      "); mpfr_print_binary (z); puts ("");
      exit (1);
    }

  mpfr_set_prec (x, 32);
  mpfr_set_prec (y, 32);
  mpfr_set_str_binary (x, "0.10110111101001110100100101111000E0");
  mpfr_set_str_binary (y, "0.10001100100101000100110111000100E0");
  if ((inexact = test_sub (x, x, y, MPFR_RNDN)))
    {
      printf ("Wrong inexact flag (2): got %d instead of 0\n", inexact);
      exit (1);
    }

  mpfr_set_prec (x, 32);
  mpfr_set_prec (y, 32);
  mpfr_set_str_binary (x, "0.11111000110111011000100111011010E0");
  mpfr_set_str_binary (y, "0.10011111101111000100001000000000E-3");
  if ((inexact = test_sub (x, x, y, MPFR_RNDN)))
    {
      printf ("Wrong inexact flag (1): got %d instead of 0\n", inexact);
      exit (1);
    }

  mpfr_set_prec (x, 33);
  mpfr_set_prec (y, 33);
  mpfr_set_ui (x, 1, MPFR_RNDN);
  mpfr_set_str_binary (y, "-0.1E-32");
  mpfr_add (x, x, y, MPFR_RNDN);
  mpfr_set_str_binary (y, "0.111111111111111111111111111111111E0");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in mpfr_sub (1 - 1E-33) with prec=33\n");
      printf ("Expected "); mpfr_print_binary (y); puts ("");
      printf ("got      "); mpfr_print_binary (x); puts ("");
      exit (1);
    }

  mpfr_set_prec (x, 32);
  mpfr_set_prec (y, 33);
  mpfr_set_ui (x, 1, MPFR_RNDN);
  mpfr_set_str_binary (y, "-0.1E-32");
  mpfr_add (x, x, y, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 1))
    {
      printf ("Error in mpfr_sub (1 - 1E-33) with prec=32\n");
      printf ("Expected 1.0, got "); mpfr_print_binary (x); puts ("");
      exit (1);
    }

  mpfr_set_prec (x, 65);
  mpfr_set_prec (y, 65);
  mpfr_set_prec (z, 64);
  mpfr_set_str_binary (x, "1.1110111011110001110111011111111111101000011001011100101100101101");
  mpfr_set_str_binary (y, "0.1110111011110001110111011111111111101000011001011100101100101100");
  test_sub (z, x, y, MPFR_RNDZ);
  if (mpfr_cmp_ui (z, 1))
    {
      printf ("Error in mpfr_sub (1)\n");
      exit (1);
    }
  test_sub (z, x, y, MPFR_RNDU);
  mpfr_set_str_binary (x, "1.000000000000000000000000000000000000000000000000000000000000001");
  if (mpfr_cmp (z, x))
    {
      printf ("Error in mpfr_sub (2)\n");
      printf ("Expected "); mpfr_print_binary (x); puts ("");
      printf ("Got      "); mpfr_print_binary (z); puts ("");
      exit (1);
    }
  mpfr_set_str_binary (x, "1.1110111011110001110111011111111111101000011001011100101100101101");
  test_sub (z, x, y, MPFR_RNDN);
  if (mpfr_cmp_ui (z, 1))
    {
      printf ("Error in mpfr_sub (3)\n");
      exit (1);
    }
  inexact = test_sub (z, x, y, MPFR_RNDA);
  mpfr_set_str_binary (x, "1.000000000000000000000000000000000000000000000000000000000000001");
  if (mpfr_cmp (z, x) || inexact <= 0)
    {
      printf ("Error in mpfr_sub (4)\n");
      exit (1);
    }
  mpfr_set_prec (x, 66);
  mpfr_set_str_binary (x, "1.11101110111100011101110111111111111010000110010111001011001010111");
  test_sub (z, x, y, MPFR_RNDN);
  if (mpfr_cmp_ui (z, 1))
    {
      printf ("Error in mpfr_sub (5)\n");
      exit (1);
    }

  /* check in-place operations */
  mpfr_set_ui (x, 1, MPFR_RNDN);
  test_sub (x, x, x, MPFR_RNDN);
  if (mpfr_cmp_ui(x, 0))
    {
      printf ("Error for mpfr_sub (x, x, x, MPFR_RNDN) with x=1.0\n");
      exit (1);
    }

  mpfr_set_prec (x, 53);
  mpfr_set_prec (y, 53);
  mpfr_set_prec (z, 53);
  mpfr_set_str1 (x, "1.229318102e+09");
  mpfr_set_str1 (y, "2.32221184180698677665e+05");
  test_sub (z, x, y, MPFR_RNDN);
  if (mpfr_cmp_str1 (z, "1229085880.815819263458251953125"))
    {
      printf ("Error in mpfr_sub (1.22e9 - 2.32e5)\n");
      printf ("expected 1229085880.815819263458251953125, got ");
      mpfr_out_str(stdout, 10, 0, z, MPFR_RNDN);
      putchar('\n');
      exit (1);
    }

  mpfr_set_prec (x, 112);
  mpfr_set_prec (y, 98);
  mpfr_set_prec (z, 54);
  mpfr_set_str_binary (x, "0.11111100100000000011000011100000101101010001000111E-401");
  mpfr_set_str_binary (y, "0.10110000100100000101101100011111111011101000111000101E-464");
  test_sub (z, x, y, MPFR_RNDN);
  if (mpfr_cmp (z, x)) {
    printf ("mpfr_sub(z, x, y) failed for prec(x)=112, prec(y)=98\n");
    printf ("expected "); mpfr_print_binary (x); puts ("");
    printf ("got      "); mpfr_print_binary (z); puts ("");
    exit (1);
  }

  mpfr_set_prec (x, 33);
  mpfr_set_ui (x, 1, MPFR_RNDN);
  mpfr_div_2exp (x, x, 32, MPFR_RNDN);
  mpfr_sub_ui (x, x, 1, MPFR_RNDN);

  mpfr_set_prec (x, 5);
  mpfr_set_prec (y, 5);
  mpfr_set_str_binary (x, "1e-12");
  mpfr_set_ui (y, 1, MPFR_RNDN);
  test_sub (x, y, x, MPFR_RNDD);
  mpfr_set_str_binary (y, "0.11111");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in mpfr_sub (x, y, x, MPFR_RNDD) for x=2^(-12), y=1\n");
      exit (1);
    }

  mpfr_set_prec (x, 24);
  mpfr_set_prec (y, 24);
  mpfr_set_str_binary (x, "-0.100010000000000000000000E19");
  mpfr_set_str_binary (y, "0.100000000000000000000100E15");
  mpfr_add (x, x, y, MPFR_RNDD);
  mpfr_set_str_binary (y, "-0.1E19");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in mpfr_add (2)\n");
      exit (1);
    }

  mpfr_set_prec (x, 2);
  mpfr_set_prec (y, 10);
  mpfr_set_prec (z, 10);
  mpfr_set_ui (y, 0, MPFR_RNDN);
  mpfr_set_str_binary (z, "0.10001");
  if (test_sub (x, y, z, MPFR_RNDN) <= 0)
    {
      printf ("Wrong inexact flag in x=mpfr_sub(0,z) for prec(z)>prec(x)\n");
      exit (1);
    }
  if (test_sub (x, z, y, MPFR_RNDN) >= 0)
    {
      printf ("Wrong inexact flag in x=mpfr_sub(z,0) for prec(z)>prec(x)\n");
      exit (1);
    }

  mpfr_clear (x);
  mpfr_clear (y);
  mpfr_clear (z);
}
示例#10
0
文件: tdiv.c 项目: cmjonze/mpfr
static void
test_extreme (void)
{
  mpfr_t x, y, z;
  mpfr_exp_t emin, emax;
  mpfr_prec_t p[4] = { 8, 32, 64, 256 };
  int xi, yi, zi, j, r;
  unsigned int flags, ex_flags;

  emin = mpfr_get_emin ();
  emax = mpfr_get_emax ();

  mpfr_set_emin (MPFR_EMIN_MIN);
  mpfr_set_emax (MPFR_EMAX_MAX);

  for (xi = 0; xi < 4; xi++)
    {
      mpfr_init2 (x, p[xi]);
      mpfr_setmax (x, MPFR_EMAX_MAX);
      MPFR_ASSERTN (mpfr_check (x));
      for (yi = 0; yi < 4; yi++)
        {
          mpfr_init2 (y, p[yi]);
          mpfr_setmin (y, MPFR_EMIN_MIN);
          for (j = 0; j < 2; j++)
            {
              MPFR_ASSERTN (mpfr_check (y));
              for (zi = 0; zi < 4; zi++)
                {
                  mpfr_init2 (z, p[zi]);
                  RND_LOOP (r)
                    {
                      mpfr_clear_flags ();
                      mpfr_div (z, x, y, (mpfr_rnd_t) r);
                      flags = __gmpfr_flags;
                      MPFR_ASSERTN (mpfr_check (z));
                      ex_flags = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT;
                      if (flags != ex_flags)
                        {
                          printf ("Bad flags in test_extreme on z = a/b"
                                  " with %s and\n",
                                  mpfr_print_rnd_mode ((mpfr_rnd_t) r));
                          printf ("a = ");
                          mpfr_dump (x);
                          printf ("b = ");
                          mpfr_dump (y);
                          printf ("Expected flags:");
                          flags_out (ex_flags);
                          printf ("Got flags:     ");
                          flags_out (flags);
                          printf ("z = ");
                          mpfr_dump (z);
                          exit (1);
                        }
                      mpfr_clear_flags ();
                      mpfr_div (z, y, x, (mpfr_rnd_t) r);
                      flags = __gmpfr_flags;
                      MPFR_ASSERTN (mpfr_check (z));
                      ex_flags = MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT;
                      if (flags != ex_flags)
                        {
                          printf ("Bad flags in test_extreme on z = a/b"
                                  " with %s and\n",
                                  mpfr_print_rnd_mode ((mpfr_rnd_t) r));
                          printf ("a = ");
                          mpfr_dump (y);
                          printf ("b = ");
                          mpfr_dump (x);
                          printf ("Expected flags:");
                          flags_out (ex_flags);
                          printf ("Got flags:     ");
                          flags_out (flags);
                          printf ("z = ");
                          mpfr_dump (z);
                          exit (1);
                        }
                    }
                  mpfr_clear (z);
                }  /* zi */
              mpfr_nextabove (y);
            }  /* j */
          mpfr_clear (y);
        }  /* yi */
      mpfr_clear (x);
    }  /* xi */

  set_emin (emin);
  set_emax (emax);
}
示例#11
0
static void
test_generic (mpfr_prec_t p0, mpfr_prec_t p1, unsigned int nmax)
{
  mpfr_prec_t prec, xprec, yprec;
  mpfr_t x, y, z, t, w;
#if defined(TWO_ARGS_ALL)
  mpfr_t u;
#endif
#if defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
  double d;
#endif
#if defined(ULONG_ARG1) || defined(ULONG_ARG2)
  unsigned long i;
#endif
  mpfr_rnd_t rnd;
  int inexact, compare, compare2;
  unsigned int n;
  unsigned long ctrt = 0, ctrn = 0;
  int test_of = 1, test_uf = 1;
  mpfr_exp_t old_emin, old_emax;

  old_emin = mpfr_get_emin ();
  old_emax = mpfr_get_emax ();

  mpfr_inits2 (MPFR_PREC_MIN, x, y, z, t, w, (mpfr_ptr) 0);
#if defined(TWO_ARGS_ALL)
  mpfr_init2 (u, MPFR_PREC_MIN);
#endif

  /* generic test */
  for (prec = p0; prec <= p1; prec++)
    {
      mpfr_set_prec (z, prec);
      mpfr_set_prec (t, prec);
      yprec = prec + 10;
      mpfr_set_prec (y, yprec);
      mpfr_set_prec (w, yprec);

      /* Note: in precision p1, we test 4 special cases. */
      for (n = 0; n < (prec == p1 ? nmax + 4 : nmax); n++)
        {
          int infinite_input = 0;
          unsigned int flags;
          mpfr_exp_t oemin, oemax;

          xprec = prec;
          if (randlimb () & 1)
            {
              xprec *= (double) randlimb () / MP_LIMB_T_MAX;
              if (xprec < MPFR_PREC_MIN)
                xprec = MPFR_PREC_MIN;
            }
          mpfr_set_prec (x, xprec);
#if defined(TWO_ARGS)
          mpfr_set_prec (u, xprec);
#elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
          mpfr_set_prec (u, IEEE_DBL_MANT_DIG);
#elif defined(ULONG_ARG1) || defined(ULONG_ARG2)
          mpfr_set_prec (u, sizeof (unsigned long) * CHAR_BIT);
#endif

          if (n > 3 || prec < p1)
            {
#if defined(RAND_FUNCTION)
              RAND_FUNCTION (x);
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
              RAND_FUNCTION (u);
#endif
#else  /* ! defined(RAND_FUNCTION) */
              tests_default_random (x, TEST_RANDOM_POS,
                                    TEST_RANDOM_EMIN, TEST_RANDOM_EMAX,
                                    TEST_RANDOM_ALWAYS_SCALE);
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
              tests_default_random (u, TEST_RANDOM_POS2,
                                    TEST_RANDOM_EMIN, TEST_RANDOM_EMAX,
                                    TEST_RANDOM_ALWAYS_SCALE);
#endif
#endif  /* ! defined(RAND_FUNCTION) */
            }
          else
            {
              /* Special cases tested in precision p1 if n <= 3. They are
                 useful really in the extended exponent range. */
#if (defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)) && defined(MPFR_ERRDIVZERO)
              goto next_n;
#endif
              set_emin (MPFR_EMIN_MIN);
              set_emax (MPFR_EMAX_MAX);
              if (n <= 1)
                {
                  mpfr_set_si (x, n == 0 ? 1 : -1, MPFR_RNDN);
                  mpfr_set_exp (x, mpfr_get_emin ());
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
                  mpfr_set_si (u, randlimb () % 2 == 0 ? 1 : -1, MPFR_RNDN);
                  mpfr_set_exp (u, mpfr_get_emin ());
#endif
                }
              else  /* 2 <= n <= 3 */
                {
                  if (getenv ("MPFR_CHECK_MAX") == NULL)
                    goto next_n;
                  mpfr_set_si (x, n == 0 ? 1 : -1, MPFR_RNDN);
                  mpfr_setmax (x, REDUCE_EMAX);
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
                  mpfr_set_si (u, randlimb () % 2 == 0 ? 1 : -1, MPFR_RNDN);
                  mpfr_setmax (u, mpfr_get_emax ());
#endif
                }
            }

#if defined(ULONG_ARG1) || defined(ULONG_ARG2)
          i = randlimb ();
          inexact = mpfr_set_ui (u, i, MPFR_RNDN);
          MPFR_ASSERTN (inexact == 0);
#endif

          /* Exponent range for the test. */
          oemin = mpfr_get_emin ();
          oemax = mpfr_get_emax ();

          rnd = RND_RAND ();
          mpfr_clear_flags ();
#ifdef DEBUG_TGENERIC
          TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (y));
#endif
#if defined(TWO_ARGS)
          compare = TEST_FUNCTION (y, x, u, rnd);
#elif defined(DOUBLE_ARG1)
          d = mpfr_get_d (u, rnd);
          compare = TEST_FUNCTION (y, d, x, rnd);
          /* d can be infinite due to overflow in mpfr_get_d */
          infinite_input |= DOUBLE_ISINF (d);
#elif defined(DOUBLE_ARG2)
          d = mpfr_get_d (u, rnd);
          compare = TEST_FUNCTION (y, x, d, rnd);
          /* d can be infinite due to overflow in mpfr_get_d */
          infinite_input |= DOUBLE_ISINF (d);
#elif defined(ULONG_ARG1)
          compare = TEST_FUNCTION (y, i, x, rnd);
#elif defined(ULONG_ARG2)
          compare = TEST_FUNCTION (y, x, i, rnd);
#else
          compare = TEST_FUNCTION (y, x, rnd);
#endif
          flags = __gmpfr_flags;
          if (mpfr_get_emin () != oemin ||
              mpfr_get_emax () != oemax)
            {
              printf ("tgeneric: the exponent range has been modified"
                      " by the tested function!\n");
              exit (1);
            }
          TGENERIC_CHECK ("bad inexact flag",
                          (compare != 0) ^ (mpfr_inexflag_p () == 0));
          ctrt++;

          /* Tests in a reduced exponent range. */
          {
            unsigned int oldflags = flags;
            mpfr_exp_t e, emin, emax;

            /* Determine the smallest exponent range containing the
               exponents of the mpfr_t inputs (x, and u if TWO_ARGS)
               and output (y). */
            emin = MPFR_EMAX_MAX;
            emax = MPFR_EMIN_MIN;
            if (MPFR_IS_PURE_FP (x))
              {
                e = MPFR_GET_EXP (x);
                if (e < emin)
                  emin = e;
                if (e > emax)
                  emax = e;
              }
#if defined(TWO_ARGS)
            if (MPFR_IS_PURE_FP (u))
              {
                e = MPFR_GET_EXP (u);
                if (e < emin)
                  emin = e;
                if (e > emax)
                  emax = e;
              }
#endif
            if (MPFR_IS_PURE_FP (y))
              {
                e = MPFR_GET_EXP (y);
                if (test_of && e - 1 >= emax)
                  {
                    unsigned int ex_flags;

                    mpfr_set_emax (e - 1);
                    mpfr_clear_flags ();
#if defined(TWO_ARGS)
                    inexact = TEST_FUNCTION (w, x, u, rnd);
#elif defined(DOUBLE_ARG1)
                    inexact = TEST_FUNCTION (w, d, x, rnd);
#elif defined(DOUBLE_ARG2)
                    inexact = TEST_FUNCTION (w, x, d, rnd);
#elif defined(ULONG_ARG1)
                    inexact = TEST_FUNCTION (w, i, x, rnd);
#elif defined(ULONG_ARG2)
                    inexact = TEST_FUNCTION (w, x, i, rnd);
#else
                    inexact = TEST_FUNCTION (w, x, rnd);
#endif
                    flags = __gmpfr_flags;
                    mpfr_set_emax (oemax);
                    ex_flags = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT;
                    if (flags != ex_flags)
                      {
                        printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION)
                                ", reduced exponent range [%"
                                MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC
                                "d] (overflow test) on:\n",
                                (mpfr_eexp_t) oemin, (mpfr_eexp_t) e - 1);
                        printf ("x = ");
                        mpfr_dump (x);
#if defined(TWO_ARGS_ALL)
                        printf ("u = ");
                        mpfr_dump (u);
#endif
                        printf ("yprec = %u, rnd_mode = %s\n",
                                (unsigned int) yprec,
                                mpfr_print_rnd_mode (rnd));
                        printf ("Expected flags =");
                        flags_out (ex_flags);
                        printf ("     got flags =");
                        flags_out (flags);
                        printf ("inex = %d, w = ", inexact);
                        mpfr_dump (w);
                        exit (1);
                      }
                    test_of = 0;  /* Overflow is tested only once. */
                  }
                if (test_uf && e + 1 <= emin)
                  {
                    unsigned int ex_flags;

                    mpfr_set_emin (e + 1);
                    mpfr_clear_flags ();
#if defined(TWO_ARGS)
                    inexact = TEST_FUNCTION (w, x, u, rnd);
#elif defined(DOUBLE_ARG1)
                    inexact = TEST_FUNCTION (w, d, x, rnd);
#elif defined(DOUBLE_ARG2)
                    inexact = TEST_FUNCTION (w, x, d, rnd);
#elif defined(ULONG_ARG1)
                    inexact = TEST_FUNCTION (w, i, x, rnd);
#elif defined(ULONG_ARG2)
                    inexact = TEST_FUNCTION (w, x, i, rnd);
#else
                    inexact = TEST_FUNCTION (w, x, rnd);
#endif
                    flags = __gmpfr_flags;
                    mpfr_set_emin (oemin);
                    ex_flags = MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT;
                    if (flags != ex_flags)
                      {
                        printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION)
                                ", reduced exponent range [%"
                                MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC
                                "d] (underflow test) on:\n",
                                (mpfr_eexp_t) e + 1, (mpfr_eexp_t) oemax);
                        printf ("x = ");
                        mpfr_dump (x);
#if defined(TWO_ARGS_ALL)
                        printf ("u = ");
                        mpfr_dump (u);
#endif
                        printf ("yprec = %u, rnd_mode = %s\n",
                                (unsigned int) yprec,
                                mpfr_print_rnd_mode (rnd));
                        printf ("Expected flags =");
                        flags_out (ex_flags);
                        printf ("     got flags =");
                        flags_out (flags);
                        printf ("inex = %d, w = ", inexact);
                        mpfr_dump (w);
                        exit (1);
                      }
                    test_uf = 0;  /* Underflow is tested only once. */
                  }
                if (e < emin)
                  emin = e;
                if (e > emax)
                  emax = e;
              }
            if (emin > emax)
              emin = emax;  /* case where all values are singular */
            /* Consistency test in a reduced exponent range. Doing it
               for the first 10 samples and for prec == p1 (which has
               some special cases) should be sufficient. */
            if (ctrt <= 10 || prec == p1)
              {
                mpfr_set_emin (emin);
                mpfr_set_emax (emax);
#ifdef DEBUG_TGENERIC
                /* Useful information in case of assertion failure. */
                printf ("tgeneric: reduced exponent range [%"
                        MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d]\n",
                        (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
#endif
                mpfr_clear_flags ();
#if defined(TWO_ARGS)
                inexact = TEST_FUNCTION (w, x, u, rnd);
#elif defined(DOUBLE_ARG1)
                inexact = TEST_FUNCTION (w, d, x, rnd);
#elif defined(DOUBLE_ARG2)
                inexact = TEST_FUNCTION (w, x, d, rnd);
#elif defined(ULONG_ARG1)
                inexact = TEST_FUNCTION (w, i, x, rnd);
#elif defined(ULONG_ARG2)
                inexact = TEST_FUNCTION (w, x, i, rnd);
#else
                inexact = TEST_FUNCTION (w, x, rnd);
#endif
                flags = __gmpfr_flags;
                mpfr_set_emin (oemin);
                mpfr_set_emax (oemax);
                if (! (SAME_VAL (w, y) &&
                       SAME_SIGN (inexact, compare) &&
                       flags == oldflags))
                  {
                    printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION)
                            ", reduced exponent range [%"
                            MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d] on:\n",
                            (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
                    printf ("x = ");
                    mpfr_dump (x);
#if defined(TWO_ARGS_ALL)
                    printf ("u = ");
                    mpfr_dump (u);
#endif
                    printf ("yprec = %u, rnd_mode = %s\n",
                            (unsigned int) yprec, mpfr_print_rnd_mode (rnd));
                    printf ("Expected:\n  y = ");
                    mpfr_dump (y);
                    printf ("  inex = %d, flags =", compare);
                    flags_out (oldflags);
                    printf ("Got:\n  w = ");
                    mpfr_dump (w);
                    printf ("  inex = %d, flags =", inexact);
                    flags_out (flags);
                    exit (1);
                  }
              }
            __gmpfr_flags = oldflags;  /* restore the flags */
          }

          if (MPFR_IS_SINGULAR (y))
            {
              if (MPFR_IS_NAN (y) || mpfr_nanflag_p ())
                TGENERIC_CHECK ("bad NaN flag",
                                MPFR_IS_NAN (y) && mpfr_nanflag_p ());
              else if (MPFR_IS_INF (y))
                {
                  TGENERIC_CHECK ("bad overflow flag",
                                  (compare != 0) ^ (mpfr_overflow_p () == 0));
                  TGENERIC_CHECK ("bad divide-by-zero flag",
                                  (compare == 0 && !infinite_input) ^
                                  (mpfr_divby0_p () == 0));
                }
              else if (MPFR_IS_ZERO (y))
                TGENERIC_CHECK ("bad underflow flag",
                                (compare != 0) ^ (mpfr_underflow_p () == 0));
            }
          else if (mpfr_divby0_p ())
            {
              TGENERIC_CHECK ("both overflow and divide-by-zero",
                              ! mpfr_overflow_p ());
              TGENERIC_CHECK ("both underflow and divide-by-zero",
                              ! mpfr_underflow_p ());
              TGENERIC_CHECK ("bad compare value (divide-by-zero)",
                              compare == 0);
            }
          else if (mpfr_overflow_p ())
            {
              TGENERIC_CHECK ("both underflow and overflow",
                              ! mpfr_underflow_p ());
              TGENERIC_CHECK ("bad compare value (overflow)", compare != 0);
              mpfr_nexttoinf (y);
              TGENERIC_CHECK ("should have been max MPFR number (overflow)",
                              MPFR_IS_INF (y));
            }
          else if (mpfr_underflow_p ())
            {
              TGENERIC_CHECK ("bad compare value (underflow)", compare != 0);
              mpfr_nexttozero (y);
              TGENERIC_CHECK ("should have been min MPFR number (underflow)",
                              MPFR_IS_ZERO (y));
            }
          else if (mpfr_can_round (y, yprec, rnd, rnd, prec))
            {
              ctrn++;
              mpfr_set (t, y, rnd);
              /* Risk of failures are known when some flags are already set
                 before the function call. Do not set the erange flag, as
                 it will remain set after the function call and no checks
                 are performed in such a case (see the mpfr_erangeflag_p
                 test below). */
              if (randlimb () & 1)
                __gmpfr_flags = MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE;
#ifdef DEBUG_TGENERIC
              TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (z));
#endif
              /* Let's increase the precision of the inputs in a random way.
                 In most cases, this doesn't make any difference, but for
                 the mpfr_fmod bug fixed in r6230, this triggers the bug. */
              mpfr_prec_round (x, mpfr_get_prec (x) + (randlimb () & 15),
                               MPFR_RNDN);
#if defined(TWO_ARGS)
              mpfr_prec_round (u, mpfr_get_prec (u) + (randlimb () & 15),
                               MPFR_RNDN);
              inexact = TEST_FUNCTION (z, x, u, rnd);
#elif defined(DOUBLE_ARG1)
              inexact = TEST_FUNCTION (z, d, x, rnd);
#elif defined(DOUBLE_ARG2)
              inexact = TEST_FUNCTION (z, x, d, rnd);
#elif defined(ULONG_ARG1)
              inexact = TEST_FUNCTION (z, i, x, rnd);
#elif defined(ULONG_ARG2)
              inexact = TEST_FUNCTION (z, x, i, rnd);
#else
              inexact = TEST_FUNCTION (z, x, rnd);
#endif
              if (mpfr_erangeflag_p ())
                goto next_n;
              if (! mpfr_equal_p (t, z))
                {
                  printf ("tgeneric: results differ for "
                          MAKE_STR(TEST_FUNCTION) " on\n  x = ");
                  mpfr_dump (x);
#if defined(TWO_ARGS_ALL)
                  printf ("  u = ");
                  mpfr_dump (u);
#endif
                  printf ("  prec = %u, rnd_mode = %s\n",
                          (unsigned int) prec, mpfr_print_rnd_mode (rnd));
                  printf ("Got      ");
                  mpfr_dump (z);
                  printf ("Expected ");
                  mpfr_dump (t);
                  printf ("Approx   ");
                  mpfr_dump (y);
                  exit (1);
                }
              compare2 = mpfr_cmp (t, y);
              /* if rounding to nearest, cannot know the sign of t - f(x)
                 because of composed rounding: y = o(f(x)) and t = o(y) */
              if (compare * compare2 >= 0)
                compare = compare + compare2;
              else
                compare = inexact; /* cannot determine sign(t-f(x)) */
              if (! SAME_SIGN (inexact, compare))
                {
                  printf ("Wrong inexact flag for rnd=%s: expected %d, got %d"
                          "\n", mpfr_print_rnd_mode (rnd), compare, inexact);
                  printf ("x = ");
                  mpfr_dump (x);
#if defined(TWO_ARGS_ALL)
                  printf ("u = ");
                  mpfr_dump (u);
#endif
                  printf ("y = ");
                  mpfr_dump (y);
                  printf ("t = ");
                  mpfr_dump (t);
                  exit (1);
                }
            }
          else if (getenv ("MPFR_SUSPICIOUS_OVERFLOW") != NULL)
            {
              /* For developers only! */
              MPFR_ASSERTN (MPFR_IS_PURE_FP (y));
              mpfr_nexttoinf (y);
              if (MPFR_IS_INF (y) && MPFR_IS_LIKE_RNDZ (rnd, MPFR_IS_NEG (y))
                  && !mpfr_overflow_p () && TGENERIC_SO_TEST)
                {
                  printf ("Possible bug! |y| is the maximum finite number "
                          "and has been obtained when\nrounding toward zero"
                          " (%s). Thus there is a very probable overflow,\n"
                          "but the overflow flag is not set!\n",
                          mpfr_print_rnd_mode (rnd));
                  printf ("x = ");
                  mpfr_dump (x);
#if defined(TWO_ARGS_ALL)
                  printf ("u = ");
                  mpfr_dump (u);
#endif
                  exit (1);
                }
            }

        next_n:
          /* In case the exponent range has been changed by
             tests_default_random() or for special values... */
          mpfr_set_emin (old_emin);
          mpfr_set_emax (old_emax);
        }
    }

#ifndef TGENERIC_NOWARNING
  if (3 * ctrn < 2 * ctrt)
    printf ("Warning! Too few normal cases in generic tests (%lu / %lu)\n",
            ctrn, ctrt);
#endif

  mpfr_clears (x, y, z, t, w, (mpfr_ptr) 0);
#if defined(TWO_ARGS_ALL)
  mpfr_clear (u);
#endif
}
示例#12
0
static void
test_generic (mp_prec_t p0, mp_prec_t p1, unsigned int N)
{
  mp_prec_t prec, xprec, yprec;
  mpfr_t x, y, z, t;
#ifdef TWO_ARGS
  mpfr_t u;
#elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
  mpfr_t u;
  double d;
#endif
  mp_rnd_t rnd;
  int inexact, compare, compare2;
  unsigned int n;
  unsigned long ctrt = 0, ctrn = 0;
  mp_exp_t old_emin, old_emax;

  old_emin = mpfr_get_emin ();
  old_emax = mpfr_get_emax ();

  mpfr_init (x);
  mpfr_init (y);
  mpfr_init (z);
  mpfr_init (t);
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
  mpfr_init (u);
#endif

  /* generic test */
  for (prec = p0; prec <= p1; prec++)
    {
      mpfr_set_prec (z, prec);
      mpfr_set_prec (t, prec);
      yprec = prec + 10;
      mpfr_set_prec (y, yprec);

      /* Note: in precision p1, we test 4 special cases. */
      for (n = 0; n < (prec == p1 ? N + 4 : N); n++)
        {
          xprec = prec;
          if (randlimb () & 1)
            {
              xprec *= (double) randlimb () / MP_LIMB_T_MAX;
              if (xprec < MPFR_PREC_MIN)
                xprec = MPFR_PREC_MIN;
            }
          mpfr_set_prec (x, xprec);
#ifdef TWO_ARGS
          mpfr_set_prec (u, xprec);
#elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
          mpfr_set_prec (u, IEEE_DBL_MANT_DIG);
#endif

          if (n > 3 || prec < p1)
            {
#if defined(RAND_FUNCTION)
              RAND_FUNCTION (x);
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
              RAND_FUNCTION (u);
#endif
#else
              tests_default_random (x, TEST_RANDOM_POS,
                                    TEST_RANDOM_EMIN, TEST_RANDOM_EMAX);
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
              tests_default_random (u, TEST_RANDOM_POS2,
                                    TEST_RANDOM_EMIN, TEST_RANDOM_EMAX);
#endif
#endif
            }
          else
            {
              /* Special cases tested in precision p1 if n <= 3. They are
                 useful really in the extended exponent range. */
              set_emin (MPFR_EMIN_MIN);
              set_emax (MPFR_EMAX_MAX);
              if (n <= 1)
                {
                  mpfr_set_si (x, n == 0 ? 1 : -1, GMP_RNDN);
                  mpfr_set_exp (x, mpfr_get_emin ());
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
                  mpfr_set_si (u, randlimb () % 2 == 0 ? 1 : -1, GMP_RNDN);
                  mpfr_set_exp (u, mpfr_get_emin ());
#endif
                }
              else  /* 2 <= n <= 3 */
                {
                  if (getenv ("MPFR_CHECK_MAX") == NULL)
                    goto next_n;
                  mpfr_set_si (x, n == 0 ? 1 : -1, GMP_RNDN);
                  mpfr_setmax (x, REDUCE_EMAX);
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
                  mpfr_set_si (u, randlimb () % 2 == 0 ? 1 : -1, GMP_RNDN);
                  mpfr_setmax (u, mpfr_get_emax ());
#endif
                }
            }

          rnd = RND_RAND ();
          mpfr_clear_flags ();
#ifdef DEBUG_TGENERIC
          TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (y));
#endif
#if defined(TWO_ARGS)
          compare = TEST_FUNCTION (y, x, u, rnd);
#elif defined(DOUBLE_ARG1)
          d = mpfr_get_d (u, rnd);
          compare = TEST_FUNCTION (y, d, x, rnd);
#elif defined(DOUBLE_ARG2)
          d = mpfr_get_d (u, rnd);
          compare = TEST_FUNCTION (y, x, d, rnd);
#else
          compare = TEST_FUNCTION (y, x, rnd);
#endif
          TGENERIC_CHECK ("Bad inexact flag",
                          (compare != 0) ^ (mpfr_inexflag_p () == 0));
          ctrt++;
          if (MPFR_IS_SINGULAR (y))
            {
              if (MPFR_IS_NAN (y) || mpfr_nanflag_p ())
                TGENERIC_CHECK ("Bad NaN flag",
                                MPFR_IS_NAN (y) && mpfr_nanflag_p ());
              else if (MPFR_IS_INF (y))
                TGENERIC_CHECK ("Bad overflow flag",
                                (compare != 0) ^ (mpfr_overflow_p () == 0));
              else if (MPFR_IS_ZERO (y))
                TGENERIC_CHECK ("Bad underflow flag",
                                (compare != 0) ^ (mpfr_underflow_p () == 0));
            }
          else if (mpfr_overflow_p ())
            {
              TGENERIC_CHECK ("Bad compare value (overflow)", compare != 0);
              mpfr_nexttoinf (y);
              TGENERIC_CHECK ("Should have been max MPFR number",
                              MPFR_IS_INF (y));
            }
          else if (mpfr_underflow_p ())
            {
              TGENERIC_CHECK ("Bad compare value (underflow)", compare != 0);
              mpfr_nexttozero (y);
              TGENERIC_CHECK ("Should have been min MPFR number",
                              MPFR_IS_ZERO (y));
            }
          else if (mpfr_can_round (y, yprec, rnd, rnd, prec))
            {
              ctrn++;
              mpfr_set (t, y, rnd);
              /* Risk of failures are known when some flags are already set
                 before the function call. Do not set the erange flag, as
                 it will remain set after the function call and no checks
                 are performed in such a case (see the mpfr_erangeflag_p
                 test below). */
              if (randlimb () & 1)
                __gmpfr_flags = MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE;
#ifdef DEBUG_TGENERIC
              TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (z));
#endif
              /* Let's increase the precision of the inputs in a random way.
                 In most cases, this doesn't make any difference, but this
                 triggers the mpfr_fmod bug fixed in r6235. */
              mpfr_prec_round (x, mpfr_get_prec (x) + (randlimb () & 15),
                               GMP_RNDN);
#if defined(TWO_ARGS)
              mpfr_prec_round (u, mpfr_get_prec (u) + (randlimb () & 15),
                               GMP_RNDN);
              inexact = TEST_FUNCTION (z, x, u, rnd);
#elif defined(DOUBLE_ARG1)
              inexact = TEST_FUNCTION (z, d, x, rnd);
#elif defined(DOUBLE_ARG2)
              inexact = TEST_FUNCTION (z, x, d, rnd);
#else
              inexact = TEST_FUNCTION (z, x, rnd);
#endif
              if (mpfr_erangeflag_p ())
                goto next_n;
              if (mpfr_nan_p (z) || mpfr_cmp (t, z) != 0)
                {
                  printf ("results differ for x=");
                  mpfr_out_str (stdout, 2, xprec, x, GMP_RNDN);
#ifdef TWO_ARGS
                  printf ("\nu=");
                  mpfr_out_str (stdout, 2, xprec, u, GMP_RNDN);
#elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
                  printf ("\nu=");
                  mpfr_out_str (stdout, 2, IEEE_DBL_MANT_DIG, u, GMP_RNDN);
#endif
                  printf (" prec=%u rnd_mode=%s\n", (unsigned) prec,
                          mpfr_print_rnd_mode (rnd));
                  printf ("got      ");
                  mpfr_out_str (stdout, 2, prec, z, GMP_RNDN);
                  puts ("");
                  printf ("expected ");
                  mpfr_out_str (stdout, 2, prec, t, GMP_RNDN);
                  puts ("");
                  printf ("approx   ");
                  mpfr_print_binary (y);
                  puts ("");
                  exit (1);
                }
              compare2 = mpfr_cmp (t, y);
              /* if rounding to nearest, cannot know the sign of t - f(x)
                 because of composed rounding: y = o(f(x)) and t = o(y) */
              if (compare * compare2 >= 0)
                compare = compare + compare2;
              else
                compare = inexact; /* cannot determine sign(t-f(x)) */
              if (((inexact == 0) && (compare != 0)) ||
                  ((inexact > 0) && (compare <= 0)) ||
                  ((inexact < 0) && (compare >= 0)))
                {
                  printf ("Wrong inexact flag for rnd=%s: expected %d, got %d"
                          "\n", mpfr_print_rnd_mode (rnd), compare, inexact);
                  printf ("x="); mpfr_print_binary (x); puts ("");
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
                  printf ("u="); mpfr_print_binary (u); puts ("");
#endif
                  printf ("y="); mpfr_print_binary (y); puts ("");
                  printf ("t="); mpfr_print_binary (t); puts ("");
                  exit (1);
                }
            }
          else if (getenv ("MPFR_SUSPICIOUS_OVERFLOW") != NULL)
            {
              /* For developers only! */
              MPFR_ASSERTN (MPFR_IS_PURE_FP (y));
              mpfr_nexttoinf (y);
              if (MPFR_IS_INF (y) && MPFR_IS_LIKE_RNDZ (rnd, MPFR_IS_NEG (y))
                  && !mpfr_overflow_p ())
                {
                  printf ("Possible bug! |y| is the maximum finite number "
                          "and has been obtained when\nrounding toward zero"
                          " (%s). Thus there is a very probable overflow,\n"
                          "but the overflow flag is not set!\n",
                          mpfr_print_rnd_mode (rnd));
                  printf ("x="); mpfr_print_binary (x); puts ("");
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
                  printf ("u="); mpfr_print_binary (u); puts ("");
#endif
                  exit (1);
                }
            }

        next_n:
          /* In case the exponent range has been changed by
             tests_default_random() or for special values... */
          mpfr_set_emin (old_emin);
          mpfr_set_emax (old_emax);
        }
    }

#ifndef TGENERIC_NOWARNING
  if (3 * ctrn < 2 * ctrt)
    printf ("Warning! Too few normal cases in generic tests (%lu / %lu)\n",
            ctrn, ctrt);
#endif

  mpfr_clear (x);
  mpfr_clear (y);
  mpfr_clear (z);
  mpfr_clear (t);
#if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
  mpfr_clear (u);
#endif
}
示例#13
0
文件: erf.c 项目: BrianGladman/mpfr
int
mpfr_erf (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  mpfr_t xf;
  mp_limb_t xf_limb[(53 - 1) / GMP_NUMB_BITS + 1];
  int inex, large;
  MPFR_SAVE_EXPO_DECL (expo);

  MPFR_LOG_FUNC
    (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode),
     ("y[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (y), mpfr_log_prec, y, inex));

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN (x))
        {
          MPFR_SET_NAN (y);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF (x)) /* erf(+inf) = +1, erf(-inf) = -1 */
        return mpfr_set_si (y, MPFR_INT_SIGN (x), MPFR_RNDN);
      else /* erf(+0) = +0, erf(-0) = -0 */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          return mpfr_set (y, x, MPFR_RNDN); /* should keep the sign of x */
        }
    }

  /* now x is neither NaN, Inf nor 0 */

  /* first try expansion at x=0 when x is small, or asymptotic expansion
     where x is large */

  MPFR_SAVE_EXPO_MARK (expo);

  /* around x=0, we have erf(x) = 2x/sqrt(Pi) (1 - x^2/3 + ...),
     with 1 - x^2/3 <= sqrt(Pi)*erf(x)/2/x <= 1 for x >= 0. This means that
     if x^2/3 < 2^(-PREC(y)-1) we can decide of the correct rounding,
     unless we have a worst-case for 2x/sqrt(Pi). */
  if (MPFR_EXP(x) < - (mpfr_exp_t) (MPFR_PREC(y) / 2))
    {
      /* we use 2x/sqrt(Pi) (1 - x^2/3) <= erf(x) <= 2x/sqrt(Pi) for x > 0
         and 2x/sqrt(Pi) <= erf(x) <= 2x/sqrt(Pi) (1 - x^2/3) for x < 0.
         In both cases |2x/sqrt(Pi) (1 - x^2/3)| <= |erf(x)| <= |2x/sqrt(Pi)|.
         We will compute l and h such that l <= |2x/sqrt(Pi) (1 - x^2/3)|
         and |2x/sqrt(Pi)| <= h. If l and h round to the same value to
         precision PREC(y) and rounding rnd_mode, then we are done. */
      mpfr_t l, h; /* lower and upper bounds for erf(x) */
      int ok, inex2;

      mpfr_init2 (l, MPFR_PREC(y) + 17);
      mpfr_init2 (h, MPFR_PREC(y) + 17);
      /* first compute l */
      mpfr_mul (l, x, x, MPFR_RNDU);
      mpfr_div_ui (l, l, 3, MPFR_RNDU); /* upper bound on x^2/3 */
      mpfr_ui_sub (l, 1, l, MPFR_RNDZ); /* lower bound on 1 - x^2/3 */
      mpfr_const_pi (h, MPFR_RNDU); /* upper bound of Pi */
      mpfr_sqrt (h, h, MPFR_RNDU); /* upper bound on sqrt(Pi) */
      mpfr_div (l, l, h, MPFR_RNDZ); /* lower bound on 1/sqrt(Pi) (1 - x^2/3) */
      mpfr_mul_2ui (l, l, 1, MPFR_RNDZ); /* 2/sqrt(Pi) (1 - x^2/3) */
      mpfr_mul (l, l, x, MPFR_RNDZ); /* |l| is a lower bound on
                                       |2x/sqrt(Pi) (1 - x^2/3)| */
      /* now compute h */
      mpfr_const_pi (h, MPFR_RNDD); /* lower bound on Pi */
      mpfr_sqrt (h, h, MPFR_RNDD); /* lower bound on sqrt(Pi) */
      mpfr_div_2ui (h, h, 1, MPFR_RNDD); /* lower bound on sqrt(Pi)/2 */
      /* since sqrt(Pi)/2 < 1, the following should not underflow */
      mpfr_div (h, x, h, MPFR_IS_POS(x) ? MPFR_RNDU : MPFR_RNDD);
      /* round l and h to precision PREC(y) */
      inex = mpfr_prec_round (l, MPFR_PREC(y), rnd_mode);
      inex2 = mpfr_prec_round (h, MPFR_PREC(y), rnd_mode);
      /* Caution: we also need inex=inex2 (inex might be 0). */
      ok = SAME_SIGN (inex, inex2) && mpfr_cmp (l, h) == 0;
      if (ok)
        mpfr_set (y, h, rnd_mode);
      mpfr_clear (l);
      mpfr_clear (h);
      if (ok)
        goto end;
      /* this test can still fail for small precision, for example
         for x=-0.100E-2 with a target precision of 3 bits, since
         the error term x^2/3 is not that small. */
    }

  MPFR_TMP_INIT1(xf_limb, xf, 53);
  mpfr_div (xf, x, __gmpfr_const_log2_RNDU, MPFR_RNDZ); /* round to zero
                        ensures we get a lower bound of |x/log(2)| */
  mpfr_mul (xf, xf, x, MPFR_RNDZ);
  large = mpfr_cmp_ui (xf, MPFR_PREC (y) + 1) > 0;

  /* when x goes to infinity, we have erf(x) = 1 - 1/sqrt(Pi)/exp(x^2)/x + ...
     and |erf(x) - 1| <= exp(-x^2) is true for any x >= 0, thus if
     exp(-x^2) < 2^(-PREC(y)-1) the result is 1 or 1-epsilon.
     This rewrites as x^2/log(2) > p+1. */
  if (MPFR_UNLIKELY (large))
    /* |erf x| = 1 or 1- */
    {
      mpfr_rnd_t rnd2 = MPFR_IS_POS (x) ? rnd_mode : MPFR_INVERT_RND(rnd_mode);
      if (rnd2 == MPFR_RNDN || rnd2 == MPFR_RNDU || rnd2 == MPFR_RNDA)
        {
          inex = MPFR_INT_SIGN (x);
          mpfr_set_si (y, inex, rnd2);
        }
      else /* round to zero */
        {
          inex = -MPFR_INT_SIGN (x);
          mpfr_setmax (y, 0); /* warning: setmax keeps the old sign of y */
          MPFR_SET_SAME_SIGN (y, x);
        }
    }
  else  /* use Taylor */
    {
      double xf2;

      /* FIXME: get rid of doubles/mpfr_get_d here */
      xf2 = mpfr_get_d (x, MPFR_RNDN);
      xf2 = xf2 * xf2; /* xf2 ~ x^2 */
      inex = mpfr_erf_0 (y, x, xf2, rnd_mode);
    }

 end:
  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (y, inex, rnd_mode);
}