Пример #1
0
int
mpfr_check_range (mpfr_ptr x, mp_rnd_t rnd_mode)
{
  if (MPFR_IS_FP(x) && MPFR_NOTZERO(x))
    { /* x is a non-zero FP */
      mp_exp_t exp = MPFR_EXP(x);
      if (exp < __mpfr_emin)
        return mpfr_set_underflow(x, rnd_mode, MPFR_SIGN(x));
      if (exp > __mpfr_emax)
        return mpfr_set_overflow(x, rnd_mode, MPFR_SIGN(x));
    }
  return 0;
}
Пример #2
0
int
mpfr_get_z (mpz_ptr z, mpfr_srcptr f, mpfr_rnd_t rnd)
{
  int inex;
  mpfr_t r;
  mpfr_exp_t exp;
  MPFR_SAVE_EXPO_DECL (expo);

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f)))
    {
      if (MPFR_UNLIKELY (MPFR_NOTZERO (f)))
        MPFR_SET_ERANGEFLAG ();
      mpz_set_ui (z, 0);
      /* The ternary value is 0 even for infinity. Giving the rounding
         direction in this case would not make much sense anyway, and
         the direction would not necessarily match rnd. */
      return 0;
    }

  MPFR_SAVE_EXPO_MARK (expo);

  exp = MPFR_GET_EXP (f);
  /* if exp <= 0, then |f|<1, thus |o(f)|<=1 */
  MPFR_ASSERTN (exp < 0 || exp <= MPFR_PREC_MAX);
  mpfr_init2 (r, (exp < (mpfr_exp_t) MPFR_PREC_MIN ?
                  MPFR_PREC_MIN : (mpfr_prec_t) exp));
  inex = mpfr_rint (r, f, rnd);
  MPFR_ASSERTN (inex != 1 && inex != -1); /* integral part of f is
                                             representable in r */
  MPFR_ASSERTN (MPFR_IS_FP (r));

  /* The flags from mpfr_rint are the wanted ones. In particular,
     it sets the inexact flag when necessary. */
  MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);

  exp = mpfr_get_z_2exp (z, r);
  if (exp >= 0)
    mpz_mul_2exp (z, z, exp);
  else
    mpz_fdiv_q_2exp (z, z, -exp);
  mpfr_clear (r);

  MPFR_SAVE_EXPO_FREE (expo);

  return inex;
}
Пример #3
0
/* bug reported by Joseph S. Myers on 2013-10-27
   https://sympa.inria.fr/sympa/arc/mpfr/2013-10/msg00015.html */
static void
bug20131027 (void)
{
  mpfr_t sum, t[4];
  mpfr_ptr p[4];
  char *s[4] = {
    "0x1p1000",
    "-0x0.fffffffffffff80000000000000001p1000",
    "-0x1p947",
    "0x1p880"
  };
  int i, r;

  mpfr_init2 (sum, 53);

  for (i = 0; i < 4; i++)
    {
      mpfr_init2 (t[i], i == 0 ? 53 : 1000);
      mpfr_set_str (t[i], s[i], 0, MPFR_RNDN);
      p[i] = t[i];
    }

  RND_LOOP(r)
    {
      int expected_sign = (mpfr_rnd_t) r == MPFR_RNDD ? -1 : 1;
      int inex;

      inex = mpfr_sum (sum, p, 4, (mpfr_rnd_t) r);

      if (MPFR_NOTZERO (sum) || MPFR_SIGN (sum) != expected_sign || inex != 0)
        {
          printf ("mpfr_sum incorrect in bug20131027 for %s:\n"
                  "expected %c0 with inex = 0, got ",
                  mpfr_print_rnd_mode ((mpfr_rnd_t) r),
                  expected_sign > 0 ? '+' : '-');
          mpfr_dump (sum);
          printf ("with inex = %d\n", inex);
          exit (1);
        }
    }

  for (i = 0; i < 4; i++)
    mpfr_clear (t[i]);
  mpfr_clear (sum);
}
Пример #4
0
int
mpfr_div_2si (mpfr_ptr y, mpfr_srcptr x, long int n, mp_rnd_t rnd_mode)
{
  int inexact;

  inexact = y != x ? mpfr_set (y, x, rnd_mode) : 0;

  if (MPFR_IS_FP(y) && MPFR_NOTZERO(y))
    {
      if (n > 0 && (__mpfr_emin > MPFR_EMAX_MAX - n ||
                    MPFR_EXP(y) < __mpfr_emin + n))
        return mpfr_set_underflow (y, rnd_mode, MPFR_SIGN(y));

      if (n < 0 && (__mpfr_emax < MPFR_EMIN_MIN - n ||
                    MPFR_EXP(y) > __mpfr_emax + n))
        return mpfr_set_overflow (y, rnd_mode, MPFR_SIGN(y));

      MPFR_EXP(y) -= n;
    }

  return inexact;
}
Пример #5
0
/* Assumes that the exponent range has already been extended and if y is
   an integer, then the result is not exact in unbounded exponent range. */
int
mpfr_pow_general (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y,
                  mpfr_rnd_t rnd_mode, int y_is_integer, mpfr_save_expo_t *expo)
{
  mpfr_t t, u, k, absx;
  int neg_result = 0;
  int k_non_zero = 0;
  int check_exact_case = 0;
  int inexact;
  /* Declaration of the size variable */
  mpfr_prec_t Nz = MPFR_PREC(z);               /* target precision */
  mpfr_prec_t Nt;                              /* working precision */
  mpfr_exp_t err;                              /* error */
  MPFR_ZIV_DECL (ziv_loop);


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

  /* We put the absolute value of x in absx, pointing to the significand
     of x to avoid allocating memory for the significand of absx. */
  MPFR_ALIAS(absx, x, /*sign=*/ 1, /*EXP=*/ MPFR_EXP(x));

  /* We will compute the absolute value of the result. So, let's
     invert the rounding mode if the result is negative. */
  if (MPFR_IS_NEG (x) && is_odd (y))
    {
      neg_result = 1;
      rnd_mode = MPFR_INVERT_RND (rnd_mode);
    }

  /* compute the precision of intermediary variable */
  /* the optimal number of bits : see algorithms.tex */
  Nt = Nz + 5 + MPFR_INT_CEIL_LOG2 (Nz);

  /* initialise of intermediary variable */
  mpfr_init2 (t, Nt);

  MPFR_ZIV_INIT (ziv_loop, Nt);
  for (;;)
    {
      MPFR_BLOCK_DECL (flags1);

      /* compute exp(y*ln|x|), using MPFR_RNDU to get an upper bound, so
         that we can detect underflows. */
      mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDD : MPFR_RNDU); /* ln|x| */
      mpfr_mul (t, y, t, MPFR_RNDU);                              /* y*ln|x| */
      if (k_non_zero)
        {
          MPFR_LOG_MSG (("subtract k * ln(2)\n", 0));
          mpfr_const_log2 (u, MPFR_RNDD);
          mpfr_mul (u, u, k, MPFR_RNDD);
          /* Error on u = k * log(2): < k * 2^(-Nt) < 1. */
          mpfr_sub (t, t, u, MPFR_RNDU);
          MPFR_LOG_MSG (("t = y * ln|x| - k * ln(2)\n", 0));
          MPFR_LOG_VAR (t);
        }
      /* estimate of the error -- see pow function in algorithms.tex.
         The error on t is at most 1/2 + 3*2^(EXP(t)+1) ulps, which is
         <= 2^(EXP(t)+3) for EXP(t) >= -1, and <= 2 ulps for EXP(t) <= -2.
         Additional error if k_no_zero: treal = t * errk, with
         1 - |k| * 2^(-Nt) <= exp(-|k| * 2^(-Nt)) <= errk <= 1,
         i.e., additional absolute error <= 2^(EXP(k)+EXP(t)-Nt).
         Total error <= 2^err1 + 2^err2 <= 2^(max(err1,err2)+1). */
      err = MPFR_NOTZERO (t) && MPFR_GET_EXP (t) >= -1 ?
        MPFR_GET_EXP (t) + 3 : 1;
      if (k_non_zero)
        {
          if (MPFR_GET_EXP (k) > err)
            err = MPFR_GET_EXP (k);
          err++;
        }
      MPFR_BLOCK (flags1, mpfr_exp (t, t, MPFR_RNDN));  /* exp(y*ln|x|)*/
      /* We need to test */
      if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (t) || MPFR_UNDERFLOW (flags1)))
        {
          mpfr_prec_t Ntmin;
          MPFR_BLOCK_DECL (flags2);

          MPFR_ASSERTN (!k_non_zero);
          MPFR_ASSERTN (!MPFR_IS_NAN (t));

          /* Real underflow? */
          if (MPFR_IS_ZERO (t))
            {
              /* Underflow. We computed rndn(exp(t)), where t >= y*ln|x|.
                 Therefore rndn(|x|^y) = 0, and we have a real underflow on
                 |x|^y. */
              inexact = mpfr_underflow (z, rnd_mode == MPFR_RNDN ? MPFR_RNDZ
                                        : rnd_mode, MPFR_SIGN_POS);
              if (expo != NULL)
                MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT
                                             | MPFR_FLAGS_UNDERFLOW);
              break;
            }

          /* Real overflow? */
          if (MPFR_IS_INF (t))
            {
              /* Note: we can probably use a low precision for this test. */
              mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDU : MPFR_RNDD);
              mpfr_mul (t, y, t, MPFR_RNDD);            /* y * ln|x| */
              MPFR_BLOCK (flags2, mpfr_exp (t, t, MPFR_RNDD));
              /* t = lower bound on exp(y * ln|x|) */
              if (MPFR_OVERFLOW (flags2))
                {
                  /* We have computed a lower bound on |x|^y, and it
                     overflowed. Therefore we have a real overflow
                     on |x|^y. */
                  inexact = mpfr_overflow (z, rnd_mode, MPFR_SIGN_POS);
                  if (expo != NULL)
                    MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT
                                                 | MPFR_FLAGS_OVERFLOW);
                  break;
                }
            }

          k_non_zero = 1;
          Ntmin = sizeof(mpfr_exp_t) * CHAR_BIT;
          if (Ntmin > Nt)
            {
              Nt = Ntmin;
              mpfr_set_prec (t, Nt);
            }
          mpfr_init2 (u, Nt);
          mpfr_init2 (k, Ntmin);
          mpfr_log2 (k, absx, MPFR_RNDN);
          mpfr_mul (k, y, k, MPFR_RNDN);
          mpfr_round (k, k);
          MPFR_LOG_VAR (k);
          /* |y| < 2^Ntmin, therefore |k| < 2^Nt. */
          continue;
        }
      if (MPFR_LIKELY (MPFR_CAN_ROUND (t, Nt - err, Nz, rnd_mode)))
        {
          inexact = mpfr_set (z, t, rnd_mode);
          break;
        }

      /* check exact power, except when y is an integer (since the
         exact cases for y integer have already been filtered out) */
      if (check_exact_case == 0 && ! y_is_integer)
        {
          if (mpfr_pow_is_exact (z, absx, y, rnd_mode, &inexact))
            break;
          check_exact_case = 1;
        }

      /* reactualisation of the precision */
      MPFR_ZIV_NEXT (ziv_loop, Nt);
      mpfr_set_prec (t, Nt);
      if (k_non_zero)
        mpfr_set_prec (u, Nt);
    }
  MPFR_ZIV_FREE (ziv_loop);

  if (k_non_zero)
    {
      int inex2;
      long lk;

      /* The rounded result in an unbounded exponent range is z * 2^k. As
       * MPFR chooses underflow after rounding, the mpfr_mul_2si below will
       * correctly detect underflows and overflows. However, in rounding to
       * nearest, if z * 2^k = 2^(emin - 2), then the double rounding may
       * affect the result. We need to cope with that before overwriting z.
       * This can occur only if k < 0 (this test is necessary to avoid a
       * potential integer overflow).
       * If inexact >= 0, then the real result is <= 2^(emin - 2), so that
       * o(2^(emin - 2)) = +0 is correct. If inexact < 0, then the real
       * result is > 2^(emin - 2) and we need to round to 2^(emin - 1).
       */
      MPFR_ASSERTN (MPFR_EXP_MAX <= LONG_MAX);
      lk = mpfr_get_si (k, MPFR_RNDN);
      /* Due to early overflow detection, |k| should not be much larger than
       * MPFR_EMAX_MAX, and as MPFR_EMAX_MAX <= MPFR_EXP_MAX/2 <= LONG_MAX/2,
       * an overflow should not be possible in mpfr_get_si (and lk is exact).
       * And one even has the following assertion. TODO: complete proof.
       */
      MPFR_ASSERTD (lk > LONG_MIN && lk < LONG_MAX);
      /* Note: even in case of overflow (lk inexact), the code is correct.
       * Indeed, for the 3 occurrences of lk:
       *   - The test lk < 0 is correct as sign(lk) = sign(k).
       *   - In the test MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk,
       *     if lk is inexact, then lk = LONG_MIN <= MPFR_EXP_MIN
       *     (the minimum value of the mpfr_exp_t type), and
       *     __gmpfr_emin - 1 - lk >= MPFR_EMIN_MIN - 1 - 2 * MPFR_EMIN_MIN
       *     >= - MPFR_EMIN_MIN - 1 = MPFR_EMAX_MAX - 1. However, from the
       *     choice of k, z has been chosen to be around 1, so that the
       *     result of the test is false, as if lk were exact.
       *   - In the mpfr_mul_2si (z, z, lk, rnd_mode), if lk is inexact,
       *     then |lk| >= LONG_MAX >= MPFR_EXP_MAX, and as z is around 1,
       *     mpfr_mul_2si underflows or overflows in the same way as if
       *     lk were exact.
       * TODO: give a bound on |t|, then on |EXP(z)|.
       */
      if (rnd_mode == MPFR_RNDN && inexact < 0 && lk < 0 &&
          MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk && mpfr_powerof2_raw (z))
        {
          /* Rounding to nearest, real result > z * 2^k = 2^(emin - 2),
           * underflow case: as the minimum precision is > 1, we will
           * obtain the correct result and exceptions by replacing z by
           * nextabove(z).
           */
          MPFR_ASSERTN (MPFR_PREC_MIN > 1);
          mpfr_nextabove (z);
        }
      MPFR_CLEAR_FLAGS ();
      inex2 = mpfr_mul_2si (z, z, lk, rnd_mode);
      if (inex2)  /* underflow or overflow */
        {
          inexact = inex2;
          if (expo != NULL)
            MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, __gmpfr_flags);
        }
      mpfr_clears (u, k, (mpfr_ptr) 0);
    }
  mpfr_clear (t);

  /* update the sign of the result if x was negative */
  if (neg_result)
    {
      MPFR_SET_NEG(z);
      inexact = -inexact;
    }

  return inexact;
}
Пример #6
0
/* Exact product. The number a is assumed to have enough allocated memory,
   where the trailing bits are regarded as being part of the input numbers
   (no reallocation is attempted and no check is performed as MPFR_TMP_INIT
   could have been used). The arguments b and c may actually be UBF numbers
   (mpfr_srcptr can be seen a bit like void *, but is stronger).
   This function does not change the flags, except in case of NaN. */
