예제 #1
0
파일: tdiv.c 프로젝트: Distrotech/mpfr
static void
check_lowr (void)
{
  mpfr_t x, y, z, z2, z3, tmp;
  int k, c, c2;


  mpfr_init2 (x, 1000);
  mpfr_init2 (y, 100);
  mpfr_init2 (tmp, 850);
  mpfr_init2 (z, 10);
  mpfr_init2 (z2, 10);
  mpfr_init2 (z3, 50);

  for (k = 1; k < KMAX; k++)
    {
      do
        {
          mpfr_urandomb (z, RANDS);
        }
      while (mpfr_cmp_ui (z, 0) == 0);
      do
        {
          mpfr_urandomb (tmp, RANDS);
        }
      while (mpfr_cmp_ui (tmp, 0) == 0);
      mpfr_mul (x, z, tmp, MPFR_RNDN); /* exact */
      c = test_div (z2, x, tmp, MPFR_RNDN);

      if (c || mpfr_cmp (z2, z))
        {
          printf ("Error in mpfr_div rnd=MPFR_RNDN\n");
          printf ("got        "); mpfr_print_binary(z2); puts ("");
          printf ("instead of "); mpfr_print_binary(z); puts ("");
          printf ("inex flag = %d, expected 0\n", c);
          exit (1);
        }
    }

  /* x has still precision 1000, z precision 10, and tmp prec 850 */
  mpfr_set_prec (z2, 9);
  for (k = 1; k < KMAX; k++)
    {
      mpfr_urandomb (z, RANDS);
      do
        {
          mpfr_urandomb (tmp, RANDS);
        }
      while (mpfr_cmp_ui (tmp, 0) == 0);
      mpfr_mul (x, z, tmp, MPFR_RNDN); /* exact */
      c = test_div (z2, x, tmp, MPFR_RNDN);
      /* since z2 has one less bit that z, either the division is exact
         if z is representable on 9 bits, or we have an even round case */

      c2 = get_inexact (z2, x, tmp);
      if ((mpfr_cmp (z2, z) == 0 && c) || inex_cmp (c, c2))
        {
          printf ("Error in mpfr_div rnd=MPFR_RNDN\n");
          printf ("got        "); mpfr_print_binary(z2); puts ("");
          printf ("instead of "); mpfr_print_binary(z); puts ("");
          printf ("inex flag = %d, expected %d\n", c, c2);
          exit (1);
        }
      else if (c == 2)
        {
          mpfr_nexttoinf (z);
          if (mpfr_cmp(z2, z))
            {
              printf ("Error in mpfr_div [even rnd?] rnd=MPFR_RNDN\n");
              printf ("Dividing ");
              printf ("got        "); mpfr_print_binary(z2); puts ("");
              printf ("instead of "); mpfr_print_binary(z); puts ("");
              printf ("inex flag = %d\n", 1);
              exit (1);
            }
        }
      else if (c == -2)
        {
          mpfr_nexttozero (z);
          if (mpfr_cmp(z2, z))
            {
              printf ("Error in mpfr_div [even rnd?] rnd=MPFR_RNDN\n");
              printf ("Dividing ");
              printf ("got        "); mpfr_print_binary(z2); puts ("");
              printf ("instead of "); mpfr_print_binary(z); puts ("");
              printf ("inex flag = %d\n", 1);
              exit (1);
            }
        }
    }

  mpfr_set_prec(x, 1000);
  mpfr_set_prec(y, 100);
  mpfr_set_prec(tmp, 850);
  mpfr_set_prec(z, 10);
  mpfr_set_prec(z2, 10);

  /* almost exact divisions */
  for (k = 1; k < KMAX; k++)
    {
      do
        {
          mpfr_urandomb (z, RANDS);
        }
      while (mpfr_cmp_ui (z, 0) == 0);
      do
        {
          mpfr_urandomb (tmp, RANDS);
        }
      while (mpfr_cmp_ui (tmp, 0) == 0);
      mpfr_mul(x, z, tmp, MPFR_RNDN);
      mpfr_set(y, tmp, MPFR_RNDD);
      mpfr_nexttoinf (x);

      c = test_div(z2, x, y, MPFR_RNDD);
      test_div(z3, x, y, MPFR_RNDD);
      mpfr_set(z, z3, MPFR_RNDD);

      if (c != -1 || mpfr_cmp(z2, z))
        {
          printf ("Error in mpfr_div rnd=MPFR_RNDD\n");
          printf ("got        "); mpfr_print_binary(z2); puts ("");
          printf ("instead of "); mpfr_print_binary(z); puts ("");
          printf ("inex flag = %d\n", c);
          exit (1);
        }

      mpfr_set (y, tmp, MPFR_RNDU);
      test_div (z3, x, y, MPFR_RNDU);
      mpfr_set (z, z3, MPFR_RNDU);
      c = test_div (z2, x, y, MPFR_RNDU);
      if (c != 1 || mpfr_cmp (z2, z))
        {
          printf ("Error in mpfr_div rnd=MPFR_RNDU\n");
          printf ("u="); mpfr_dump (x);
          printf ("v="); mpfr_dump (y);
          printf ("got        "); mpfr_print_binary (z2); puts ("");
          printf ("instead of "); mpfr_print_binary (z); puts ("");
          printf ("inex flag = %d\n", c);
          exit (1);
        }
    }

  mpfr_clear (x);
  mpfr_clear (y);
  mpfr_clear (z);
  mpfr_clear (z2);
  mpfr_clear (z3);
  mpfr_clear (tmp);
}
예제 #2
0
파일: tdiv.c 프로젝트: Distrotech/mpfr
static void
check_special (void)
{
  mpfr_t  a, d, q;
  mpfr_exp_t emax, emin;
  int i;

  mpfr_init2 (a, 100L);
  mpfr_init2 (d, 100L);
  mpfr_init2 (q, 100L);

  /* 1/nan == nan */
  mpfr_set_ui (a, 1L, MPFR_RNDN);
  MPFR_SET_NAN (d);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN);

  /* nan/1 == nan */
  MPFR_SET_NAN (a);
  mpfr_set_ui (d, 1L, MPFR_RNDN);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN);

  /* +inf/1 == +inf */
  MPFR_SET_INF (a);
  MPFR_SET_POS (a);
  mpfr_set_ui (d, 1L, MPFR_RNDN);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q));
  MPFR_ASSERTN (mpfr_sgn (q) > 0);
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* +inf/-1 == -inf */
  MPFR_SET_INF (a);
  MPFR_SET_POS (a);
  mpfr_set_si (d, -1, MPFR_RNDN);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q));
  MPFR_ASSERTN (mpfr_sgn (q) < 0);
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* -inf/1 == -inf */
  MPFR_SET_INF (a);
  MPFR_SET_NEG (a);
  mpfr_set_ui (d, 1L, MPFR_RNDN);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q));
  MPFR_ASSERTN (mpfr_sgn (q) < 0);
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* -inf/-1 == +inf */
  MPFR_SET_INF (a);
  MPFR_SET_NEG (a);
  mpfr_set_si (d, -1, MPFR_RNDN);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q));
  MPFR_ASSERTN (mpfr_sgn (q) > 0);
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* 1/+inf == +0 */
  mpfr_set_ui (a, 1L, MPFR_RNDN);
  MPFR_SET_INF (d);
  MPFR_SET_POS (d);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_number_p (q));
  MPFR_ASSERTN (mpfr_sgn (q) == 0);
  MPFR_ASSERTN (MPFR_IS_POS (q));
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* 1/-inf == -0 */
  mpfr_set_ui (a, 1L, MPFR_RNDN);
  MPFR_SET_INF (d);
  MPFR_SET_NEG (d);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_number_p (q));
  MPFR_ASSERTN (mpfr_sgn (q) == 0);
  MPFR_ASSERTN (MPFR_IS_NEG (q));
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* -1/+inf == -0 */
  mpfr_set_si (a, -1, MPFR_RNDN);
  MPFR_SET_INF (d);
  MPFR_SET_POS (d);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_number_p (q));
  MPFR_ASSERTN (mpfr_sgn (q) == 0);
  MPFR_ASSERTN (MPFR_IS_NEG (q));
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* -1/-inf == +0 */
  mpfr_set_si (a, -1, MPFR_RNDN);
  MPFR_SET_INF (d);
  MPFR_SET_NEG (d);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_number_p (q));
  MPFR_ASSERTN (mpfr_sgn (q) == 0);
  MPFR_ASSERTN (MPFR_IS_POS (q));
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* 0/0 == nan */
  mpfr_set_ui (a, 0L, MPFR_RNDN);
  mpfr_set_ui (d, 0L, MPFR_RNDN);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN);

  /* +inf/+inf == nan */
  MPFR_SET_INF (a);
  MPFR_SET_POS (a);
  MPFR_SET_INF (d);
  MPFR_SET_POS (d);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN);

  /* 1/+0 = +inf */
  mpfr_set_ui (a, 1, MPFR_RNDZ);
  mpfr_set_ui (d, 0, MPFR_RNDZ);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0);
  MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0);

  /* 1/-0 = -inf */
  mpfr_set_ui (a, 1, MPFR_RNDZ);
  mpfr_set_ui (d, 0, MPFR_RNDZ);
  mpfr_neg (d, d, MPFR_RNDZ);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0);
  MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0);

  /* -1/+0 = -inf */
  mpfr_set_si (a, -1, MPFR_RNDZ);
  mpfr_set_ui (d, 0, MPFR_RNDZ);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0);
  MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0);

  /* -1/-0 = +inf */
  mpfr_set_si (a, -1, MPFR_RNDZ);
  mpfr_set_ui (d, 0, MPFR_RNDZ);
  mpfr_neg (d, d, MPFR_RNDZ);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0);
  MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0);

  /* +inf/+0 = +inf */
  MPFR_SET_INF (a);
  MPFR_SET_POS (a);
  mpfr_set_ui (d, 0, MPFR_RNDZ);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0);
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* +inf/-0 = -inf */
  MPFR_SET_INF (a);
  MPFR_SET_POS (a);
  mpfr_set_ui (d, 0, MPFR_RNDZ);
  mpfr_neg (d, d, MPFR_RNDZ);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0);
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* -inf/+0 = -inf */
  MPFR_SET_INF (a);
  MPFR_SET_NEG (a);
  mpfr_set_ui (d, 0, MPFR_RNDZ);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0);
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* -inf/-0 = +inf */
  MPFR_SET_INF (a);
  MPFR_SET_NEG (a);
  mpfr_set_ui (d, 0, MPFR_RNDZ);
  mpfr_neg (d, d, MPFR_RNDZ);
  mpfr_clear_flags ();
  MPFR_ASSERTN (test_div (q, a, d, MPFR_RNDZ) == 0); /* exact */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0);
  MPFR_ASSERTN (__gmpfr_flags == 0);

  /* check overflow */
  emax = mpfr_get_emax ();
  set_emax (1);
  mpfr_set_ui (a, 1, MPFR_RNDZ);
  mpfr_set_ui (d, 1, MPFR_RNDZ);
  mpfr_div_2exp (d, d, 1, MPFR_RNDZ);
  mpfr_clear_flags ();
  test_div (q, a, d, MPFR_RNDU); /* 1 / 0.5 = 2 -> overflow */
  MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0);
  MPFR_ASSERTN (__gmpfr_flags == (MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT));
  set_emax (emax);

  /* check underflow */
  emin = mpfr_get_emin ();
  set_emin (-1);
  mpfr_set_ui (a, 1, MPFR_RNDZ);
  mpfr_div_2exp (a, a, 2, MPFR_RNDZ);
  mpfr_set_prec (d, mpfr_get_prec (q) + 8);
  for (i = -1; i <= 1; i++)
    {
      int sign;

      /* Test 2^(-2) / (+/- (2 + eps)), with eps < 0, eps = 0, eps > 0.
         -> underflow.
         With div.c r5513, this test fails for eps > 0 in MPFR_RNDN. */
      mpfr_set_ui (d, 2, MPFR_RNDZ);
      if (i < 0)
        mpfr_nextbelow (d);
      if (i > 0)
        mpfr_nextabove (d);
      for (sign = 0; sign <= 1; sign++)
        {
          mpfr_clear_flags ();
          test_div (q, a, d, MPFR_RNDZ); /* result = 0 */
          MPFR_ASSERTN (__gmpfr_flags ==
                        (MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT));
          MPFR_ASSERTN (sign ? MPFR_IS_NEG (q) : MPFR_IS_POS (q));
          MPFR_ASSERTN (MPFR_IS_ZERO (q));
          mpfr_clear_flags ();
          test_div (q, a, d, MPFR_RNDN); /* result = 0 iff eps >= 0 */
          MPFR_ASSERTN (__gmpfr_flags ==
                        (MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT));
          MPFR_ASSERTN (sign ? MPFR_IS_NEG (q) : MPFR_IS_POS (q));
          if (i < 0)
            mpfr_nexttozero (q);
          MPFR_ASSERTN (MPFR_IS_ZERO (q));
          mpfr_neg (d, d, MPFR_RNDN);
        }
    }
  set_emin (emin);

  mpfr_clear (a);
  mpfr_clear (d);
  mpfr_clear (q);
}
예제 #3
0
파일: tanh.c 프로젝트: pgundlach/LuaTeX
int
mpfr_tanh (mpfr_ptr y, mpfr_srcptr xt , mpfr_rnd_t rnd_mode)
{
  /****** Declaration ******/
  mpfr_t x;
  int inexact;
  MPFR_SAVE_EXPO_DECL (expo);

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

  /* Special value checking */
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (xt)))
    {
      if (MPFR_IS_NAN (xt))
        {
          MPFR_SET_NAN (y);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF (xt))
        {
          /* tanh(inf) = 1 && tanh(-inf) = -1 */
          return mpfr_set_si (y, MPFR_INT_SIGN (xt), rnd_mode);
        }
      else /* tanh (0) = 0 and xt is zero */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO(xt));
          MPFR_SET_ZERO (y);
          MPFR_SET_SAME_SIGN (y, xt);
          MPFR_RET (0);
        }
    }

  /* tanh(x) = x - x^3/3 + ... so the error is < 2^(3*EXP(x)-1) */
  MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, xt, -2 * MPFR_GET_EXP (xt), 1, 0,
                                    rnd_mode, {});

  MPFR_TMP_INIT_ABS (x, xt);

  MPFR_SAVE_EXPO_MARK (expo);

  /* General case */
  {
    /* Declaration of the intermediary variable */
    mpfr_t t, te;
    mpfr_exp_t d;

    /* Declaration of the size variable */
    mpfr_prec_t Ny = MPFR_PREC(y);   /* target precision */
    mpfr_prec_t Nt;                  /* working precision */
    long int err;                  /* error */
    int sign = MPFR_SIGN (xt);
    MPFR_ZIV_DECL (loop);
    MPFR_GROUP_DECL (group);

    /* First check for BIG overflow of exp(2*x):
       For x > 0, exp(2*x) > 2^(2*x)
       If 2 ^(2*x) > 2^emax or x>emax/2, there is an overflow */
    if (MPFR_UNLIKELY (mpfr_cmp_si (x, __gmpfr_emax/2) >= 0)) {
      /* initialise of intermediary variables
         since 'set_one' label assumes the variables have been
         initialize */
      MPFR_GROUP_INIT_2 (group, MPFR_PREC_MIN, t, te);
      goto set_one;
    }

    /* Compute the precision of intermediary variable */
    /* The optimal number of bits: see algorithms.tex */
    Nt = Ny + MPFR_INT_CEIL_LOG2 (Ny) + 4;
    /* if x is small, there will be a cancellation in exp(2x)-1 */
    if (MPFR_GET_EXP (x) < 0)
      Nt += -MPFR_GET_EXP (x);

    /* initialise of intermediary variable */
    MPFR_GROUP_INIT_2 (group, Nt, t, te);

    MPFR_ZIV_INIT (loop, Nt);
    for (;;) {
      /* tanh = (exp(2x)-1)/(exp(2x)+1) */
      mpfr_mul_2ui (te, x, 1, MPFR_RNDN);  /* 2x */
      /* since x > 0, we can only have an overflow */
      mpfr_exp (te, te, MPFR_RNDN);        /* exp(2x) */
      if (MPFR_UNLIKELY (MPFR_IS_INF (te))) {
      set_one:
        inexact = MPFR_FROM_SIGN_TO_INT (sign);
        mpfr_set4 (y, __gmpfr_one, MPFR_RNDN, sign);
        if (MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG_SIGN (sign)))
          {
            inexact = -inexact;
            mpfr_nexttozero (y);
          }
        break;
      }
      d = MPFR_GET_EXP (te);              /* For Error calculation */
      mpfr_add_ui (t, te, 1, MPFR_RNDD);   /* exp(2x) + 1*/
      mpfr_sub_ui (te, te, 1, MPFR_RNDU);  /* exp(2x) - 1*/
      d = d - MPFR_GET_EXP (te);
      mpfr_div (t, te, t, MPFR_RNDN);      /* (exp(2x)-1)/(exp(2x)+1)*/

      /* Calculation of the error */
      d = MAX(3, d + 1);
      err = Nt - (d + 1);

      if (MPFR_LIKELY ((d <= Nt / 2) && MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
        {
          inexact = mpfr_set4 (y, t, rnd_mode, sign);
          break;
        }

      /* if t=1, we still can round since |sinh(x)| < 1 */
      if (MPFR_GET_EXP (t) == 1)
        goto set_one;

      /* Actualisation of the precision */
      MPFR_ZIV_NEXT (loop, Nt);
      MPFR_GROUP_REPREC_2 (group, Nt, t, te);
    }
    MPFR_ZIV_FREE (loop);
    MPFR_GROUP_CLEAR (group);
  }
  MPFR_SAVE_EXPO_FREE (expo);
  inexact = mpfr_check_range (y, inexact, rnd_mode);

  return inexact;
}
예제 #4
0
파일: tests.c 프로젝트: Kirija/XPIR
/* Test n random bad cases. A precision py in [pymin,pymax] and
 * a number y of precision py are chosen randomly. One computes
 * x = inv(y) in precision px = py + psup (rounded to nearest).
 * Then (in general), y is a bad case for fct in precision py (in
 * the directed rounding modes, but also in the rounding-to-nearest
 * mode for some lower precision: see data_check).
 * fct, inv, name: data related to the function.
 * pos, emin, emax: arguments for tests_default_random.
 */
void
bad_cases (int (*fct)(FLIST), int (*inv)(FLIST), const char *name,
           int pos, mpfr_exp_t emin, mpfr_exp_t emax,
           mpfr_prec_t pymin, mpfr_prec_t pymax, mpfr_prec_t psup,
           int n)
{
  mpfr_t x, y, z;
  char *dbgenv;
  int i, dbg;
  mpfr_exp_t old_emin, old_emax;

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

  dbgenv = getenv ("MPFR_DEBUG_BADCASES");
  dbg = dbgenv != 0 ? atoi (dbgenv) : 0;  /* debug level */
  mpfr_inits (x, y, z, (mpfr_ptr) 0);
  for (i = 0; i < n; i++)
    {
      mpfr_prec_t px, py, pz;
      int inex;

      if (dbg)
        printf ("bad_cases: i = %d\n", i);
      py = pymin + (randlimb () % (pymax - pymin + 1));
      mpfr_set_prec (y, py);
      tests_default_random (y, pos, emin, emax);
      if (dbg)
        {
          printf ("bad_cases: yprec =%4ld, y = ", (long) py);
          mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
          printf ("\n");
        }
      px = py + psup;
      mpfr_set_prec (x, px);
      mpfr_clear_flags ();
      inv (x, y, MPFR_RNDN);
      if (mpfr_nanflag_p () || mpfr_overflow_p () || mpfr_underflow_p ())
        {
          if (dbg)
            printf ("bad_cases: no normal inverse\n");
          goto next_i;
        }
      if (dbg > 1)
        {
          printf ("bad_cases: x = ");
          mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN);
          printf ("\n");
        }
      pz = px;
      do
        {
          pz += 32;
          mpfr_set_prec (z, pz);
          if (fct (z, x, MPFR_RNDN) == 0)
            {
              if (dbg)
                printf ("bad_cases: exact case\n");
              goto next_i;
            }
          if (dbg)
            {
              if (dbg > 1)
                {
                  printf ("bad_cases: %s(x) ~= ", name);
                  mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
                }
              else
                {
                  printf ("bad_cases:   [MPFR_RNDZ]  ~= ");
                  mpfr_out_str (stdout, 16, 40, z, MPFR_RNDZ);
                }
              printf ("\n");
            }
          inex = mpfr_prec_round (z, py, MPFR_RNDN);
          if (mpfr_nanflag_p () || mpfr_overflow_p () || mpfr_underflow_p ()
              || ! mpfr_equal_p (z, y))
            {
              if (dbg)
                printf ("bad_cases: inverse doesn't match\n");
              goto next_i;
            }
        }
      while (inex == 0);
      /* We really have a bad case. */
      do
        py--;
      while (py >= MPFR_PREC_MIN && mpfr_prec_round (z, py, MPFR_RNDZ) == 0);
      py++;
      /* py is now the smallest output precision such that we have
         a bad case in the directed rounding modes. */
      if (mpfr_prec_round (y, py, MPFR_RNDZ) != 0)
        {
          printf ("Internal error for i = %d\n", i);
          exit (1);
        }
      if ((inex > 0 && MPFR_IS_POS (z)) ||
          (inex < 0 && MPFR_IS_NEG (z)))
        {
          mpfr_nexttozero (y);
          if (mpfr_zero_p (y))
            goto next_i;
        }
      if (dbg)
        {
          printf ("bad_cases: yprec =%4ld, y = ", (long) py);
          mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
          printf ("\n");
        }
      /* Note: y is now the expected result rounded toward zero. */
      test5rm (fct, x, y, z, MPFR_RNDZ, 0, name);
    next_i:
      /* In case the exponent range has been changed by
         tests_default_random()... */
      mpfr_set_emin (old_emin);
      mpfr_set_emax (old_emax);
    }
  mpfr_clears (x, y, z, (mpfr_ptr) 0);
}
예제 #5
0
파일: tzeta.c 프로젝트: SESA/EbbRT-mpfr
/* Usage: tzeta - generic tests
          tzeta s prec rnd_mode - compute zeta(s) with precision 'prec'
                                  and rounding mode 'mode' */