void
mpfr_ubf_mul_exact (mpfr_ubf_ptr a, mpfr_srcptr b, mpfr_srcptr c)
{
  MPFR_LOG_FUNC
    (("b[%Pu]=%.*Rg c[%Pu]=%.*Rg",
      mpfr_get_prec (b), mpfr_log_prec, b,
      mpfr_get_prec (c), mpfr_log_prec, c),
     ("a[%Pu]=%.*Rg",
      mpfr_get_prec (a), mpfr_log_prec, a));

  MPFR_ASSERTD ((mpfr_ptr) a != b);
  MPFR_ASSERTD ((mpfr_ptr) a != c);
  MPFR_SIGN (a) = MPFR_MULT_SIGN (MPFR_SIGN (b), MPFR_SIGN (c));

  if (MPFR_ARE_SINGULAR (b, c))
    {
      if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c))
        MPFR_SET_NAN (a);
      else if (MPFR_IS_INF (b))
        {
          if (MPFR_NOTZERO (c))
            MPFR_SET_INF (a);
          else
            MPFR_SET_NAN (a);
        }
      else if (MPFR_IS_INF (c))
        {
          if (!MPFR_IS_ZERO (b))
            MPFR_SET_INF (a);
          else
            MPFR_SET_NAN (a);
        }
      else
        {
          MPFR_ASSERTD (MPFR_IS_ZERO(b) || MPFR_IS_ZERO(c));
          MPFR_SET_ZERO (a);
        }
    }
  else
    {
      mpfr_exp_t e;
      mp_size_t bn, cn;
      mpfr_limb_ptr ap;
      mp_limb_t u, v;
      int m;

      /* Note about the code below: For the choice of the precision of
       * the result a, one could choose PREC(b) + PREC(c), instead of
       * taking whole limbs into account, but in most cases where one
       * would gain one limb, one would need to copy the significand
       * instead of a no-op (see the mul.c code).
       * But in the case MPFR_LIMB_MSB (u) == 0, if the result fits in
       * an-1 limbs, one could actually do
       *   mpn_rshift (ap, ap, k, GMP_NUMB_BITS - 1)
       * instead of
       *   mpn_lshift (ap, ap, k, 1)
       * to gain one limb (and reduce the precision), replacing a shift
       * by another one. Would this be interesting?
       */

      bn = MPFR_LIMB_SIZE (b);
      cn = MPFR_LIMB_SIZE (c);

      ap = MPFR_MANT (a);

      u = (bn >= cn) ?
        mpn_mul (ap, MPFR_MANT (b), bn, MPFR_MANT (c), cn) :
        mpn_mul (ap, MPFR_MANT (c), cn, MPFR_MANT (b), bn);
      if (MPFR_UNLIKELY (MPFR_LIMB_MSB (u) == 0))
        {
          m = 1;
          MPFR_DBGRES (v = mpn_lshift (ap, ap, bn + cn, 1));
          MPFR_ASSERTD (v == 0);
        }
      else
        m = 0;

      if (! MPFR_IS_UBF (b) && ! MPFR_IS_UBF (c) &&
          (e = MPFR_GET_EXP (b) + MPFR_GET_EXP (c) - m,
           MPFR_EXP_IN_RANGE (e)))
        {
          MPFR_SET_EXP (a, e);
        }
      else
        {
          mpz_t be, ce;

          mpz_init (MPFR_ZEXP (a));

          /* This may involve copies of mpz_t, but exponents should not be
             very large integers anyway. */
          mpfr_get_zexp (be, b);
          mpfr_get_zexp (ce, c);
          mpz_add (MPFR_ZEXP (a), be, ce);
          mpz_clear (be);
          mpz_clear (ce);
          mpz_sub_ui (MPFR_ZEXP (a), MPFR_ZEXP (a), m);
          MPFR_SET_UBF (a);
        }
    }
}
Пример #7
0
static void
underflows (void)
{
    mpfr_t x, y, z;
    int err = 0;
    int inexact;
    int i;
    mp_exp_t emin;

    mpfr_init2 (x, 64);
    mpfr_init2 (y, 64);

    mpfr_set_ui (x, 1, GMP_RNDN);
    mpfr_set_exp (x, mpfr_get_emin());

    for (i = 3; i < 10; i++)
    {
        mpfr_set_ui (y, i, GMP_RNDN);
        mpfr_div_2ui (y, y, 1, GMP_RNDN);
        test_pow (y, x, y, GMP_RNDN);
        if (!MPFR_IS_FP(y) || mpfr_cmp_ui (y, 0))
        {
            printf ("Error in mpfr_pow for ");
            mpfr_out_str (stdout, 2, 0, x, GMP_RNDN);
            printf (" ^ (%d/2)\nGot ", i);
            mpfr_out_str (stdout, 2, 0, y, GMP_RNDN);
            printf (" instead of 0.\n");
            exit (1);
        }
    }

    mpfr_init2 (z, 55);
    mpfr_set_str (x, "0.110011010011101001110001110100010000110111101E0",
                  2, GMP_RNDN);
    mpfr_set_str (y, "0.101110010011111001011010100011011100111110011E40",
                  2, GMP_RNDN);
    mpfr_clear_flags ();
    inexact = mpfr_pow (z, x, y, GMP_RNDU);
    if (!mpfr_underflow_p ())
    {
        printf ("Underflow flag is not set for special underflow test.\n");
        err = 1;
    }
    if (inexact <= 0)
    {
        printf ("Ternary value is wrong for special underflow test.\n");
        err = 1;
    }
    mpfr_set_ui (x, 0, GMP_RNDN);
    mpfr_nextabove (x);
    if (mpfr_cmp (x, z) != 0)
    {
        printf ("Wrong value for special underflow test.\nGot ");
        mpfr_out_str (stdout, 2, 0, z, GMP_RNDN);
        printf ("\ninstead of ");
        mpfr_out_str (stdout, 2, 2, x, GMP_RNDN);
        printf ("\n");
        err = 1;
    }
    if (err)
        exit (1);

    /* MPFR currently (2006-08-19) segfaults on the following code (and
       possibly makes other programs crash due to the lack of memory),
       because y is converted into an mpz_t, and the required precision
       is too high. */
    mpfr_set_prec (x, 2);
    mpfr_set_prec (y, 2);
    mpfr_set_prec (z, 12);
    mpfr_set_ui_2exp (x, 3, -2, GMP_RNDN);
    mpfr_set_ui_2exp (y, 1, mpfr_get_emax () - 1, GMP_RNDN);
    mpfr_clear_flags ();
    mpfr_pow (z, x, y, GMP_RNDN);
    if (!mpfr_underflow_p () || MPFR_NOTZERO (z))
    {
        printf ("Underflow test with large y fails.\n");
        exit (1);
    }

    emin = mpfr_get_emin ();
    mpfr_set_emin (-256);
    mpfr_set_prec (x, 2);
    mpfr_set_prec (y, 2);
    mpfr_set_prec (z, 12);
    mpfr_set_ui_2exp (x, 3, -2, GMP_RNDN);
    mpfr_set_ui_2exp (y, 1, 38, GMP_RNDN);
    mpfr_clear_flags ();
    inexact = mpfr_pow (z, x, y, GMP_RNDN);
    if (!mpfr_underflow_p () || MPFR_NOTZERO (z) || inexact >= 0)
    {
        printf ("Bad underflow detection for 0.75^(2^38). Obtained:\n"
                "Underflow flag... %-3s (should be 'yes')\n"
                "Zero result...... %-3s (should be 'yes')\n"
                "Inexact value.... %-3d (should be negative)\n",
                mpfr_underflow_p () ? "yes" : "no",
                MPFR_IS_ZERO (z) ? "yes" : "no", inexact);
        exit (1);
    }
    mpfr_set_emin (emin);

    emin = mpfr_get_emin ();
    mpfr_set_emin (-256);
    mpfr_set_prec (x, 2);
    mpfr_set_prec (y, 40);
    mpfr_set_prec (z, 12);
    mpfr_set_ui_2exp (x, 3, -1, GMP_RNDN);
    mpfr_set_si_2exp (y, -1, 38, GMP_RNDN);
    for (i = 0; i < 4; i++)
    {
        if (i == 2)
            mpfr_neg (x, x, GMP_RNDN);
        mpfr_clear_flags ();
        inexact = mpfr_pow (z, x, y, GMP_RNDN);
        if (!mpfr_underflow_p () || MPFR_NOTZERO (z) ||
                (i == 3 ? (inexact <= 0) : (inexact >= 0)))
        {
            printf ("Bad underflow detection for (");
            mpfr_out_str (stdout, 10, 0, x, GMP_RNDN);
            printf (")^(-2^38-%d). Obtained:\n"
                    "Overflow flag.... %-3s (should be 'no')\n"
                    "Underflow flag... %-3s (should be 'yes')\n"
                    "Zero result...... %-3s (should be 'yes')\n"
                    "Inexact value.... %-3d (should be %s)\n", i,
                    mpfr_overflow_p () ? "yes" : "no",
                    mpfr_underflow_p () ? "yes" : "no",
                    MPFR_IS_ZERO (z) ? "yes" : "no", inexact,
                    i == 3 ? "positive" : "negative");
            exit (1);
        }
        inexact = mpfr_sub_ui (y, y, 1, GMP_RNDN);
        MPFR_ASSERTN (inexact == 0);
    }
    mpfr_set_emin (emin);

    mpfr_clears (x, y, z, (void *) 0);
}
Пример #8
0
Файл: mul.c Проект: gnooth/xcl
static int
mpfr_mul3 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
{
    /* Old implementation */
    int sign_product, cc, inexact;
    mpfr_exp_t ax;
    mp_limb_t *tmp;
    mp_limb_t b1;
    mpfr_prec_t bq, cq;
    mp_size_t bn, cn, tn, k;
    MPFR_TMP_DECL(marker);

    /* deal with special cases */
    if (MPFR_ARE_SINGULAR(b,c))
    {
        if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c))
        {
            MPFR_SET_NAN(a);
            MPFR_RET_NAN;
        }
        sign_product = MPFR_MULT_SIGN( MPFR_SIGN(b) , MPFR_SIGN(c) );
        if (MPFR_IS_INF(b))
        {
            if (MPFR_IS_INF(c) || MPFR_NOTZERO(c))
            {
                MPFR_SET_SIGN(a,sign_product);
                MPFR_SET_INF(a);
                MPFR_RET(0); /* exact */
            }
            else
            {
                MPFR_SET_NAN(a);
                MPFR_RET_NAN;
            }
        }
        else if (MPFR_IS_INF(c))
        {
            if (MPFR_NOTZERO(b))
            {
                MPFR_SET_SIGN(a, sign_product);
                MPFR_SET_INF(a);
                MPFR_RET(0); /* exact */
            }
            else
            {
                MPFR_SET_NAN(a);
                MPFR_RET_NAN;
            }
        }
        else
        {
            MPFR_ASSERTD(MPFR_IS_ZERO(b) || MPFR_IS_ZERO(c));
            MPFR_SET_SIGN(a, sign_product);
            MPFR_SET_ZERO(a);
            MPFR_RET(0); /* 0 * 0 is exact */
        }
    }
    sign_product = MPFR_MULT_SIGN( MPFR_SIGN(b) , MPFR_SIGN(c) );

    ax = MPFR_GET_EXP (b) + MPFR_GET_EXP (c);

    bq = MPFR_PREC(b);
    cq = MPFR_PREC(c);

    MPFR_ASSERTD(bq+cq > bq); /* PREC_MAX is /2 so no integer overflow */

    bn = (bq+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; /* number of limbs of b */
    cn = (cq+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; /* number of limbs of c */
    k = bn + cn; /* effective nb of limbs used by b*c (= tn or tn+1) below */
    tn = (bq + cq + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
    /* <= k, thus no int overflow */
    MPFR_ASSERTD(tn <= k);

    /* Check for no size_t overflow*/
    MPFR_ASSERTD((size_t) k <= ((size_t) -1) / BYTES_PER_MP_LIMB);
    MPFR_TMP_MARK(marker);
    tmp = (mp_limb_t *) MPFR_TMP_ALLOC((size_t) k * BYTES_PER_MP_LIMB);

    /* multiplies two mantissa in temporary allocated space */
    b1 = (MPFR_LIKELY(bn >= cn)) ?
         mpn_mul (tmp, MPFR_MANT(b), bn, MPFR_MANT(c), cn)
         : mpn_mul (tmp, MPFR_MANT(c), cn, MPFR_MANT(b), bn);

    /* now tmp[0]..tmp[k-1] contains the product of both mantissa,
       with tmp[k-1]>=2^(GMP_NUMB_BITS-2) */
    b1 >>= GMP_NUMB_BITS - 1; /* msb from the product */

    /* if the mantissas of b and c are uniformly distributed in ]1/2, 1],
       then their product is in ]1/4, 1/2] with probability 2*ln(2)-1 ~ 0.386
       and in [1/2, 1] with probability 2-2*ln(2) ~ 0.614 */
    tmp += k - tn;
    if (MPFR_UNLIKELY(b1 == 0))
        mpn_lshift (tmp, tmp, tn, 1); /* tn <= k, so no stack corruption */
    cc = mpfr_round_raw (MPFR_MANT (a), tmp, bq + cq,
                         MPFR_IS_NEG_SIGN(sign_product),
                         MPFR_PREC (a), rnd_mode, &inexact);

    /* cc = 1 ==> result is a power of two */
    if (MPFR_UNLIKELY(cc))
        MPFR_MANT(a)[MPFR_LIMB_SIZE(a)-1] = MPFR_LIMB_HIGHBIT;

    MPFR_TMP_FREE(marker);

    {
        mpfr_exp_t ax2 = ax + (mpfr_exp_t) (b1 - 1 + cc);
        if (MPFR_UNLIKELY( ax2 > __gmpfr_emax))
            return mpfr_overflow (a, rnd_mode, sign_product);
        if (MPFR_UNLIKELY( ax2 < __gmpfr_emin))
        {
            /* In the rounding to the nearest mode, if the exponent of the exact
               result (i.e. before rounding, i.e. without taking cc into account)
               is < __gmpfr_emin - 1 or the exact result is a power of 2 (i.e. if
               both arguments are powers of 2), then round to zero. */
            if (rnd_mode == MPFR_RNDN &&
                    (ax + (mpfr_exp_t) b1 < __gmpfr_emin ||
                     (mpfr_powerof2_raw (b) && mpfr_powerof2_raw (c))))
                rnd_mode = MPFR_RNDZ;
            return mpfr_underflow (a, rnd_mode, sign_product);
        }
        MPFR_SET_EXP (a, ax2);
        MPFR_SET_SIGN(a, sign_product);
    }
    MPFR_RET (inexact);
}
Пример #9
0
int
main (void)
{
  mpfr_t x, y;
  int i, r;

  tests_start_mpfr ();

  mpfr_init2 (x, 256);
  mpfr_init2 (y, 8);

  RND_LOOP (r)
    {

      /* Check NAN */
      mpfr_set_nan (x);
      if (mpfr_fits_ulong_p (x, (mpfr_rnd_t) r))
        ERROR1 (1);
      if (mpfr_fits_slong_p (x, (mpfr_rnd_t) r))
        ERROR1 (2);
      if (mpfr_fits_uint_p (x, (mpfr_rnd_t) r))
        ERROR1 (3);
      if (mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
        ERROR1 (4);
      if (mpfr_fits_ushort_p (x, (mpfr_rnd_t) r))
        ERROR1 (5);
      if (mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
        ERROR1 (6);

      /* Check INF */
      mpfr_set_inf (x, 1);
      if (mpfr_fits_ulong_p (x, (mpfr_rnd_t) r))
        ERROR1 (7);
      if (mpfr_fits_slong_p (x, (mpfr_rnd_t) r))
        ERROR1 (8);
      if (mpfr_fits_uint_p (x, (mpfr_rnd_t) r))
        ERROR1 (9);
      if (mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
        ERROR1 (10);
      if (mpfr_fits_ushort_p (x, (mpfr_rnd_t) r))
        ERROR1 (11);
      if (mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
        ERROR1 (12);

      /* Check Zero */
      MPFR_SET_ZERO (x);
      if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r))
        ERROR1 (13);
      if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r))
        ERROR1 (14);
      if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r))
        ERROR1 (15);
      if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
        ERROR1 (16);
      if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r))
        ERROR1 (17);
      if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
        ERROR1 (18);

      /* Check small positive op */
      mpfr_set_str1 (x, "1@-1");
      if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r))
        ERROR1 (19);
      if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r))
        ERROR1 (20);
      if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r))
        ERROR1 (21);
      if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
        ERROR1 (22);
      if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r))
        ERROR1 (23);
      if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
        ERROR1 (24);

      /* Check 17 */
      mpfr_set_ui (x, 17, MPFR_RNDN);
      if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r))
        ERROR1 (25);
      if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r))
        ERROR1 (26);
      if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r))
        ERROR1 (27);
      if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
        ERROR1 (28);
      if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r))
        ERROR1 (29);
      if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
        ERROR1 (30);

      /* Check all other values */
      mpfr_set_ui (x, ULONG_MAX, MPFR_RNDN);
      mpfr_mul_2exp (x, x, 1, MPFR_RNDN);
      if (mpfr_fits_ulong_p (x, (mpfr_rnd_t) r))
        ERROR1 (31);
      if (mpfr_fits_slong_p (x, (mpfr_rnd_t) r))
        ERROR1 (32);
      mpfr_mul_2exp (x, x, 40, MPFR_RNDN);
      if (mpfr_fits_ulong_p (x, (mpfr_rnd_t) r))
        ERROR1 (33);
      if (mpfr_fits_uint_p (x, (mpfr_rnd_t) r))
        ERROR1 (34);
      if (mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
        ERROR1 (35);
      if (mpfr_fits_ushort_p (x, (mpfr_rnd_t) r))
        ERROR1 (36);
      if (mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
        ERROR1 (37);

      mpfr_set_ui (x, ULONG_MAX, MPFR_RNDN);
      if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r))
        ERROR1 (38);
      mpfr_set_ui (x, LONG_MAX, MPFR_RNDN);
      if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r))
        ERROR1 (39);
      mpfr_set_ui (x, UINT_MAX, MPFR_RNDN);
      if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r))
        ERROR1 (40);
      mpfr_set_ui (x, INT_MAX, MPFR_RNDN);
      if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
        ERROR1 (41);
      mpfr_set_ui (x, USHRT_MAX, MPFR_RNDN);
      if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r))
        ERROR1 (42);
      mpfr_set_ui (x, SHRT_MAX, MPFR_RNDN);
      if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
        ERROR1 (43);

      mpfr_set_si (x, 1, MPFR_RNDN);
      if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
        ERROR1 (44);
      if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
        ERROR1 (45);

      /* Check negative op */
      for (i = 1; i <= 4; i++)
        {
          int inv;

          mpfr_set_si_2exp (x, -i, -2, MPFR_RNDN);
          mpfr_rint (y, x, (mpfr_rnd_t) r);
          inv = MPFR_NOTZERO (y);
          if (!mpfr_fits_ulong_p (x, (mpfr_rnd_t) r) ^ inv)
            ERROR1 (46);
          if (!mpfr_fits_slong_p (x, (mpfr_rnd_t) r))
            ERROR1 (47);
          if (!mpfr_fits_uint_p (x, (mpfr_rnd_t) r) ^ inv)
            ERROR1 (48);
          if (!mpfr_fits_sint_p (x, (mpfr_rnd_t) r))
            ERROR1 (49);
          if (!mpfr_fits_ushort_p (x, (mpfr_rnd_t) r) ^ inv)
            ERROR1 (50);
          if (!mpfr_fits_sshort_p (x, (mpfr_rnd_t) r))
            ERROR1 (51);
        }
    }

  mpfr_clear (x);
  mpfr_clear (y);

  check_intmax ();

  tests_end_mpfr ();
  return 0;
}
Пример #10
0
Файл: texp.c Проект: jozip/xcl
static void
underflow_up (int extended_emin)
{
    mpfr_t minpos, x, y, t, t2;
    int precx, precy;
    int inex;
    int rnd;
    int e3;
    int i, j;

    mpfr_init2 (minpos, 2);
    mpfr_set_ui (minpos, 0, MPFR_RNDN);
    mpfr_nextabove (minpos);

    /* Let's test values near the underflow boundary.
     *
     * Minimum representable positive number: minpos = 2^(emin - 1).
     * Let's choose an MPFR number x = log(minpos) + eps, with |eps| small
     * (note: eps cannot be 0, and cannot be a rational number either).
     * Then exp(x) = minpos * exp(eps) ~= minpos * (1 + eps + eps^2).
     * We will compute y = rnd(exp(x)) in some rounding mode, precision p.
     *   1. If eps > 0, then in any rounding mode:
     *        rnd(exp(x)) >= minpos and no underflow.
     *      So, let's take x1 = rndu(log(minpos)) in some precision.
     *   2. If eps < 0, then exp(x) < minpos and the result will be either 0
     *      or minpos. An underflow always occurs in MPFR_RNDZ and MPFR_RNDD,
     *      but not necessarily in MPFR_RNDN and MPFR_RNDU (this is underflow
     *      after rounding in an unbounded exponent range). If -a < eps < -b,
     *        minpos * (1 - a) < exp(x) < minpos * (1 - b + b^2).
     *      - If eps > -2^(-p), no underflow in MPFR_RNDU.
     *      - If eps > -2^(-p-1), no underflow in MPFR_RNDN.
     *      - If eps < - (2^(-p-1) + 2^(-2p-1)), underflow in MPFR_RNDN.
     *      - If eps < - (2^(-p) + 2^(-2p+1)), underflow in MPFR_RNDU.
     *      - In MPFR_RNDN, result is minpos iff exp(eps) > 1/2, i.e.
     *        - log(2) < eps < ...
     *
     * Moreover, since precy < MPFR_EXP_THRESHOLD (to avoid tests that take
     * too much time), mpfr_exp() always selects mpfr_exp_2(); so, we need
     * to test mpfr_exp_3() too. This will be done via the e3 variable:
     *   e3 = 0: mpfr_exp(), thus mpfr_exp_2().
     *   e3 = 1: mpfr_exp_3(), via the exp_3() wrapper.
     * i.e.: inex = e3 ? exp_3 (y, x, rnd) : mpfr_exp (y, x, rnd);
     */

    /* Case eps > 0. In revision 5461 (trunk) on a 64-bit Linux machine:
     *   Incorrect flags in underflow_up, eps > 0, MPFR_RNDN and extended emin
     *   for precx = 96, precy = 16, mpfr_exp_3
     *   Got 9 instead of 8.
     * Note: testing this case in several precisions for x and y introduces
     * some useful random. Indeed, the bug is not always triggered.
     * Fixed in r5469.
     */
    for (precx = 16; precx <= 128; precx += 16)
    {
        mpfr_init2 (x, precx);
        mpfr_log (x, minpos, MPFR_RNDU);
        for (precy = 16; precy <= 128; precy += 16)
        {
            mpfr_init2 (y, precy);

            for (e3 = 0; e3 <= 1; e3++)
            {
                RND_LOOP (rnd)
                {
                    int err = 0;

                    mpfr_clear_flags ();
                    inex = e3 ? exp_3 (y, x, (mpfr_rnd_t) rnd)
                           : mpfr_exp (y, x, (mpfr_rnd_t) rnd);
                    if (__gmpfr_flags != MPFR_FLAGS_INEXACT)
                    {
                        printf ("Incorrect flags in underflow_up, eps > 0, %s",
                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
                        if (extended_emin)
                            printf (" and extended emin");
                        printf ("\nfor precx = %d, precy = %d, %s\n",
                                precx, precy, e3 ? "mpfr_exp_3" : "mpfr_exp");
                        printf ("Got %u instead of %u.\n", __gmpfr_flags,
                                (unsigned int) MPFR_FLAGS_INEXACT);
                        err = 1;
                    }
                    if (mpfr_cmp0 (y, minpos) < 0)
                    {
                        printf ("Incorrect result in underflow_up, eps > 0, %s",
                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
                        if (extended_emin)
                            printf (" and extended emin");
                        printf ("\nfor precx = %d, precy = %d, %s\n",
                                precx, precy, e3 ? "mpfr_exp_3" : "mpfr_exp");
                        mpfr_dump (y);
                        err = 1;
                    }
                    MPFR_ASSERTN (inex != 0);
                    if (rnd == MPFR_RNDD || rnd == MPFR_RNDZ)
                        MPFR_ASSERTN (inex < 0);
                    if (rnd == MPFR_RNDU)
                        MPFR_ASSERTN (inex > 0);
                    if (err)
                        exit (1);
                }
            }

            mpfr_clear (y);
        }
        mpfr_clear (x);
    }

    /* Case - log(2) < eps < 0 in MPFR_RNDN, starting with small-precision x;
     * only check the result and the ternary value.
     * Previous to r5453 (trunk), on 32-bit and 64-bit machines, this fails
     * for precx = 65 and precy = 16, e.g.:
     *   exp_2.c:264:  assertion failed: ...
     * because mpfr_sub (r, x, r, MPFR_RNDU); yields a null value. This is
     * fixed in r5453 by going to next Ziv's iteration.
     */
    for (precx = sizeof(mpfr_exp_t) * CHAR_BIT + 1; precx <= 81; precx += 8)
    {
        mpfr_init2 (x, precx);
        mpfr_log (x, minpos, MPFR_RNDD);  /* |ulp| <= 1/2 */
        for (precy = 16; precy <= 128; precy += 16)
        {
            mpfr_init2 (y, precy);
            inex = mpfr_exp (y, x, MPFR_RNDN);
            if (inex <= 0 || mpfr_cmp0 (y, minpos) != 0)
            {
                printf ("Error in underflow_up, - log(2) < eps < 0");
                if (extended_emin)
                    printf (" and extended emin");
                printf (" for prec = %d\nExpected ", precy);
                mpfr_out_str (stdout, 16, 0, minpos, MPFR_RNDN);
                printf (" (minimum positive MPFR number) and inex > 0\nGot ");
                mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
                printf ("\nwith inex = %d\n", inex);
                exit (1);
            }
            mpfr_clear (y);
        }
        mpfr_clear (x);
    }

    /* Cases eps ~ -2^(-p) and eps ~ -2^(-p-1). More precisely,
     *   _ for j = 0, eps > -2^(-(p+i)),
     *   _ for j = 1, eps < - (2^(-(p+i)) + 2^(1-2(p+i))),
     * where i = 0 or 1.
     */
    mpfr_inits2 (2, t, t2, (mpfr_ptr) 0);
    for (precy = 16; precy <= 128; precy += 16)
    {
        mpfr_set_ui_2exp (t, 1, - precy, MPFR_RNDN);         /* 2^(-p) */
        mpfr_set_ui_2exp (t2, 1, 1 - 2 * precy, MPFR_RNDN);  /* 2^(-2p+1) */
        precx = sizeof(mpfr_exp_t) * CHAR_BIT + 2 * precy + 8;
        mpfr_init2 (x, precx);
        mpfr_init2 (y, precy);
        for (i = 0; i <= 1; i++)
        {
            for (j = 0; j <= 1; j++)
            {
                if (j == 0)
                {
                    /* Case eps > -2^(-(p+i)). */
                    mpfr_log (x, minpos, MPFR_RNDU);
                }
                else  /* j == 1 */
                {
                    /* Case eps < - (2^(-(p+i)) + 2^(1-2(p+i))). */
                    mpfr_log (x, minpos, MPFR_RNDD);
                    inex = mpfr_sub (x, x, t2, MPFR_RNDN);
                    MPFR_ASSERTN (inex == 0);
                }
                inex = mpfr_sub (x, x, t, MPFR_RNDN);
                MPFR_ASSERTN (inex == 0);

                RND_LOOP (rnd)
                for (e3 = 0; e3 <= 1; e3++)
                {
                    int err = 0;
                    unsigned int flags;

                    flags = MPFR_FLAGS_INEXACT |
                            (((rnd == MPFR_RNDU || rnd == MPFR_RNDA)
                              && (i == 1 || j == 0)) ||
                             (rnd == MPFR_RNDN && (i == 1 && j == 0)) ?
                             0 : MPFR_FLAGS_UNDERFLOW);
                    mpfr_clear_flags ();
                    inex = e3 ? exp_3 (y, x, (mpfr_rnd_t) rnd)
                           : mpfr_exp (y, x, (mpfr_rnd_t) rnd);
                    if (__gmpfr_flags != flags)
                    {
                        printf ("Incorrect flags in underflow_up, %s",
                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
                        if (extended_emin)
                            printf (" and extended emin");
                        printf ("\nfor precx = %d, precy = %d, ",
                                precx, precy);
                        if (j == 0)
                            printf ("eps >~ -2^(-%d)", precy + i);
                        else
                            printf ("eps <~ - (2^(-%d) + 2^(%d))",
                                    precy + i, 1 - 2 * (precy + i));
                        printf (", %s\n", e3 ? "mpfr_exp_3" : "mpfr_exp");
                        printf ("Got %u instead of %u.\n",
                                __gmpfr_flags, flags);
                        err = 1;
                    }
                    if (rnd == MPFR_RNDU || rnd == MPFR_RNDA || rnd == MPFR_RNDN ?
                            mpfr_cmp0 (y, minpos) != 0 : MPFR_NOTZERO (y))
                    {
                        printf ("Incorrect result in underflow_up, %s",
                                mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
                        if (extended_emin)
                            printf (" and extended emin");
                        printf ("\nfor precx = %d, precy = %d, ",
                                precx, precy);
                        if (j == 0)
                            printf ("eps >~ -2^(-%d)", precy + i);
                        else
                            printf ("eps <~ - (2^(-%d) + 2^(%d))",
                                    precy + i, 1 - 2 * (precy + i));
                        printf (", %s\n", e3 ? "mpfr_exp_3" : "mpfr_exp");
                        mpfr_dump (y);
                        err = 1;
                    }
                    if (err)
                        exit (1);
                }  /* for (e3 ...) */
            }  /* for (j ...) */
            mpfr_div_2si (t, t, 1, MPFR_RNDN);
            mpfr_div_2si (t2, t2, 2, MPFR_RNDN);
        }  /* for (i ...) */
        mpfr_clears (x, y, (mpfr_ptr) 0);
    }  /* for (precy ...) */
    mpfr_clears (t, t2, (mpfr_ptr) 0);

    /* Case exp(eps) ~= 1/2, i.e. eps ~= - log(2).
     * We choose x0 and x1 with high enough precision such that:
     *   x0 = rndd(rndd(log(minpos)) - rndu(log(2)))
     *   x1 = rndu(rndu(log(minpos)) - rndd(log(2)))
     * In revision 5507 (trunk) on a 64-bit Linux machine, this fails:
     *   Error in underflow_up, eps >~ - log(2) and extended emin
     *   for precy = 16, mpfr_exp
     *   Expected 1.0@-1152921504606846976 (minimum positive MPFR number),
     *   inex > 0 and flags = 9
     *   Got 0
     *   with inex = -1 and flags = 9
     * due to a double-rounding problem in mpfr_mul_2si when rescaling
     * the result.
     */
    mpfr_inits2 (sizeof(mpfr_exp_t) * CHAR_BIT + 64, x, t, (mpfr_ptr) 0);
    for (i = 0; i <= 1; i++)
    {
        mpfr_log (x, minpos, i ? MPFR_RNDU : MPFR_RNDD);
        mpfr_const_log2 (t, i ? MPFR_RNDD : MPFR_RNDU);
        mpfr_sub (x, x, t, i ? MPFR_RNDU : MPFR_RNDD);
        for (precy = 16; precy <= 128; precy += 16)
        {
            mpfr_init2 (y, precy);
            for (e3 = 0; e3 <= 1; e3++)
            {
                unsigned int flags, uflags =
                    MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW;

                mpfr_clear_flags ();
                inex = e3 ? exp_3 (y, x, MPFR_RNDN) : mpfr_exp (y, x, MPFR_RNDN);
                flags = __gmpfr_flags;
                if (flags != uflags ||
                        (i ? (inex <= 0 || mpfr_cmp0 (y, minpos) != 0)
                         : (inex >= 0 || MPFR_NOTZERO (y))))
                {
                    printf ("Error in underflow_up, eps %c~ - log(2)",
                            i ? '>' : '<');
                    if (extended_emin)
                        printf (" and extended emin");
                    printf ("\nfor precy = %d, %s\nExpected ", precy,
                            e3 ? "mpfr_exp_3" : "mpfr_exp");
                    if (i)
                    {
                        mpfr_out_str (stdout, 16, 0, minpos, MPFR_RNDN);
                        printf (" (minimum positive MPFR number),\ninex >");
                    }
                    else
                    {
                        printf ("+0, inex <");
                    }
                    printf (" 0 and flags = %u\nGot ", uflags);
                    mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
                    printf ("\nwith inex = %d and flags = %u\n", inex, flags);
                    exit (1);
                }
            }
            mpfr_clear (y);
        }
    }
    mpfr_clears (x, t, (mpfr_ptr) 0);

    mpfr_clear (minpos);
}
Пример #11
0
Файл: eq.c Проект: mahdiz/mpclib
int
mpfr_eq (mpfr_srcptr u, mpfr_srcptr v, unsigned long int n_bits)
{
    mp_srcptr up, vp;
    mp_size_t usize, vsize, size, i;
    mp_exp_t uexp, vexp;
    int usign, k;

    uexp = MPFR_EXP(u);
    vexp = MPFR_EXP(v);

    usize = (MPFR_PREC(u)-1)/BITS_PER_MP_LIMB + 1;
    vsize = (MPFR_PREC(v)-1)/BITS_PER_MP_LIMB + 1;

    usign = MPFR_SIGN(u);

    /* 1. Are the signs different?  */
    if (usign ==  MPFR_SIGN(v))
    {
        /* U and V are both non-negative or both negative.  */
        if (!MPFR_NOTZERO(u))
            return !MPFR_NOTZERO(v);
        if (!MPFR_NOTZERO(v))
            return !MPFR_NOTZERO(u);

        /* Fall out.  */
    }
    else
    {
        /* Either U or V is negative, but not both.  */
        if (MPFR_NOTZERO(u) || MPFR_NOTZERO(v))
            return 0;
        else return 1; /* particular case -0 = +0 */
    }

    /* U and V have the same sign and are both non-zero.  */
    if (MPFR_IS_INF(u))
        return (MPFR_IS_INF(v) && (usign == MPFR_SIGN(v)));
    else if (MPFR_IS_INF(v)) return 0;

    if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v)) return 0;

    /* 2. Are the exponents different?  */
    if (uexp > vexp)
        return 0;			/* ??? handle (uexp = vexp + 1)   */
    if (vexp > uexp)
        return 0;			/* ??? handle (vexp = uexp + 1)   */

    usize = ABS (usize);
    vsize = ABS (vsize);

    up = MPFR_MANT(u);
    vp = MPFR_MANT(v);

    if (usize > vsize)
    {
        if (vsize * BITS_PER_MP_LIMB < n_bits)
        {
            k = usize - vsize - 1;
            while (k >= 0 && !up[k]) --k;
            if (k >= 0)
                return 0;		/* surely too different */
        }
        size = vsize;
    }
    else if (vsize > usize)
    {
        if (usize * BITS_PER_MP_LIMB < n_bits)
        {
            k = vsize - usize - 1;
            while (k >= 0 && !vp[k]) --k;
            if (k >= 0)
                return 0;		/* surely too different */
        }
        size = usize;
    }
    else
    {
        size = usize;
    }

    if (size > (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB)
        size = (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;

    up += usize - size;
    vp += vsize - size;

    for (i = size - 1; i > 0; i--)
    {
        if (up[i] != vp[i])
            return 0;
    }

    if (n_bits & (BITS_PER_MP_LIMB - 1))
        return (up[i] >> (BITS_PER_MP_LIMB - (n_bits & (BITS_PER_MP_LIMB - 1))) ==
                vp[i] >> (BITS_PER_MP_LIMB - (n_bits & (BITS_PER_MP_LIMB - 1))));
    else
        return (up[i] == vp[i]);
Пример #12
0
static void
check_intmax (void)
{
#ifdef _MPFR_H_HAVE_INTMAX_T
  mpfr_t x, y;
  int i, r;

  mpfr_init2 (x, sizeof (uintmax_t) * CHAR_BIT);
  mpfr_init2 (y, 8);

  RND_LOOP (r)
    {
      /* Check NAN */
      mpfr_set_nan (x);
      if (mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (52);
      if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (53);

      /* Check INF */
      mpfr_set_inf (x, 1);
      if (mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (54);
      if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (55);

      /* Check Zero */
      MPFR_SET_ZERO (x);
      if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (56);
      if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (57);

      /* Check positive small op */
      mpfr_set_str1 (x, "1@-1");
      if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (58);
      if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (59);

      /* Check 17 */
      mpfr_set_ui (x, 17, MPFR_RNDN);
      if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (60);
      if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (61);

      /* Check hugest */
      mpfr_set_ui_2exp (x, 42, sizeof (uintmax_t) * 32, MPFR_RNDN);
      if (mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (62);
      if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (63);

      /* Check all other values */
      mpfr_set_uj (x, MPFR_UINTMAX_MAX, MPFR_RNDN);
      mpfr_add_ui (x, x, 1, MPFR_RNDN);
      if (mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (64);
      mpfr_set_uj (x, MPFR_UINTMAX_MAX, MPFR_RNDN);
      if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (65);
      mpfr_set_sj (x, MPFR_INTMAX_MAX, MPFR_RNDN);
      mpfr_add_ui (x, x, 1, MPFR_RNDN);
      if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (66);
      mpfr_set_sj (x, MPFR_INTMAX_MAX, MPFR_RNDN);
      if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (67);
      mpfr_set_sj (x, MPFR_INTMAX_MIN, MPFR_RNDN);
      if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (68);
      mpfr_sub_ui (x, x, 1, MPFR_RNDN);
      if (mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
        ERROR1 (69);

      /* Check negative op */
      for (i = 1; i <= 4; i++)
        {
          int inv;

          mpfr_set_si_2exp (x, -i, -2, MPFR_RNDN);
          mpfr_rint (y, x, (mpfr_rnd_t) r);
          inv = MPFR_NOTZERO (y);
          if (!mpfr_fits_uintmax_p (x, (mpfr_rnd_t) r) ^ inv)
            ERROR1 (70);
          if (!mpfr_fits_intmax_p (x, (mpfr_rnd_t) r))
            ERROR1 (71);
        }
    }

  mpfr_clear (x);
  mpfr_clear (y);
#endif
}
Пример #13
0
static void
check_special_exprange (void)
{
  int inexact, ov;
  unsigned int eflags, gflags;
  mpfr_t xi, xf, x;
  mpfr_exp_t emax;

  emax = mpfr_get_emax ();
  mpfr_init2 (xi, 7);
  mpfr_init2 (xf, 7);
  mpfr_init2 (x, 8);

  mpfr_set_str (x, "0.11111111", 2, MPFR_RNDN);
  for (ov = 0; ov <= 1; ov++)
    {
      const char *s = ov ? "@Inf@" : "1";

      if (ov)
        set_emax (0);
      mpfr_clear_flags ();
      inexact = mpfr_modf (xi, xf, x, MPFR_RNDN);
      gflags = __gmpfr_flags;
      set_emax (emax);
      if (MPFR_NOTZERO (xi) || MPFR_IS_NEG (xi) ||
          mpfr_cmp_str1 (xf, s) != 0)
        {
          printf ("Error in check_special_exprange (ov = %d):"
                  " expected 0 and %s, got\n", ov, s);
          mpfr_out_str (stdout, 2, 0, xi, MPFR_RNDN);
          printf (" and ");
          mpfr_out_str (stdout, 2, 0, xf, MPFR_RNDN);
          printf ("\n");
          exit (1);
        }
      if (inexact != 4)
        {
          printf ("Bad inexact value in check_special_exprange (ov = %d):"
                  " expected 4, got %d\n", ov, inexact);
          exit (1);
        }
      eflags = MPFR_FLAGS_INEXACT | (ov ? MPFR_FLAGS_OVERFLOW : 0);
      if (gflags != eflags)
        {
          printf ("Bad flags in check_special_exprange (ov = %d):"
                  " expected %u, got %u\n", ov, eflags, gflags);
          exit (1);
        }
    }

  /* Test if an overflow occurs in mpfr_set for ope >= opq. */
  mpfr_set_emax (MPFR_EMAX_MAX);
  mpfr_set_inf (x, 1);
  mpfr_nextbelow (x);
  mpfr_clear_flags ();
  inexact = mpfr_modf (xi, xf, x, MPFR_RNDN);
  gflags = __gmpfr_flags;
  if (mpfr_cmp_str1 (xi, "@Inf@") != 0 ||
      MPFR_NOTZERO (xf) || MPFR_IS_NEG (xf))
    {
      printf ("Error in check_special_exprange:"
              " expected 0 and @Inf@, got\n");
      mpfr_out_str (stdout, 2, 0, xi, MPFR_RNDN);
      printf (" and ");
      mpfr_out_str (stdout, 2, 0, xf, MPFR_RNDN);
      printf ("\n");
      exit (1);
    }
  if (inexact != 1)
    {
      printf ("Bad inexact value in check_special_exprange:"
              " expected 1, got %d\n", inexact);
      exit (1);
    }
  eflags = MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW;
  if (gflags != eflags)
    {
      printf ("Bad flags in check_special_exprange:"
              " expected %u, got %u\n", eflags, gflags);
      exit (1);
    }
  set_emax (emax);

  /* Test if an underflow occurs in the general case. TODO */

  mpfr_clears (xi, xf, x, (mpfr_ptr) 0);
}
Пример #14
0
int
mpfr_atan2 (mpfr_ptr dest, mpfr_srcptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  mpfr_t tmp, pi;
  int inexact;
  mpfr_prec_t prec;
  mpfr_exp_t e;
  MPFR_SAVE_EXPO_DECL (expo);
  MPFR_ZIV_DECL (loop);

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

  /* Special cases */
  if (MPFR_ARE_SINGULAR (x, y))
    {
      /* atan2(0, 0) does not raise the "invalid" floating-point
         exception, nor does atan2(y, 0) raise the "divide-by-zero"
         floating-point exception.
         -- atan2(±0, -0) returns ±pi.313)
         -- atan2(±0, +0) returns ±0.
         -- atan2(±0, x) returns ±pi, for x < 0.
         -- atan2(±0, x) returns ±0, for x > 0.
         -- atan2(y, ±0) returns -pi/2 for y < 0.
         -- atan2(y, ±0) returns pi/2 for y > 0.
         -- atan2(±oo, -oo) returns ±3pi/4.
         -- atan2(±oo, +oo) returns ±pi/4.
         -- atan2(±oo, x) returns ±pi/2, for finite x.
         -- atan2(±y, -oo) returns ±pi, for finite y > 0.
         -- atan2(±y, +oo) returns ±0, for finite y > 0.
      */
      if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y))
        {
          MPFR_SET_NAN (dest);
          MPFR_RET_NAN;
        }
      if (MPFR_IS_ZERO (y))
        {
          if (MPFR_IS_NEG (x)) /* +/- PI */
            {
            set_pi:
              if (MPFR_IS_NEG (y))
                {
                  inexact =  mpfr_const_pi (dest, MPFR_INVERT_RND (rnd_mode));
                  MPFR_CHANGE_SIGN (dest);
                  return -inexact;
                }
              else
                return mpfr_const_pi (dest, rnd_mode);
            }
          else /* +/- 0 */
            {
            set_zero:
              MPFR_SET_ZERO (dest);
              MPFR_SET_SAME_SIGN (dest, y);
              return 0;
            }
        }
      if (MPFR_IS_ZERO (x))
        {
          return pi_div_2ui (dest, 1, MPFR_IS_NEG (y), rnd_mode);
        }
      if (MPFR_IS_INF (y))
        {
          if (!MPFR_IS_INF (x)) /* +/- PI/2 */
            return pi_div_2ui (dest, 1, MPFR_IS_NEG (y), rnd_mode);
          else if (MPFR_IS_POS (x)) /* +/- PI/4 */
            return pi_div_2ui (dest, 2, MPFR_IS_NEG (y), rnd_mode);
          else /* +/- 3*PI/4: Ugly since we have to round properly */
            {
              mpfr_t tmp2;
              MPFR_ZIV_DECL (loop2);
              mpfr_prec_t prec2 = MPFR_PREC (dest) + 10;

              MPFR_SAVE_EXPO_MARK (expo);
              mpfr_init2 (tmp2, prec2);
              MPFR_ZIV_INIT (loop2, prec2);
              for (;;)
                {
                  mpfr_const_pi (tmp2, MPFR_RNDN);
                  mpfr_mul_ui (tmp2, tmp2, 3, MPFR_RNDN); /* Error <= 2  */
                  mpfr_div_2ui (tmp2, tmp2, 2, MPFR_RNDN);
                  if (mpfr_round_p (MPFR_MANT (tmp2), MPFR_LIMB_SIZE (tmp2),
                                    MPFR_PREC (tmp2) - 2,
                                    MPFR_PREC (dest) + (rnd_mode == MPFR_RNDN)))
                    break;
                  MPFR_ZIV_NEXT (loop2, prec2);
                  mpfr_set_prec (tmp2, prec2);
                }
              MPFR_ZIV_FREE (loop2);
              if (MPFR_IS_NEG (y))
                MPFR_CHANGE_SIGN (tmp2);
              inexact = mpfr_set (dest, tmp2, rnd_mode);
              mpfr_clear (tmp2);
              MPFR_SAVE_EXPO_FREE (expo);
              return mpfr_check_range (dest, inexact, rnd_mode);
            }
        }
      MPFR_ASSERTD (MPFR_IS_INF (x));
      if (MPFR_IS_NEG (x))
        goto set_pi;
      else
        goto set_zero;
    }

  /* When x is a power of two, we call directly atan(y/x) since y/x is
     exact. */
  if (MPFR_UNLIKELY (MPFR_IS_POWER_OF_2 (x)))
    {
      int r;
      mpfr_t yoverx;
      unsigned int saved_flags = __gmpfr_flags;

      mpfr_init2 (yoverx, MPFR_PREC (y));
      if (MPFR_LIKELY (mpfr_div_2si (yoverx, y, MPFR_GET_EXP (x) - 1,
                                     MPFR_RNDN) == 0))
        {
          /* Here the flags have not changed due to mpfr_div_2si. */
          r = mpfr_atan (dest, yoverx, rnd_mode);
          mpfr_clear (yoverx);
          return r;
        }
      else
        {
          /* Division is inexact because of a small exponent range */
          mpfr_clear (yoverx);
          __gmpfr_flags = saved_flags;
        }
    }

  MPFR_SAVE_EXPO_MARK (expo);

  /* Set up initial prec */
  prec = MPFR_PREC (dest) + 3 + MPFR_INT_CEIL_LOG2 (MPFR_PREC (dest));
  mpfr_init2 (tmp, prec);

  MPFR_ZIV_INIT (loop, prec);
  if (MPFR_IS_POS (x))
    /* use atan2(y,x) = atan(y/x) */
    for (;;)
      {
        int div_inex;
        MPFR_BLOCK_DECL (flags);

        MPFR_BLOCK (flags, div_inex = mpfr_div (tmp, y, x, MPFR_RNDN));
        if (div_inex == 0)
          {
            /* Result is exact. */
            inexact = mpfr_atan (dest, tmp, rnd_mode);
            goto end;
          }

        /* Error <= ulp (tmp) except in case of underflow or overflow. */

        /* If the division underflowed, since |atan(z)/z| < 1, we have
           an underflow. */
        if (MPFR_UNDERFLOW (flags))
          {
            int sign;

            /* In the case MPFR_RNDN with 2^(emin-2) < |y/x| < 2^(emin-1):
               The smallest significand value S > 1 of |y/x| is:
                 * 1 / (1 - 2^(-px))                        if py <= px,
                 * (1 - 2^(-px) + 2^(-py)) / (1 - 2^(-px))  if py >= px.
               Therefore S - 1 > 2^(-pz), where pz = max(px,py). We have:
               atan(|y/x|) > atan(z), where z = 2^(emin-2) * (1 + 2^(-pz)).
                           > z - z^3 / 3.
                           > 2^(emin-2) * (1 + 2^(-pz) - 2^(2 emin - 5))
               Assuming pz <= -2 emin + 5, we can round away from zero
               (this is what mpfr_underflow always does on MPFR_RNDN).
               In the case MPFR_RNDN with |y/x| <= 2^(emin-2), we round
               toward zero, as |atan(z)/z| < 1. */
            MPFR_ASSERTN (MPFR_PREC_MAX <=
                          2 * (mpfr_uexp_t) - MPFR_EMIN_MIN + 5);
            if (rnd_mode == MPFR_RNDN && MPFR_IS_ZERO (tmp))
              rnd_mode = MPFR_RNDZ;
            sign = MPFR_SIGN (tmp);
            mpfr_clear (tmp);
            MPFR_SAVE_EXPO_FREE (expo);
            return mpfr_underflow (dest, rnd_mode, sign);
          }

        mpfr_atan (tmp, tmp, MPFR_RNDN);   /* Error <= 2*ulp (tmp) since
                                             abs(D(arctan)) <= 1 */
        /* TODO: check that the error bound is correct in case of overflow. */
        /* FIXME: Error <= ulp(tmp) ? */
        if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - 2, MPFR_PREC (dest),
                                         rnd_mode)))
          break;
        MPFR_ZIV_NEXT (loop, prec);
        mpfr_set_prec (tmp, prec);
      }
  else /* x < 0 */
    /*  Use sign(y)*(PI - atan (|y/x|)) */
    {
      mpfr_init2 (pi, prec);
      for (;;)
        {
          mpfr_div (tmp, y, x, MPFR_RNDN);   /* Error <= ulp (tmp) */
          /* If tmp is 0, we have |y/x| <= 2^(-emin-2), thus
             atan|y/x| < 2^(-emin-2). */
          MPFR_SET_POS (tmp);               /* no error */
          mpfr_atan (tmp, tmp, MPFR_RNDN);   /* Error <= 2*ulp (tmp) since
                                               abs(D(arctan)) <= 1 */
          mpfr_const_pi (pi, MPFR_RNDN);     /* Error <= ulp(pi) /2 */
          e = MPFR_NOTZERO(tmp) ? MPFR_GET_EXP (tmp) : __gmpfr_emin - 1;
          mpfr_sub (tmp, pi, tmp, MPFR_RNDN);          /* see above */
          if (MPFR_IS_NEG (y))
            MPFR_CHANGE_SIGN (tmp);
          /* Error(tmp) <= (1/2+2^(EXP(pi)-EXP(tmp)-1)+2^(e-EXP(tmp)+1))*ulp
                        <= 2^(MAX (MAX (EXP(PI)-EXP(tmp)-1, e-EXP(tmp)+1),
                                        -1)+2)*ulp(tmp) */
          e = MAX (MAX (MPFR_GET_EXP (pi)-MPFR_GET_EXP (tmp) - 1,
                        e - MPFR_GET_EXP (tmp) + 1), -1) + 2;
          if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - e, MPFR_PREC (dest),
                                           rnd_mode)))
            break;
          MPFR_ZIV_NEXT (loop, prec);
          mpfr_set_prec (tmp, prec);
          mpfr_set_prec (pi, prec);
        }
      mpfr_clear (pi);
    }
  inexact = mpfr_set (dest, tmp, rnd_mode);

 end:
  MPFR_ZIV_FREE (loop);
  mpfr_clear (tmp);
  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (dest, inexact, rnd_mode);
}
Пример #15
0
static void
tst (void)
{
  int sv = sizeof (val) / sizeof (*val);
  int i, j;
  int rnd;
  mpfr_t x, y, z, tmp;

  mpfr_inits2 (53, x, y, z, tmp, (mpfr_ptr) 0);

  for (i = 0; i < sv; i++)
    for (j = 0; j < sv; j++)
      RND_LOOP (rnd)
        {
          int exact, inex;
          unsigned int flags;

          if (my_setstr (x, val[i]) || my_setstr (y, val[j]))
            {
              printf ("internal error for (%d,%d,%d)\n", i, j, rnd);
              exit (1);
            }
          mpfr_clear_flags ();
          inex = mpfr_pow (z, x, y, (mpfr_rnd_t) rnd);
          flags = __gmpfr_flags;
          if (! MPFR_IS_NAN (z) && mpfr_nanflag_p ())
            err ("got NaN flag without NaN value", i, j, rnd, z, inex);
          if (MPFR_IS_NAN (z) && ! mpfr_nanflag_p ())
            err ("got NaN value without NaN flag", i, j, rnd, z, inex);
          if (inex != 0 && ! mpfr_inexflag_p ())
            err ("got non-zero ternary value without inexact flag",
                 i, j, rnd, z, inex);
          if (inex == 0 && mpfr_inexflag_p ())
            err ("got null ternary value with inexact flag",
                 i, j, rnd, z, inex);
          if (i >= 3 && j >= 3)
            {
              if (mpfr_underflow_p ())
                err ("got underflow", i, j, rnd, z, inex);
              if (mpfr_overflow_p ())
                err ("got overflow", i, j, rnd, z, inex);
              exact = MPFR_IS_SINGULAR (z) ||
                (mpfr_mul_2ui (tmp, z, 16, MPFR_RNDN), mpfr_integer_p (tmp));
              if (exact && inex != 0)
                err ("got exact value with ternary flag different from 0",
                     i, j, rnd, z, inex);
              if (! exact && inex == 0)
                err ("got inexact value with ternary flag equal to 0",
                     i, j, rnd, z, inex);
            }
          if (MPFR_IS_ZERO (x) && ! MPFR_IS_NAN (y) && MPFR_NOTZERO (y))
            {
              if (MPFR_IS_NEG (y) && ! MPFR_IS_INF (z))
                err ("expected an infinity", i, j, rnd, z, inex);
              if (MPFR_IS_POS (y) && ! MPFR_IS_ZERO (z))
                err ("expected a zero", i, j, rnd, z, inex);
              if ((MPFR_IS_NEG (x) && is_odd (y)) ^ MPFR_IS_NEG (z))
                err ("wrong sign", i, j, rnd, z, inex);
            }
          if (! MPFR_IS_NAN (x) && mpfr_cmp_si (x, -1) == 0)
            {
              /* x = -1 */
              if (! (MPFR_IS_INF (y) || mpfr_integer_p (y)) &&
                  ! MPFR_IS_NAN (z))
                err ("expected NaN", i, j, rnd, z, inex);
              if ((MPFR_IS_INF (y) || (mpfr_integer_p (y) && ! is_odd (y)))
                  && ! mpfr_equal_p (z, __gmpfr_one))
                err ("expected 1", i, j, rnd, z, inex);
              if (is_odd (y) &&
                  (MPFR_IS_NAN (z) || mpfr_cmp_si (z, -1) != 0))
                err ("expected -1", i, j, rnd, z, inex);
            }
          if ((mpfr_equal_p (x, __gmpfr_one) || MPFR_IS_ZERO (y)) &&
              ! mpfr_equal_p (z, __gmpfr_one))
            err ("expected 1", i, j, rnd, z, inex);
          if (MPFR_IS_PURE_FP (x) && MPFR_IS_NEG (x) &&
              MPFR_IS_FP (y) && ! mpfr_integer_p (y) &&
              ! MPFR_IS_NAN (z))
            err ("expected NaN", i, j, rnd, z, inex);
          if (MPFR_IS_INF (y) && MPFR_NOTZERO (x))
            {
              int cmpabs1 = mpfr_cmpabs (x, __gmpfr_one);

              if ((MPFR_IS_NEG (y) ? (cmpabs1 < 0) : (cmpabs1 > 0)) &&
                  ! (MPFR_IS_POS (z) && MPFR_IS_INF (z)))
                err ("expected +Inf", i, j, rnd, z, inex);
              if ((MPFR_IS_NEG (y) ? (cmpabs1 > 0) : (cmpabs1 < 0)) &&
                  ! (MPFR_IS_POS (z) && MPFR_IS_ZERO (z)))
                err ("expected +0", i, j, rnd, z, inex);
            }
          if (MPFR_IS_INF (x) && ! MPFR_IS_NAN (y) && MPFR_NOTZERO (y))
            {
              if (MPFR_IS_POS (y) && ! MPFR_IS_INF (z))
                err ("expected an infinity", i, j, rnd, z, inex);
              if (MPFR_IS_NEG (y) && ! MPFR_IS_ZERO (z))
                err ("expected a zero", i, j, rnd, z, inex);
              if ((MPFR_IS_NEG (x) && is_odd (y)) ^ MPFR_IS_NEG (z))
                err ("wrong sign", i, j, rnd, z, inex);
            }
          test_others (val[i], val[j], (mpfr_rnd_t) rnd, x, y, z, inex, flags,
                       "tst");
        }
  mpfr_clears (x, y, z, tmp, (mpfr_ptr) 0);
}
Пример #16
0
static void
generic_tests (void)
{
  mpfr_t exact_sum, sum1, sum2;
  mpfr_t *t;
  mpfr_ptr *p;
  mpfr_prec_t precmax = 444;
  int i, m, nmax = 500;
  int rnd_mode;

  t = (mpfr_t *) tests_allocate (nmax * sizeof(mpfr_t));
  p = (mpfr_ptr *) tests_allocate (nmax * sizeof(mpfr_ptr));
  for (i = 0; i < nmax; i++)
    {
      mpfr_init2 (t[i], precmax);
      p[i] = t[i];
    }
  mpfr_inits2 (precmax, exact_sum, sum1, sum2, (mpfr_ptr) 0);

  for (m = 0; m < 4000; m++)
    {
      int non_uniform, n;
      mpfr_prec_t prec;

      non_uniform = randlimb () % 10;
      n = (randlimb () % nmax) + 1;
      prec = MPFR_PREC_MIN + (randlimb () % (precmax - MPFR_PREC_MIN + 1));
      mpfr_set_prec (sum1, prec);
      mpfr_set_prec (sum2, prec);

      for (i = 0; i < n; i++)
        {
          mpfr_set_prec (t[i], MPFR_PREC_MIN +
                         (randlimb () % (precmax - MPFR_PREC_MIN + 1)));
          mpfr_urandomb (t[i], RANDS);
          if (m % 8 != 0 && (m % 8 == 1 || (randlimb () & 1)))
            mpfr_neg (t[i], t[i], MPFR_RNDN);
          if (non_uniform && MPFR_NOTZERO (t[i]))
            mpfr_set_exp (t[i], randlimb () % 1000);
          /* putchar ("-0+"[SIGN (mpfr_sgn (t[i])) + 1]); */
        }
      /* putchar ('\n'); */
      get_exact_sum (exact_sum, t, n);
      RND_LOOP (rnd_mode)
        {
          int inex1, inex2;

          inex1 = mpfr_set (sum1, exact_sum, (mpfr_rnd_t) rnd_mode);
          inex2 = mpfr_sum (sum2, p, n, (mpfr_rnd_t) rnd_mode);
          if (!(mpfr_equal_p (sum1, sum2) && SAME_SIGN (inex1, inex2)))
            {
              printf ("generic_tests failed on m = %d, %s\n", m,
                      mpfr_print_rnd_mode ((mpfr_rnd_t) rnd_mode));
              printf ("Expected ");
              mpfr_dump (sum1);
              printf ("with inex = %d\n", inex1);
              printf ("Got      ");
              mpfr_dump (sum2);
              printf ("with inex = %d\n", inex2);
              exit (1);
            }
        }
    }

  for (i = 0; i < nmax; i++)
    mpfr_clear (t[i]);
  mpfr_clears (exact_sum, sum1, sum2, (mpfr_ptr) 0);
  tests_free (t, nmax * sizeof(mpfr_t));
  tests_free (p, nmax * sizeof(mpfr_ptr));
}
Пример #17
0
/* generic code */
__float128
mpfr_get_float128 (mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    return (__float128) mpfr_get_d (x, rnd_mode);
  else /* now x is a normal non-zero number */
    {
      __float128 r; /* result */
      __float128 m;
      double s; /* part of result */
      mpfr_exp_t sh; /* exponent shift, so that x/2^sh is in the double range */
      mpfr_t y, z;
      int sign;

      /* first round x to the target __float128 precision, so that
         all subsequent operations are exact (this avoids double rounding
         problems) */
      mpfr_init2 (y, IEEE_FLOAT128_MANT_DIG);
      mpfr_init2 (z, IEEE_FLOAT128_MANT_DIG);

      mpfr_set (y, x, rnd_mode);
      sh = MPFR_GET_EXP (y);
      sign = MPFR_SIGN (y);
      MPFR_SET_EXP (y, 0);
      MPFR_SET_POS (y);

      r = 0.0;
      do
        {
          s = mpfr_get_d (y, MPFR_RNDN); /* high part of y */
          r += (__float128) s;
          mpfr_set_d (z, s, MPFR_RNDN);  /* exact */
          mpfr_sub (y, y, z, MPFR_RNDN); /* exact */
        }
      while (MPFR_NOTZERO (y));

      mpfr_clear (z);
      mpfr_clear (y);

      /* we now have to multiply r by 2^sh */
      MPFR_ASSERTD (r > 0);
      if (sh != 0)
        {
          /* An overflow may occur (example: 0.5*2^1024) */
          while (r < 1.0)
            {
              r += r;
              sh--;
            }

          if (sh > 0)
            m = 2.0;
          else
            {
              m = 0.5;
              sh = -sh;
            }

          for (;;)
            {
              if (sh % 2)
                r = r * m;
              sh >>= 1;
              if (sh == 0)
                break;
              m = m * m;
            }
        }
      if (sign < 0)
        r = -r;
      return r;
    }
}
static void
check_parse (void)
{
  mpfr_t x;
  char *s;
  int res;

  mpfr_init (x);

  /* Invalid data */
  mpfr_set_si (x, -1, MPFR_RNDN);
  res = mpfr_strtofr (x, "  invalid", NULL, 10, MPFR_RNDN);
  if (MPFR_NOTZERO (x) || MPFR_IS_NEG (x))
    {
      printf ("Failed parsing '  invalid' (1)\n X=");
      mpfr_dump (x);
      exit (1);
    }
  MPFR_ASSERTN (res == 0);
  mpfr_set_si (x, -1, MPFR_RNDN);
  res = mpfr_strtofr (x, "  invalid", &s, 0, MPFR_RNDN);
  if (MPFR_NOTZERO (x) || MPFR_IS_NEG (x) || strcmp (s, "  invalid"))
    {
      printf ("Failed parsing '  invalid' (2)\n S=%s\n X=", s);
      mpfr_dump (x);
      exit (1);
    }
  MPFR_ASSERTN (res == 0);
  /* Check if it stops correctly */
  mpfr_strtofr (x, "15*x", &s, 10, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 15) || strcmp (s, "*x"))
    {
      printf ("Failed parsing '15*x'\n S=%s\n X=", s);
      mpfr_dump (x);
      exit (1);
    }
  /* Check for leading spaces */
  mpfr_strtofr (x, "  1.5E-10 *x^2", &s, 10, MPFR_RNDN);
  if (mpfr_cmp_str1 (x, "1.5E-10") || strcmp (s, " *x^2"))
    {
      printf ("Failed parsing '1.5E-10*x^2'\n S=%s\n X=", s);
      mpfr_dump (x);
      exit (1);
    }
  /* Check for leading sign */
  mpfr_strtofr (x, "  +17.5E-42E ", &s, 10, MPFR_RNDN);
  if (mpfr_cmp_str1 (x, "17.5E-42") || strcmp (s, "E "))
    {
      printf ("Failed parsing '+17.5E-42E '\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-17.5E+42E\n", &s, 10, MPFR_RNDN);
  if (mpfr_cmp_str1 (x, "-17.5E42") || strcmp (s, "E\n"))
    {
      printf ("Failed parsing '-17.5E+42\\n'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* P form */
  mpfr_strtofr (x, "0x42P17", &s, 16, MPFR_RNDN);
  if (mpfr_cmp_str (x, "8650752", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '0x42P17' (base = 16)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-0X42p17", &s, 16, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-8650752", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-0x42p17' (base = 16)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "42p17", &s, 16, MPFR_RNDN);
  if (mpfr_cmp_str (x, "8650752", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '42p17' (base = 16)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-42P17", &s, 16, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-8650752", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-42P17' (base = 16)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "0b1001P17", &s, 2, MPFR_RNDN);
  if (mpfr_cmp_str (x, "1179648", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '0b1001P17' (base = 2)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-0B1001p17", &s, 2, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-1179648", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-0B1001p17' (base = 2)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "1001p17", &s, 2, MPFR_RNDN);
  if (mpfr_cmp_str (x, "1179648", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '1001p17' (base = 2)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-1001P17", &s, 2, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-1179648", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-1001P17' (base = 2)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Check for auto-detection of the base */
  mpfr_strtofr (x, "+0x42P17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "42P17", 16, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '+0x42P17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-42E17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-42E17", 10, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '-42E17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-42P17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "-42", 10, MPFR_RNDN) || strcmp (s, "P17"))
    {
      printf ("Failed parsing '-42P17' (base = 0)\n S='%s'\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, " 0b0101.011@42", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "0101.011@42", 2, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '0101.011@42'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, " 0b0101.011P42", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "0101.011@42", 2, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '0101.011@42'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "+0x42@17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str (x, "4.2@18", 16, MPFR_RNDN) || *s != 0)
    {
      printf ("Failed parsing '+0x42P17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }


  /* Check for space inside the mantissa */
  mpfr_strtofr (x, "+0x4 2@17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 4) || strcmp(s," 2@17"))
    {
      printf ("Failed parsing '+0x4 2@17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "+0x42 P17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 0x42) || strcmp(s," P17"))
    {
      printf ("Failed parsing '+0x42 P17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Space between mantissa and exponent */
  mpfr_strtofr (x, " -0b0101P 17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_si (x, -5) || strcmp(s,"P 17"))
    {
      printf ("Failed parsing '-0b0101P 17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Check for Invalid exponent. */
  mpfr_strtofr (x, " -0b0101PF17", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_si (x, -5) || strcmp(s,"PF17"))
    {
      printf ("Failed parsing '-0b0101PF17'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* At least one digit in the mantissa. */
  mpfr_strtofr (x, " .E10", &s, 0, MPFR_RNDN);
  if (strcmp(s," .E10"))
    {
      printf ("Failed parsing ' .E10'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Check 2 '.': 2.3.4   */
  mpfr_strtofr (x, "-1.2.3E4", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_str1 (x, "-1.2") || strcmp(s,".3E4"))
    {
      printf ("Failed parsing '-1.2.3E4'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  /* Check for 0x and 0b */
  mpfr_strtofr (x, "  0xG", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 0) || strcmp(s,"xG"))
    {
      printf ("Failed parsing '  0xG'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "  0b2", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 0) || strcmp(s,"b2"))
    {
      printf ("Failed parsing '  0b2'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "-0x.23@2Z33", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_si (x, -0x23) || strcmp(s,"Z33"))
    {
      printf ("Failed parsing '-0x.23@2Z33'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }
  mpfr_strtofr (x, "  0x", &s, 0, MPFR_RNDN);
  if (mpfr_cmp_ui (x, 0) || strcmp(s,"x"))
    {
      printf ("Failed parsing '  0x'\n S=%s\n X=", s);
      mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n');
      exit (1);
    }

  mpfr_clear (x);
}
Пример #19
0
static void
test_urandomb (long nbtests, mpfr_prec_t prec, int verbose)
{
    mpfr_t x;
    int *tab, size_tab, k, sh, xn;
    double d, av = 0, var = 0, chi2 = 0, th;
    mpfr_exp_t emin;

    size_tab = (nbtests >= 1000 ? nbtests / 50 : 20);
    tab = (int *) calloc (size_tab, sizeof(int));
    if (tab == NULL)
    {
        fprintf (stderr, "trandom: can't allocate memory in test_urandomb\n");
        exit (1);
    }

    mpfr_init2 (x, prec);
    xn = 1 + (prec - 1) / mp_bits_per_limb;
    sh = xn * mp_bits_per_limb - prec;

    for (k = 0; k < nbtests; k++)
    {
        mpfr_urandomb (x, RANDS);
        MPFR_ASSERTN (MPFR_IS_FP (x));
        /* check that lower bits are zero */
        if (MPFR_NOTZERO(x) && (MPFR_MANT(x)[0] & MPFR_LIMB_MASK(sh)))
        {
            printf ("Error: mpfr_urandomb() returns invalid numbers:\n");
            mpfr_dump (x);
            exit (1);
        }
        d = mpfr_get_d1 (x);
        av += d;
        var += d*d;
        tab[(int)(size_tab * d)]++;
    }

    /* coverage test */
    emin = mpfr_get_emin ();
    set_emin (1); /* the generated number in [0,1[ is not in the exponent
                        range, except if it is zero */
    k = mpfr_urandomb (x, RANDS);
    if (MPFR_IS_ZERO(x) == 0 && (k == 0 || mpfr_nan_p (x) == 0))
    {
        printf ("Error in mpfr_urandomb, expected NaN, got ");
        mpfr_dump (x);
        exit (1);
    }
    set_emin (emin);

    mpfr_clear (x);
    if (!verbose)
    {
        free(tab);
        return;
    }

    av /= nbtests;
    var = (var / nbtests) - av * av;

    th = (double)nbtests / size_tab;
    printf("Average = %.5f\nVariance = %.5f\n", av, var);
    printf("Repartition for urandomb. Each integer should be close to %d.\n",
           (int)th);

    for (k = 0; k < size_tab; k++)
    {
        chi2 += (tab[k] - th) * (tab[k] - th) / th;
        printf("%d ", tab[k]);
        if (((k+1) & 7) == 0)
            printf("\n");
    }

    printf("\nChi2 statistics value (with %d degrees of freedom) : %.5f\n\n",
           size_tab - 1, chi2);

    free(tab);
    return;
}