int
main (int argc, char *argv[])
{
  mpfr_t s, y, z;
  mpfr_prec_t prec;
  mpfr_rnd_t rnd_mode;
  int inex;

  tests_start_mpfr ();

  if (argc != 1 && argc != 4)
    {
      printf ("Usage: tzeta\n"
              "    or tzeta s prec rnd_mode\n");
      exit (1);
    }

  if (argc == 4)
    {
      prec = atoi(argv[2]);
      mpfr_init2 (s, prec);
      mpfr_init2 (z, prec);
      mpfr_set_str (s, argv[1], 10, MPFR_RNDN);
      rnd_mode = (mpfr_rnd_t) atoi(argv[3]);

      mpfr_zeta (z, s, rnd_mode);
      mpfr_out_str (stdout, 10, 0, z, MPFR_RNDN);
      printf ("\n");

      mpfr_clear (s);
      mpfr_clear (z);

      return 0;
    }

  test1();

  mpfr_init2 (s, MPFR_PREC_MIN);
  mpfr_init2 (y, MPFR_PREC_MIN);
  mpfr_init2 (z, MPFR_PREC_MIN);


  /* the following seems to loop */
  mpfr_set_prec (s, 6);
  mpfr_set_prec (z, 6);
  mpfr_set_str_binary (s, "1.10010e4");
  mpfr_zeta (z, s, MPFR_RNDZ);


  mpfr_set_prec (s, 53);
  mpfr_set_prec (y, 53);
  mpfr_set_prec (z, 53);

  mpfr_set_ui (s, 1, MPFR_RNDN);
  mpfr_clear_divby0();
  mpfr_zeta (z, s, MPFR_RNDN);
  if (!mpfr_inf_p (z) || MPFR_SIGN (z) < 0 || !mpfr_divby0_p())
    {
      printf ("Error in mpfr_zeta for s = 1 (should be +inf) with divby0 flag\n");
      exit (1);
    }

  mpfr_set_str_binary (s, "0.1100011101110111111111111010000110010111001011001011");
  mpfr_set_str_binary (y, "-0.11111101111011001001001111111000101010000100000100100E2");
  mpfr_zeta (z, s, MPFR_RNDN);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (1,RNDN)\n");
      exit (1);
    }
  mpfr_zeta (z, s, MPFR_RNDZ);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (1,RNDZ)\n");
      exit (1);
    }
  mpfr_zeta (z, s, MPFR_RNDU);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (1,RNDU)\n");
      exit (1);
    }
  mpfr_zeta (z, s, MPFR_RNDD);
  mpfr_nexttoinf (y);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (1,RNDD)\n");
      exit (1);
    }

  mpfr_set_str_binary (s, "0.10001011010011100110010001100100001011000010011001011");
  mpfr_set_str_binary (y, "-0.11010011010010101101110111011010011101111101111010110E1");
  mpfr_zeta (z, s, MPFR_RNDN);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (2,RNDN)\n");
      exit (1);
    }
  mpfr_zeta (z, s, MPFR_RNDZ);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (2,RNDZ)\n");
      exit (1);
    }
  mpfr_zeta (z, s, MPFR_RNDU);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (2,RNDU)\n");
      exit (1);
    }
  mpfr_zeta (z, s, MPFR_RNDD);
  mpfr_nexttoinf (y);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (2,RNDD)\n");
      exit (1);
    }

  mpfr_set_str_binary (s, "0.1100111110100001111110111000110101111001011101000101");
  mpfr_set_str_binary (y, "-0.10010111010110000111011111001101100001111011000001010E3");
  mpfr_zeta (z, s, MPFR_RNDN);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (3,RNDN)\n");
      exit (1);
    }
  mpfr_zeta (z, s, MPFR_RNDD);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (3,RNDD)\n");
      exit (1);
    }
  mpfr_nexttozero (y);
  mpfr_zeta (z, s, MPFR_RNDZ);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (3,RNDZ)\n");
      exit (1);
    }
  mpfr_zeta (z, s, MPFR_RNDU);
  if (mpfr_cmp (z, y) != 0)
    {
      printf ("Error in mpfr_zeta (3,RNDU)\n");
      exit (1);
    }

  mpfr_set_str (s, "-400000001", 10, MPFR_RNDZ);
  mpfr_zeta (z, s, MPFR_RNDN);
  if (!(mpfr_inf_p (z) && MPFR_SIGN(z) < 0))
    {
      printf ("Error in mpfr_zeta (-400000001)\n");
      exit (1);
    }
  mpfr_set_str (s, "-400000003", 10, MPFR_RNDZ);
  mpfr_zeta (z, s, MPFR_RNDN);
  if (!(mpfr_inf_p (z) && MPFR_SIGN(z) > 0))
    {
      printf ("Error in mpfr_zeta (-400000003)\n");
      exit (1);
    }

  mpfr_set_prec (s, 34);
  mpfr_set_prec (z, 34);
  mpfr_set_str_binary (s, "-1.111111100001011110000010001010000e-35");
  mpfr_zeta (z, s, MPFR_RNDD);
  mpfr_set_str_binary (s, "-1.111111111111111111111111111111111e-2");
  if (mpfr_cmp (s, z))
    {
      printf ("Error in mpfr_zeta, prec=34, MPFR_RNDD\n");
      mpfr_dump (z);
      exit (1);
    }

  /* bug found by nightly tests on June 7, 2007 */
  mpfr_set_prec (s, 23);
  mpfr_set_prec (z, 25);
  mpfr_set_str_binary (s, "-1.0110110110001000000000e-27");
  mpfr_zeta (z, s, MPFR_RNDN);
  mpfr_set_prec (s, 25);
  mpfr_set_str_binary (s, "-1.111111111111111111111111e-2");
  if (mpfr_cmp (s, z))
    {
      printf ("Error in mpfr_zeta, prec=25, MPFR_RNDN\n");
      printf ("expected "); mpfr_dump (s);
      printf ("got      "); mpfr_dump (z);
      exit (1);
    }

  /* bug reported by Kevin Rauch on 26 Oct 2007 */
  mpfr_set_prec (s, 128);
  mpfr_set_prec (z, 128);
  mpfr_set_str_binary (s, "-0.1000000000000000000000000000000000000000000000000000000000000001E64");
  inex = mpfr_zeta (z, s, MPFR_RNDN);
  MPFR_ASSERTN (mpfr_inf_p (z) && MPFR_SIGN (z) < 0 && inex < 0);
  inex = mpfr_zeta (z, s, MPFR_RNDU);
  mpfr_set_inf (s, -1);
  mpfr_nextabove (s);
  MPFR_ASSERTN (mpfr_equal_p (z, s) && inex > 0);

  mpfr_clear (s);
  mpfr_clear (y);
  mpfr_clear (z);

  test_generic (2, 70, 5);
  test2 ();

  tests_end_mpfr ();
  return 0;
}
예제 #6
0
파일: cos.c 프로젝트: Distrotech/mpfr
int
mpfr_cos (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  mpfr_prec_t K0, K, precy, m, k, l;
  int inexact, reduce = 0;
  mpfr_t r, s, xr, c;
  mpfr_exp_t exps, cancel = 0, expx;
  MPFR_ZIV_DECL (loop);
  MPFR_SAVE_EXPO_DECL (expo);
  MPFR_GROUP_DECL (group);

  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,
     inexact));

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
        {
          MPFR_SET_NAN (y);
          MPFR_RET_NAN;
        }
      else
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          return mpfr_set_ui (y, 1, rnd_mode);
        }
    }

  MPFR_SAVE_EXPO_MARK (expo);

  /* cos(x) = 1-x^2/2 + ..., so error < 2^(2*EXP(x)-1) */
  expx = MPFR_GET_EXP (x);
  MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (y, __gmpfr_one, -2 * expx,
                                    1, 0, rnd_mode, expo, {});

  /* Compute initial precision */
  precy = MPFR_PREC (y);

  if (precy >= MPFR_SINCOS_THRESHOLD)
    {
      MPFR_SAVE_EXPO_FREE (expo);
      return mpfr_cos_fast (y, x, rnd_mode);
    }

  K0 = __gmpfr_isqrt (precy / 3);
  m = precy + 2 * MPFR_INT_CEIL_LOG2 (precy) + 2 * K0;

  if (expx >= 3)
    {
      reduce = 1;
      /* As expx + m - 1 will silently be converted into mpfr_prec_t
         in the mpfr_init2 call, the assert below may be useful to
         avoid undefined behavior. */
      MPFR_ASSERTN (expx + m - 1 <= MPFR_PREC_MAX);
      mpfr_init2 (c, expx + m - 1);
      mpfr_init2 (xr, m);
    }

  MPFR_GROUP_INIT_2 (group, m, r, s);
  MPFR_ZIV_INIT (loop, m);
  for (;;)
    {
      /* If |x| >= 4, first reduce x cmod (2*Pi) into xr, using mpfr_remainder:
         let e = EXP(x) >= 3, and m the target precision:
         (1) c <- 2*Pi              [precision e+m-1, nearest]
         (2) xr <- remainder (x, c) [precision m, nearest]
         We have |c - 2*Pi| <= 1/2ulp(c) = 2^(3-e-m)
                 |xr - x - k c| <= 1/2ulp(xr) <= 2^(1-m)
                 |k| <= |x|/(2*Pi) <= 2^(e-2)
         Thus |xr - x - 2kPi| <= |k| |c - 2Pi| + 2^(1-m) <= 2^(2-m).
         It follows |cos(xr) - cos(x)| <= 2^(2-m). */
      if (reduce)
        {
          mpfr_const_pi (c, MPFR_RNDN);
          mpfr_mul_2ui (c, c, 1, MPFR_RNDN); /* 2Pi */
          mpfr_remainder (xr, x, c, MPFR_RNDN);
          if (MPFR_IS_ZERO(xr))
            goto ziv_next;
          /* now |xr| <= 4, thus r <= 16 below */
          mpfr_mul (r, xr, xr, MPFR_RNDU); /* err <= 1 ulp */
        }
      else
        mpfr_mul (r, x, x, MPFR_RNDU); /* err <= 1 ulp */

      /* now |x| < 4 (or xr if reduce = 1), thus |r| <= 16 */

      /* we need |r| < 1/2 for mpfr_cos2_aux, i.e., EXP(r) - 2K <= -1 */
      K = K0 + 1 + MAX(0, MPFR_GET_EXP(r)) / 2;
      /* since K0 >= 0, if EXP(r) < 0, then K >= 1, thus EXP(r) - 2K <= -3;
         otherwise if EXP(r) >= 0, then K >= 1/2 + EXP(r)/2, thus
         EXP(r) - 2K <= -1 */

      MPFR_SET_EXP (r, MPFR_GET_EXP (r) - 2 * K); /* Can't overflow! */

      /* s <- 1 - r/2! + ... + (-1)^l r^l/(2l)! */
      l = mpfr_cos2_aux (s, r);
      /* l is the error bound in ulps on s */
      MPFR_SET_ONE (r);
      for (k = 0; k < K; k++)
        {
          mpfr_sqr (s, s, MPFR_RNDU);            /* err <= 2*olderr */
          MPFR_SET_EXP (s, MPFR_GET_EXP (s) + 1); /* Can't overflow */
          mpfr_sub (s, s, r, MPFR_RNDN);         /* err <= 4*olderr */
          if (MPFR_IS_ZERO(s))
            goto ziv_next;
          MPFR_ASSERTD (MPFR_GET_EXP (s) <= 1);
        }

      /* The absolute error on s is bounded by (2l+1/3)*2^(2K-m)
         2l+1/3 <= 2l+1.
         If |x| >= 4, we need to add 2^(2-m) for the argument reduction
         by 2Pi: if K = 0, this amounts to add 4 to 2l+1/3, i.e., to add
         2 to l; if K >= 1, this amounts to add 1 to 2*l+1/3. */
      l = 2 * l + 1;
      if (reduce)
        l += (K == 0) ? 4 : 1;
      k = MPFR_INT_CEIL_LOG2 (l) + 2*K;
      /* now the error is bounded by 2^(k-m) = 2^(EXP(s)-err) */

      exps = MPFR_GET_EXP (s);
      if (MPFR_LIKELY (MPFR_CAN_ROUND (s, exps + m - k, precy, rnd_mode)))
        break;

      if (MPFR_UNLIKELY (exps == 1))
        /* s = 1 or -1, and except x=0 which was already checked above,
           cos(x) cannot be 1 or -1, so we can round if the error is less
           than 2^(-precy) for directed rounding, or 2^(-precy-1) for rounding
           to nearest. */
        {
          if (m > k && (m - k >= precy + (rnd_mode == MPFR_RNDN)))
            {
              /* If round to nearest or away, result is s = 1 or -1,
                 otherwise it is round(nexttoward (s, 0)). However in order to
                 have the inexact flag correctly set below, we set |s| to
                 1 - 2^(-m) in all cases. */
              mpfr_nexttozero (s);
              break;
            }
        }

      if (exps < cancel)
        {
          m += cancel - exps;
          cancel = exps;
        }

    ziv_next:
      MPFR_ZIV_NEXT (loop, m);
      MPFR_GROUP_REPREC_2 (group, m, r, s);
      if (reduce)
        {
          mpfr_set_prec (xr, m);
          mpfr_set_prec (c, expx + m - 1);
        }
    }
  MPFR_ZIV_FREE (loop);
  inexact = mpfr_set (y, s, rnd_mode);
  MPFR_GROUP_CLEAR (group);
  if (reduce)
    {
      mpfr_clear (xr);
      mpfr_clear (c);
    }

  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (y, inexact, rnd_mode);
}
예제 #7
0
static void
check_small (void)
{
  mpfr_t x;
  char *s;
  mpfr_exp_t e;
  mpfr_prec_t p;

  mpfr_init (x);

  mpfr_set_prec (x, 20);
  mpfr_set_ui (x, 2, MPFR_RNDN);
  mpfr_nexttozero (x);
  s = mpfr_get_str (NULL, &e, 4, 2, x, MPFR_RNDU);
  if (strcmp (s, "20") || (e != 1))
    {
      printf ("Error in mpfr_get_str: 2- rounded up with 2 digits"
              " in base 4\n");
      exit (1);
    }
  mpfr_free_str (s);

  /* check n_digits=0 */
  mpfr_set_prec (x, 5);
  mpfr_set_ui (x, 17, MPFR_RNDN);
  s = mpfr_get_str (NULL, &e, 3, 0, x, MPFR_RNDN);
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 36, 0, x, MPFR_RNDN);
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 62, 0, x, MPFR_RNDN);
  mpfr_free_str (s);

  mpfr_set_prec (x, 64);
  mpfr_set_si (x, -1, MPFR_RNDN);
  mpfr_div_2exp (x, x, 63, MPFR_RNDN); /* x = -2^(-63) */
  mpfr_add_ui (x, x, 1, MPFR_RNDN); /* x = 1 - 2^(-63) */
  mpfr_mul_2exp (x, x, 32, MPFR_RNDN); /* x = 2^32 - 2^(-31) */
  s = mpfr_get_str (NULL, &e, 3, 21, x, MPFR_RNDU);
  if (strcmp (s, "102002022201221111211") || (e != 21))
    {
      printf ("Error in mpfr_get_str: 2^32-2^(-31) rounded up with"
              " 21 digits in base 3\n");
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 3, 20, x, MPFR_RNDU);
  if (strcmp (s, "10200202220122111122") || (e != 21))
    {
      printf ("Error in mpfr_get_str: 2^32-2^(-31) rounded up with"
              " 20 digits in base 3\n");
      exit (1);
    }
  mpfr_free_str (s);

  /* check corner case ret!=0, j0!=0 in mpfr_get_str_aux */
  mpfr_set_prec (x, 100);
  mpfr_set_str_binary (x, "0.1001011111010001101110010101010101111001010111111101101101100110100011110110000101110110001011110000E-9");
  s = mpfr_get_str (NULL, &e, 3, 2, x, MPFR_RNDU);
  if (strcmp (s, "22") || (e != -6))
    {
      printf ("Error in mpfr_get_str: 100-bit number rounded up with"
              " 2 digits in base 3\n");
      exit (1);
    }
  mpfr_free_str (s);

  /* check corner case exact=0 in mpfr_get_str_aux */
  mpfr_set_prec (x, 100);
  mpfr_set_str_binary (x, "0.1001001111101101111000101000110111111010101100000110010001111111011001101011101100001100110000000000E8");
  s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDZ);
  if (strcmp (s, "14") || (e != 3))
    {
      printf ("Error in mpfr_get_str: 100-bit number rounded to zero with"
              " 2 digits in base 10\n");
      exit (1);
    }
  mpfr_free_str (s);

  for (p=4; p<=200; p++)
    {
      mpfr_set_prec (x, p);
      mpfr_set_str (x, "6.5", 10, MPFR_RNDN);

      s = mpfr_get_str (NULL, &e, 6, 2, x, MPFR_RNDN);
      if (strcmp (s, "10") || (e != 2))
        {
          printf ("Error in mpfr_get_str: 6.5 rounded to nearest with"
                  " 2 digits in base 6\n");
          exit (1);
        }
      mpfr_free_str (s);

      mpfr_nexttoinf (x);
      s = mpfr_get_str (NULL, &e, 6, 2, x, MPFR_RNDN);
      if (strcmp (s, "11") || (e != 2))
        {
          printf ("Error in mpfr_get_str: 6.5+ rounded to nearest with"
                  " 2 digits in base 6\ngot %se%d instead of 11e2\n",
                  s, (int) e);
          exit (1);
        }
      mpfr_free_str (s);

      mpfr_set_str (x, "6.5", 10, MPFR_RNDN);
      mpfr_nexttozero (x);
      s = mpfr_get_str (NULL, &e, 6, 2, x, MPFR_RNDN);
      if (strcmp (s, "10") || (e != 2))
        {
          printf ("Error in mpfr_get_str: 6.5- rounded to nearest with"
                  " 2 digits in base 6\n");
          exit (1);
        }
      mpfr_free_str (s);
    }

  mpfr_set_prec (x, 3);
  mpfr_set_ui (x, 7, MPFR_RNDN);
  s = mpfr_get_str (NULL, &e, 2, 2, x, MPFR_RNDU);
  if (strcmp (s, "10") || (e != 4))
    {
      printf ("Error in mpfr_get_str: 7 rounded up with 2 bits should"
              " give 0.10e3 instead of 0.%s*2^%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* problem found by Fabrice Rouillier */
  mpfr_set_prec (x, 63);
  mpfr_set_str (x, "5e14", 10, MPFR_RNDN);
  s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDU);
  mpfr_free_str (s);

  /* bug found by Johan Vervloet */
  mpfr_set_prec (x, 6);
  mpfr_set_str (x, "688.0", 10, MPFR_RNDN);
  s = mpfr_get_str (NULL, &e, 2, 4, x, MPFR_RNDU);
  if (strcmp (s, "1011") || (e != 10))
    {
      printf ("Error in mpfr_get_str: 688 printed up to 4 bits should"
              " give 1.011e9\ninstead of ");
      mpfr_out_str (stdout, 2, 4, x, MPFR_RNDU);
      puts ("");
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_prec (x, 38);
  mpfr_set_str_binary (x, "1.0001110111110100011010100010010100110e-6");
  s = mpfr_get_str (NULL, &e, 8, 10, x, MPFR_RNDU);
  if (strcmp (s, "1073721522") || (e != -1))
    {
      printf ("Error in mpfr_get_str (3): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_prec (x, 53);
  mpfr_set_str_binary (x, "0.11010111011101100010000100010101110001000000010111001E454");
  s = mpfr_get_str (NULL, &e, 19, 12, x, MPFR_RNDU);
  if (strcmp (s, "b1cgfa4gha0h") || (e != 107))
    {
      printf ("Error in mpfr_get_str (4): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_prec (x, 145);
  mpfr_set_str_binary (x, "-0.1000110011000001011000010101101010110110101100101110100011111100011110011001001001010000100001000011000011000000010111011001000111101001110100110e6");
  s = mpfr_get_str (NULL, &e, 4, 53, x, MPFR_RNDU);
  if (strcmp (s, "-20303001120111222312230232203330132121021100201003003") || (e != 3))
    {
      printf ("Error in mpfr_get_str (5): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_prec (x, 45);
  mpfr_set_str_binary (x, "-0.00100111010110010001011001110111010001010010010");
  s = mpfr_get_str (NULL, &e, 32, 9, x, MPFR_RNDN);
  if (strcmp (s, "-4tchctq54") || (e != 0))
    {
      printf ("Error in mpfr_get_str (6): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* worst case found by Vincent Lefe`vre */
  mpfr_set_prec (x, 53);
  mpfr_set_str_binary (x, "10011110111100000000001011011110101100010000011011111E164");
  s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN);
  if (strcmp (s, "13076622631878654") || (e != 66))
    {
      printf ("Error in mpfr_get_str (7): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10000001001001001100011101010011011011111000011000100E93");
  s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDU);
  if (strcmp (s, "46") || e != 44)
    {
       printf ("Error in mpfr_get_str (8): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10010001111100000111001111010101001010000010111010101E55");
  s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDN);
  if (strcmp (s, "19") || e != 33)
    {
       printf ("Error in mpfr_get_str (9): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "11011001010010111110010101101100111110111000010110110E44");
  s = mpfr_get_str (NULL, &e, 10, 3, x, MPFR_RNDN);
  if (strcmp (s, "135") || e != 30)
    {
       printf ("Error in mpfr_get_str (10): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "11101111101000001011100001111000011111101111011001100E72");
  s = mpfr_get_str (NULL, &e, 10, 4, x, MPFR_RNDN);
  if (strcmp (s, "3981") || e != 38)
    {
       printf ("Error in mpfr_get_str (11): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10011001001100100010111100001101110101001001111110000E46");
  s = mpfr_get_str (NULL, &e, 10, 5, x, MPFR_RNDN);
  if (strcmp (s, "37930") || e != 30)
    {
       printf ("Error in mpfr_get_str (12): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10001100110111001011011110011011011101100011010001011E-72");
  s = mpfr_get_str (NULL, &e, 10, 6, x, MPFR_RNDN);
  if (strcmp (s, "104950") || e != -5)
    {
       printf ("Error in mpfr_get_str (13): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "10100100001011001000011001101101000110100110000010111E89");
  s = mpfr_get_str (NULL, &e, 10, 7, x, MPFR_RNDN);
  if (strcmp (s, "3575392") || e != 43)
    {
       printf ("Error in mpfr_get_str (14): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "11000011011110110010100110001010000001010011001011001E-73");
  s = mpfr_get_str (NULL, &e, 10, 8, x, MPFR_RNDN);
  if (strcmp (s, "72822386") || e != -6)
    {
       printf ("Error in mpfr_get_str (15): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "10101010001101000111001100001000100011100010010001010E78");
  s = mpfr_get_str (NULL, &e, 10, 9, x, MPFR_RNDN);
  if (strcmp (s, "180992873") || e != 40)
    {
      printf ("Error in mpfr_get_str (16): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "10110111001000100000001101111001100101101110011011101E91");
  s = mpfr_get_str (NULL, &e, 10, 10, x, MPFR_RNDN);
  if (strcmp (s, "1595312255") || e != 44)
    {
      printf ("Error in mpfr_get_str (17): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E93");
  s = mpfr_get_str (NULL, &e, 10, 11, x, MPFR_RNDN);
  if (strcmp (s, "54835744350") || e != 44)
    {
      printf ("Error in mpfr_get_str (18): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E92");
  s = mpfr_get_str (NULL, &e, 10, 12, x, MPFR_RNDN);
  if (strcmp (s, "274178721752") || e != 44)
    {
      printf ("Error in mpfr_get_str (19): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10011101010111101111000100111011101011110100110110101E91");
  s = mpfr_get_str (NULL, &e, 10, 13, x, MPFR_RNDN);
  if (strcmp (s, "1370893608762") || e != 44)
    {
      printf ("Error in mpfr_get_str (20): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "10010011010110011100010010100101100011101000011111111E92");
  s = mpfr_get_str (NULL, &e, 10, 14, x, MPFR_RNDN);
  if (strcmp (s, "25672105101864") || e != 44)
    {
      printf ("Error in mpfr_get_str (21): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "100110111110110001000101110100100101101000011111001E87");
  s = mpfr_get_str (NULL, &e, 10, 15, x, MPFR_RNDN);
  if (strcmp (s, "212231308858721") || e != 42)
    {
      printf ("Error in mpfr_get_str (22): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10111010110000111000101100101111001011011100101001111E-128");
  s = mpfr_get_str (NULL, &e, 10, 15, x, MPFR_RNDN);
  if (strcmp (s, "193109287087290") || e != -22)
    {
      printf ("Error in mpfr_get_str (22b): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "10001101101011010001111110000111010111010000110101010E80");
  s = mpfr_get_str (NULL, &e, 10, 16, x, MPFR_RNDN);
  if (strcmp (s, "6026241735727920") || e != 40)
    {
      printf ("Error in mpfr_get_str (23): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "100010001011101001110101000110011001001000110001001E-81");
  s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN);
  if (strcmp (s, "49741483709103481") || e != -9)
    {
      printf ("Error in mpfr_get_str (24): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "11000100001001001110111010011001111001001010110101111E-101");
  s = mpfr_get_str (NULL, &e, 10, 7, x, MPFR_RNDN);
  if (strcmp (s, "2722049") || e != -14)
    {
      printf ("Error in mpfr_get_str (25): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "11111001010011100101000001111111110001001001110110001E-135");
  s = mpfr_get_str (NULL, &e, 10, 8, x, MPFR_RNDN);
  if (strcmp (s, "20138772") || e != -24)
    {
      printf ("Error in mpfr_get_str (26): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "11111001010011100101000001111111110001001001110110001E-136");
  s = mpfr_get_str (NULL, &e, 10, 9, x, MPFR_RNDN);
  if (strcmp (s, "100693858") || e != -24)
    {
      printf ("Error in mpfr_get_str (27): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
    mpfr_free_str (s);
  mpfr_set_str_binary (x, "10001000001110010110001011111011111011011010000110001E-110");
  s = mpfr_get_str (NULL, &e, 10, 14, x, MPFR_RNDN);
  if (strcmp (s, "36923634350619") || e != -17)
    {
      printf ("Error in mpfr_get_str (28): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "11001100010111000111100010000110011101110001000101111E-87");
  s = mpfr_get_str (NULL, &e, 10, 16, x, MPFR_RNDN);
  if (strcmp (s, "4646636036100804") || e != -10)
    {
      printf ("Error in mpfr_get_str (29): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "10011111001111110100001001010111111011010101111111000E-99");
  s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN);
  if (strcmp (s, "88399901882446712") || e != -14)
    {
      printf ("Error in mpfr_get_str (30): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 8116315218207718*2^(-293) ~ 0.5100000000000000000015*10^(-72) */
  mpfr_set_str_binary (x, "11100110101011011111011100101011101110110001111100110E-293");
  s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDU);
  if (strcmp (s, "52") || e != -72)
    {
      printf ("Error in mpfr_get_str (31u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDD);
  if (strcmp (s, "51") || e != -72)
    {
      printf ("Error in mpfr_get_str (31d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 6712731423444934*2^536 ~ .151000000000000000000067*10^178 */
  mpfr_set_str_binary (x, "10111110110010011000110010011111101111000111111000110E536");
  s = mpfr_get_str (NULL, &e, 10, 3, x, MPFR_RNDU);
  if (strcmp (s, "152") || e != 178)
    {
      printf ("Error in mpfr_get_str (32u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 3, x, MPFR_RNDD);
  if (strcmp (s, "151") || e != 178)
    {
      printf ("Error in mpfr_get_str (32d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 3356365711722467*2^540 ~ .120800000000000000000054*10^179 */
  mpfr_set_str_binary (x, "1011111011001001100011001001111110111100011111100011E540");
  s = mpfr_get_str (NULL, &e, 10, 4, x, MPFR_RNDU);
  if (strcmp (s, "1209") || e != 179)
    {
      printf ("Error in mpfr_get_str (33u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 4, x, MPFR_RNDD);
  if (strcmp (s, "1208") || e != 179)
    {
      printf ("Error in mpfr_get_str (33d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 6475049196144587*2^100 ~ .8208099999999999999999988*10^46 */
  mpfr_set_str_binary (x, "10111000000010000010111011111001111010100011111001011E100");
  s = mpfr_get_str (NULL, &e, 10, 5, x, MPFR_RNDU);
  if (strcmp (s, "82081") || e != 46)
    {
      printf ("Error in mpfr_get_str (34u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 5, x, MPFR_RNDD);
  if (strcmp (s, "82080") || e != 46)
    {
      printf ("Error in mpfr_get_str (34d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 6722280709661868*2^364 ~ .25260100000000000000000012*10^126 */
  mpfr_set_str_binary (x, "10111111000011110000011110001110001111010010010101100E364");
  s = mpfr_get_str (NULL, &e, 10, 6, x, MPFR_RNDU);
  if (strcmp (s, "252602") || e != 126)
    {
      printf ("Error in mpfr_get_str (35u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 6, x, MPFR_RNDD);
  if (strcmp (s, "252601") || e != 126)
    {
      printf ("Error in mpfr_get_str (35d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 5381065484265332*2^(-455) ~ .578389299999999999999999982*10^(-121) */
  mpfr_set_str_binary (x, "10011000111100000110011110000101100111110011101110100E-455");
  s = mpfr_get_str (NULL, &e, 10, 7, x, MPFR_RNDU);
  if (strcmp (s, "5783893") || e != -121)
    {
      printf ("Error in mpfr_get_str (36u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 7, x, MPFR_RNDD);
  if (strcmp (s, "5783892") || e != -121)
    {
      printf ("Error in mpfr_get_str (36d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 8369123604277281*2^(-852) ~ .27869147000000000000000000056*10^(-240) */
  mpfr_set_str_binary (x, "11101101110111010110001101111100000111010100000100001E-852");
  s = mpfr_get_str (NULL, &e, 10, 8, x, MPFR_RNDU);
  if (strcmp (s, "27869148") || e != -240)
    {
      printf ("Error in mpfr_get_str (37u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 8, x, MPFR_RNDD);
  if (strcmp (s, "27869147") || e != -240)
    {
      printf ("Error in mpfr_get_str (37d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 7976538478610756*2^377 ~ .245540326999999999999999999982*10^130 */
  mpfr_set_str_binary (x, "11100010101101001111010010110100011100000100101000100E377");
  s = mpfr_get_str (NULL, &e, 10, 9, x, MPFR_RNDU);
  if (strcmp (s, "245540327") || e != 130)
    {
      printf ("Error in mpfr_get_str (38u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 9, x, MPFR_RNDD);
  if (strcmp (s, "245540326") || e != 130)
    {
      printf ("Error in mpfr_get_str (38d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 8942832835564782*2^(-382) ~ .9078555839000000000000000000038*10^(-99) */
  mpfr_set_str_binary (x, "11111110001010111010110000110011100110001010011101110E-382");
  s = mpfr_get_str (NULL, &e, 10, 10, x, MPFR_RNDU);
  if (strcmp (s, "9078555840") || e != -99)
    {
      printf ("Error in mpfr_get_str (39u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 10, x, MPFR_RNDD);
  if (strcmp (s, "9078555839") || e != -99)
    {
      printf ("Error in mpfr_get_str (39d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 4471416417782391*2^(-380) ~ .18157111678000000000000000000077*10^(-98) */
  mpfr_set_str_binary (x, "1111111000101011101011000011001110011000101001110111E-380");
  s = mpfr_get_str (NULL, &e, 10, 11, x, MPFR_RNDU);
  if (strcmp (s, "18157111679") || e != -98)
    {
      printf ("Error in mpfr_get_str (40u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 11, x, MPFR_RNDD);
  if (strcmp (s, "18157111678") || e != -98)
    {
      printf ("Error in mpfr_get_str (40d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 7225450889282194*2^711 ~ .778380362292999999999999999999971*10^230 */
  mpfr_set_str_binary (x, "11001101010111000001001100001100110010000001010010010E711");
  s = mpfr_get_str (NULL, &e, 10, 12, x, MPFR_RNDU);
  if (strcmp (s, "778380362293") || e != 230)
    {
      printf ("Error in mpfr_get_str (41u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 12, x, MPFR_RNDD);
  if (strcmp (s, "778380362292") || e != 230)
    {
      printf ("Error in mpfr_get_str (41d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 3612725444641097*2^713 ~ .1556760724585999999999999999999942*10^231 */
  mpfr_set_str_binary (x, "1100110101011100000100110000110011001000000101001001E713");
  s = mpfr_get_str (NULL, &e, 10, 13, x, MPFR_RNDU);
  if (strcmp (s, "1556760724586") || e != 231)
    {
      printf ("Error in mpfr_get_str (42u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 13, x, MPFR_RNDD);
  if (strcmp (s, "1556760724585") || e != 231)
    {
      printf ("Error in mpfr_get_str (42d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 6965949469487146*2^(-248) ~ .15400733123779000000000000000000016*10^(-58) */
  mpfr_set_str_binary (x, "11000101111110111111001111111101001101111000000101010E-248");
  s = mpfr_get_str (NULL, &e, 10, 14, x, MPFR_RNDU);
  if (strcmp (s, "15400733123780") || e != -58)
    {
      printf ("Error in mpfr_get_str (43u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 14, x, MPFR_RNDD);
  if (strcmp (s, "15400733123779") || e != -58)
    {
      printf ("Error in mpfr_get_str (43d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 3482974734743573*2^(-244) ~ .12320586499023200000000000000000013*10^(-57) */
  mpfr_set_str_binary (x, "1100010111111011111100111111110100110111100000010101E-244");
  s = mpfr_get_str (NULL, &e, 10, 15, x, MPFR_RNDU);
  if (strcmp (s, "123205864990233") || e != -57)
    {
      printf ("Error in mpfr_get_str (44u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 15, x, MPFR_RNDD);
  if (strcmp (s, "123205864990232") || e != -57)
    {
      printf ("Error in mpfr_get_str (44d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 7542952370752766*2^(-919) ~ .170206189963739699999999999999999974*10^(-260) */
  mpfr_set_str_binary (x, "11010110011000100011001110100100111011100110011111110E-919");
  s = mpfr_get_str (NULL, &e, 10, 16, x, MPFR_RNDU);
  if (strcmp (s, "1702061899637397") || e != -260)
    {
      printf ("Error in mpfr_get_str (45u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 16, x, MPFR_RNDD);
  if (strcmp (s, "1702061899637396") || e != -260)
    {
      printf ("Error in mpfr_get_str (45d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  /* 5592117679628511*2^165 ~ .26153245263757307000000000000000000074*10^66 */
  mpfr_set_str_binary (x, "10011110111100000000001011011110101100010000011011111E165");
  s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDU);
  if (strcmp (s, "26153245263757308") || e != 66)
    {
      printf ("Error in mpfr_get_str (46u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDD);
  if (strcmp (s, "26153245263757307") || e != 66)
    {
      printf ("Error in mpfr_get_str (46d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "11010010110111100001011010000110010000100001011011101E1223");
  s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN);
  if (strcmp (s, "10716284017294180") || e != 385)
    {
      printf ("Error in mpfr_get_str (47n): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDU);
  if (strcmp (s, "107162840172941805") || e != 385)
    {
      printf ("Error in mpfr_get_str (47u): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDD);
  if (strcmp (s, "107162840172941804") || e != 385)
    {
      printf ("Error in mpfr_get_str (47d): s=%s e=%d\n", s, (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_str_binary (x, "11111101111011000001010100001101101000010010001111E122620");
  s = mpfr_get_str (NULL, &e, 10, 17, x, MPFR_RNDN);
  if (strcmp (s, "22183435284042374") || e != 36928)
    {
      printf ("Error in mpfr_get_str (48n): s=%s e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDU);
  if (strcmp (s, "221834352840423736") || e != 36928)
    {
      printf ("Error in mpfr_get_str (48u): s=%s e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);
  s = mpfr_get_str (NULL, &e, 10, 18, x, MPFR_RNDD);
  if (strcmp (s, "221834352840423735") || e != 36928)
    {
      printf ("Error in mpfr_get_str (48d): s=%s e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_prec (x, 45);
  mpfr_set_str_binary (x, "1E45");
  s = mpfr_get_str (NULL, &e, 32, 9, x, MPFR_RNDN);
  mpfr_free_str (s);

  mpfr_set_prec (x, 7);
  mpfr_set_str_binary (x, "0.1010101E10");
  s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDU);
  mpfr_free_str (s);

  /* checks rounding of negative numbers */
  mpfr_set_prec (x, 7);
  mpfr_set_str (x, "-11.5", 10, MPFR_RNDN);
  s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDD);
  if (strcmp (s, "-12"))
    {
      printf ("Error in mpfr_get_str for x=-11.5 and rnd=MPFR_RNDD\n"
              "got %s instead of -12\n", s);
      exit (1);
  }
  mpfr_free_str (s);

  s = mpfr_get_str (NULL, &e, 10, 2, x, MPFR_RNDU);
  if (strcmp (s, "-11"))
    {
      printf ("Error in mpfr_get_str for x=-11.5 and rnd=MPFR_RNDU\n");
      exit (1);
    }
  mpfr_free_str (s);

  /* bug found by Jean-Pierre Merlet, produced error in mpfr_get_str */
  mpfr_set_prec (x, 128);
  mpfr_set_str_binary (x, "0.10111001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011010E3");
  s = mpfr_get_str (NULL, &e, 10, 0, x, MPFR_RNDU);
  mpfr_free_str (s);

  mpfr_set_prec (x, 381);
  mpfr_set_str_binary (x, "0.111111111111111111111111111111111111111111111111111111111111111111101110110000100110011101101101001010111000101111000100100011110101010110101110100000010100001000110100000100011111001000010010000010001010111001011110000001110010111101100001111000101101100000010110000101100100000101010110010110001010100111001111100011100101100000100100111001100010010011110011011010110000001000010");
  s = mpfr_get_str (NULL, &e, 10, 0, x, MPFR_RNDD);
  if (e != 0)
    {
      printf ("Error in mpfr_get_str for x=0.999999..., exponent is %d"
              " instead of 0\n", (int) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_prec (x, 5);
  mpfr_set_str_binary (x, "1101.1"); /* 13.5, or (16)_7 + 1/2 */
  s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN);
  /* we are in the tie case: both surrounding numbers are (16)_7 and
     (20)_7: since (16)_7 = 13 is odd and (20)_7 = 14 is even,
     we should have s = "20" and e = 2 */
  if (e != 2 || strcmp (s, "20"))
    {
      printf ("Error in mpfr_get_str for x=13.5, base 7\n");
      printf ("Expected s=20, e=2, got s=%s, e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);
  /* try the same example, with input just below or above 13.5 */
  mpfr_set_prec (x, 1000);
  mpfr_set_str_binary (x, "1101.1");
  mpfr_nextabove (x);
  s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN);
  if (e != 2 || strcmp (s, "20"))
    {
      printf ("Error in mpfr_get_str for x=13.5+tiny, base 7\n");
      printf ("Expected s=20, e=2, got s=%s, e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "1101.1");
  mpfr_nextbelow (x);
  s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN);
  if (e != 2 || strcmp (s, "16"))
    {
      printf ("Error in mpfr_get_str for x=13.5-tiny, base 7\n");
      printf ("Expected s=16, e=2, got s=%s, e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_set_prec (x, 7);
  mpfr_set_str_binary (x, "110000.1"); /* 48.5, or (66)_7 + 1/2 */
  s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN);
  /* we are in the tie case: both surrounding numbers are (66)_7 and
     (100)_7: since (66)_7 = 48 is even and (100)_7 is odd,
     we should hase s = "66" and e = 2 */
  if (e != 2 || strcmp (s, "66"))
    {
      printf ("Error in mpfr_get_str for x=48.5, base 7\n");
      printf ("Expected s=66, e=2, got s=%s, e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);
  /* try the same example, with input just below or above 48.5 */
  mpfr_set_prec (x, 1000);
  mpfr_set_str_binary (x, "110000.1");
  mpfr_nextabove (x);
  s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN);
  if (e != 3 || strcmp (s, "10"))
    {
      printf ("Error in mpfr_get_str for x=48.5+tiny, base 7\n");
      printf ("Expected s=10, e=3, got s=%s, e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);
  mpfr_set_str_binary (x, "110000.1");
  mpfr_nextbelow (x);
  s = mpfr_get_str (NULL, &e, 7, 2, x, MPFR_RNDN);
  if (e != 2 || strcmp (s, "66"))
    {
      printf ("Error in mpfr_get_str for x=48.5-tiny, base 7\n");
      printf ("Expected s=66, e=2, got s=%s, e=%ld\n", s, (long) e);
      exit (1);
    }
  mpfr_free_str (s);

  mpfr_clear (x);
}
예제 #8
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
}
예제 #9
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
}