Ejemplo n.º 1
0
    // Refine the random square
    mpfr_prec_t Refine(gmp_randstate_t r, mpfr_prec_t prec, long num = 1)
      const {
      if (num <= 0) return prec;
      // Use _vx as scratch
      prec += num * chunk_;
      mpfr_div_2ui(_eps, _eps, num * chunk_, MPFR_RNDN);

      mpz_urandomb(_ui, r, num * chunk_);
      mpfr_set_prec(_up, prec);
      mpfr_set_z_2exp(_up, _ui, -prec, MPFR_RNDN);
      mpfr_set_prec(_vx, prec);
      mpfr_add(_vx, _u, _up, MPFR_RNDN);
      mpfr_swap(_u, _vx);       // u = vx
      mpfr_add(_up, _u, _eps, MPFR_RNDN);

      mpz_urandomb(_vi, r, num * chunk_);
      mpfr_set_prec(_vp, prec);
      mpfr_set_z_2exp(_vp, _vi, -prec, MPFR_RNDN);
      mpfr_set_prec(_vx, prec);
      mpfr_add(_vx, _v, _vp, MPFR_RNDN);
      mpfr_swap(_v, _vx);       // v = vx
      mpfr_add(_vp, _v, _eps, MPFR_RNDN);

      return prec;
    }
Ejemplo n.º 2
0
static void
check0 (void)
{
  mpz_t y;
  mpfr_t x;
  int inexact, r;
  mpfr_exp_t e;

  /* Check for +0 */
  mpfr_init (x);
  mpz_init (y);
  mpz_set_si (y, 0);
  for (r = 0; r < MPFR_RND_MAX; r++)
    {
      e = randexp ();
      inexact = mpfr_set_z_2exp (x, y, e, (mpfr_rnd_t) r);
      if (!MPFR_IS_ZERO(x) || !MPFR_IS_POS(x) || inexact)
        {
          printf ("mpfr_set_z_2exp(x,0,e) failed for e=");
          if (e < LONG_MIN)
            printf ("(<LONG_MIN)");
          else if (e > LONG_MAX)
            printf ("(>LONG_MAX)");
          else
            printf ("%ld", (long) e);
          printf (", rnd=%s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r));
          exit (1);
        }
    }
  mpfr_clear(x);
  mpz_clear(y);
}
Ejemplo n.º 3
0
int
fmpr_get_mpfr(mpfr_t x, const fmpr_t y, mpfr_rnd_t rnd)
{
    int r;

    if (fmpr_is_special(y))
    {
        if (fmpr_is_zero(y)) mpfr_set_zero(x, 0);
        else if (fmpr_is_pos_inf(y)) mpfr_set_inf(x, 1);
        else if (fmpr_is_neg_inf(y)) mpfr_set_inf(x, -1);
        else mpfr_set_nan(x);
        r = 0;
    }
    else if (COEFF_IS_MPZ(*fmpr_expref(y)))
    {
        flint_printf("exception: exponent too large to convert to mpfr");
        abort();
    }
    else
    {
        if (!COEFF_IS_MPZ(*fmpr_manref(y)))
#if defined(__MINGW64__) 
            r = mpfr_set_sj_2exp(x, *fmpr_manref(y), *fmpr_expref(y), rnd);
#else
            r = mpfr_set_si_2exp(x, *fmpr_manref(y), *fmpr_expref(y), rnd);
#endif
        else
            r = mpfr_set_z_2exp(x, COEFF_TO_PTR(*fmpr_manref(y)), *fmpr_expref(y), rnd);

        if (!mpfr_regular_p(x))
        {
            flint_printf("exception: exponent too large to convert to mpfr");
            abort();
        }
    }
Ejemplo n.º 4
0
static void
check (long i, mpfr_rnd_t rnd)
{
  mpfr_t f;
  mpz_t z;
  mpfr_exp_t e;
  int inex;

  /* using CHAR_BIT * sizeof(long) bits of precision ensures that
     mpfr_set_z_2exp is exact below */
  mpfr_init2 (f, CHAR_BIT * sizeof(long));
  mpz_init (z);
  mpz_set_ui (z, i);
  /* the following loop ensures that no overflow occurs */
  do
    e = randexp ();
  while (e > mpfr_get_emax () - CHAR_BIT * sizeof(long));
  inex = mpfr_set_z_2exp (f, z, e, rnd);
  if (inex != 0)
    {
      printf ("Error in mpfr_set_z_2exp for i=%ld, e=%ld,"
              " wrong ternary value\n", i, (long) e);
      printf ("expected 0, got %d\n", inex);
      exit (1);
    }
  mpfr_div_2si (f, f, e, rnd);
  if (mpfr_get_si (f, MPFR_RNDZ) != i)
    {
      printf ("Error in mpfr_set_z_2exp for i=%ld e=", i);
      if (e < LONG_MIN)
        printf ("(<LONG_MIN)");
      else if (e > LONG_MAX)
        printf ("(>LONG_MAX)");
      else
        printf ("%ld", (long) e);
      printf (" rnd_mode=%d\n", rnd);
      printf ("expected %ld\n", i);
      printf ("got      "); mpfr_dump (f);
      exit (1);
    }
  mpfr_clear (f);
  mpz_clear (z);
}
Ejemplo n.º 5
0
/* set f to the integer z */
int
mpfr_set_z (mpfr_ptr f, mpz_srcptr z, mpfr_rnd_t rnd_mode)
{
  return mpfr_set_z_2exp (f, z, 0, rnd_mode);
}
Ejemplo n.º 6
0
    /**
     * Sample from the normal distribution with mean 0 and variance 1.
     *
     * @param[out] val the sample from the normal distribution
     * @param[in,out] r a GMP random generator.
     * @param[in] round the rounding direction.
     * @return the MPFR ternary result (&plusmn;1 if val is larger/smaller than
     *   the exact sample).
     **********************************************************************/
    int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const {
      const double
        s  =  0.449871, // Constants from Leva
        t  = -0.386595,
        a  =  0.19600 ,
        b  =  0.25472 ,
        r1 =  0.27597 ,
        r2 =  0.27846 ,
        u1 =  0.606530,           // sqrt(1/e) rounded down and up
        u2 =  0.606531,
        scale = std::pow(2.0, -chunk_); // for turning randoms into doubles

      while (true) {
        mpz_urandomb(_vi, r, chunk_);
        if (mpz_cmp_ui(_vi, m) >= 0) continue; // Very early reject
        double vf = (mpz_get_ui(_vi) + 0.5) * scale;
        mpz_urandomb(_ui, r, chunk_);
        double uf = (mpz_get_ui(_ui) + 0.5) * scale;
        double
          x = uf - s,
          y = vf - t,
          Q = x*x + y * (a*y - b*x);
        if (Q >= r2) continue;    // Early reject
        mpfr_set_ui_2exp(_eps, 1u, -chunk_, MPFR_RNDN);
        mpfr_prec_t prec = chunk_;
        mpfr_set_prec(_u, prec);
        mpfr_set_prec(_v, prec);
        // (u,v) = sw corner of range
        mpfr_set_z_2exp(_u, _ui, -prec, MPFR_RNDN);
        mpfr_set_z_2exp(_v, _vi, -prec, MPFR_RNDN);
        mpfr_set_prec(_up, prec);
        mpfr_set_prec(_vp, prec);
        // (up,vp) = ne corner of range
        mpfr_add(_up, _u, _eps, MPFR_RNDN);
        mpfr_add(_vp, _v, _eps, MPFR_RNDN);
        // Estimate how many extra bits will be needed to achieve the desired
        // precision.
        mpfr_prec_t prec_guard = 3 + chunk_ -
          (std::max)(mpz_sizeinbase(_ui, 2), mpz_sizeinbase(_vi, 2));
        if (Q > r1) {
          int reject;
          while (true) {
            // Rejection curve v^2 + 4 * u^2 * log(u) < 0 has a peak at u =
            // exp(-1/2) = 0.60653066.  So treat uf in (0.606530, 0.606531) =
            // (u1, u2) specially

            // Try for rejection first
            if (uf <= u1)
              reject = Reject(_u, _vp, prec, MPFR_RNDU);
            else if (uf >= u2)
              reject = Reject(_up, _vp, prec, MPFR_RNDU);
            else {              // u in (u1, u2)
              mpfr_set_prec(_vx, prec);
              mpfr_add(_vx, _vp, _eps, MPFR_RNDN);
              reject = Reject(_u, _vx, prec, MPFR_RNDU); // Could use _up too
            }
            if (reject < 0) break; // tried to reject but failed, so accept

            // Try for acceptance
            if (uf <= u1)
              reject = Reject(_up, _v, prec, MPFR_RNDD);
            else if (uf >= u2)
              reject = Reject(_u, _v, prec, MPFR_RNDD);
            else {              // u in (u2, u2)
              mpfr_sub(_vx, _v, _eps, MPFR_RNDN);
              reject = Reject(_u, _vx, prec, MPFR_RNDD); // Could use _up too
            }
            if (reject > 0) break; // tried to accept but failed, so reject

            prec = Refine(r, prec);  // still can't decide, to refine
          }
          if (reject > 0) continue; // reject, back to outer loop
        }
        // Now evaluate v/u to the necessary precision
        mpfr_prec_t prec0 = mpfr_get_prec (val);
        //        while (prec < prec0 + prec_guard) prec = Refine(r, prec);
        if (prec < prec0 + prec_guard)
          prec = Refine(r, prec,
                        (prec0 + prec_guard - prec + chunk_ - 1) / chunk_);
        mpfr_set_prec(_x1, prec0);
        mpfr_set_prec(_x2, prec0);
        int flag;
        while (true) {
          int
            f1 = mpfr_div(_x1, _v, _up, round),   // min slope
            f2 = mpfr_div(_x2, _vp, _u, round);   // max slope
          if (f1 == f2 && mpfr_equal_p(_x1, _x2)) {
            flag = f1;
            break;
          }
          prec = Refine(r, prec);
        }
        mpz_urandomb(_ui, r, 1);
        if (mpz_tstbit(_ui, 0)) {
          flag = -flag;
          mpfr_neg(val, _x1, MPFR_RNDN);
        } else
          mpfr_set(val, _x1, MPFR_RNDN);
        //      std::cerr << uf << " " << vf << " " << Q << "\n";
        return flag;
      }
    }
Ejemplo n.º 7
0
static int
mpfr_rem1 (mpfr_ptr rem, long *quo, mpfr_rnd_t rnd_q,
           mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd)
{
  mpfr_exp_t ex, ey;
  int compare, inex, q_is_odd, sign, signx = MPFR_SIGN (x);
  mpz_t mx, my, r;
  int tiny = 0;

  MPFR_ASSERTD (rnd_q == MPFR_RNDN || rnd_q == MPFR_RNDZ);

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x) || MPFR_IS_SINGULAR (y)))
    {
      if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y) || MPFR_IS_INF (x)
          || MPFR_IS_ZERO (y))
        {
          /* for remquo, quo is undefined */
          MPFR_SET_NAN (rem);
          MPFR_RET_NAN;
        }
      else                      /* either y is Inf and x is 0 or non-special,
                                   or x is 0 and y is non-special,
                                   in both cases the quotient is zero. */
        {
          if (quo)
            *quo = 0;
          return mpfr_set (rem, x, rnd);
        }
    }

  /* now neither x nor y is NaN, Inf or zero */

  mpz_init (mx);
  mpz_init (my);
  mpz_init (r);

  ex = mpfr_get_z_2exp (mx, x);  /* x = mx*2^ex */
  ey = mpfr_get_z_2exp (my, y);  /* y = my*2^ey */

  /* to get rid of sign problems, we compute it separately:
     quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y)
     quo(-x,y) = -quo(x,y), rem(-x,y)  = -rem(x,y)
     thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */
  sign = (signx == MPFR_SIGN (y)) ? 1 : -1;
  mpz_abs (mx, mx);
  mpz_abs (my, my);
  q_is_odd = 0;

  /* divide my by 2^k if possible to make operations mod my easier */
  {
    unsigned long k = mpz_scan1 (my, 0);
    ey += k;
    mpz_fdiv_q_2exp (my, my, k);
  }

  if (ex <= ey)
    {
      /* q = x/y = mx/(my*2^(ey-ex)) */

      /* First detect cases where q=0, to avoid creating a huge number
         my*2^(ey-ex): if sx = mpz_sizeinbase (mx, 2) and sy =
         mpz_sizeinbase (my, 2), we have x < 2^(ex + sx) and
         y >= 2^(ey + sy - 1), thus if ex + sx <= ey + sy - 1
         the quotient is 0 */
      if (ex + (mpfr_exp_t) mpz_sizeinbase (mx, 2) <
          ey + (mpfr_exp_t) mpz_sizeinbase (my, 2))
        {
          tiny = 1;
          mpz_set (r, mx);
          mpz_set_ui (mx, 0);
        }
      else
        {
          mpz_mul_2exp (my, my, ey - ex);   /* divide mx by my*2^(ey-ex) */

          /* since mx > 0 and my > 0, we can use mpz_tdiv_qr in all cases */
          mpz_tdiv_qr (mx, r, mx, my);
          /* 0 <= |r| <= |my|, r has the same sign as mx */
        }

      if (rnd_q == MPFR_RNDN)
        q_is_odd = mpz_tstbit (mx, 0);
      if (quo)                  /* mx is the quotient */
        {
          mpz_tdiv_r_2exp (mx, mx, WANTED_BITS);
          *quo = mpz_get_si (mx);
        }
    }
  else                          /* ex > ey */
    {
      if (quo) /* remquo case */
        /* for remquo, to get the low WANTED_BITS more bits of the quotient,
           we first compute R =  X mod Y*2^WANTED_BITS, where X and Y are
           defined below. Then the low WANTED_BITS of the quotient are
           floor(R/Y). */
        mpz_mul_2exp (my, my, WANTED_BITS);     /* 2^WANTED_BITS*Y */

      else if (rnd_q == MPFR_RNDN) /* remainder case */
        /* Let X = mx*2^(ex-ey) and Y = my. Then both X and Y are integers.
           Assume X = R mod Y, then x = X*2^ey = R*2^ey mod (Y*2^ey=y).
           To be able to perform the rounding, we need the least significant
           bit of the quotient, i.e., one more bit in the remainder,
           which is obtained by dividing by 2Y. */
        mpz_mul_2exp (my, my, 1);       /* 2Y */

      mpz_set_ui (r, 2);
      mpz_powm_ui (r, r, ex - ey, my);  /* 2^(ex-ey) mod my */
      mpz_mul (r, r, mx);
      mpz_mod (r, r, my);

      if (quo)                  /* now 0 <= r < 2^WANTED_BITS*Y */
        {
          mpz_fdiv_q_2exp (my, my, WANTED_BITS);   /* back to Y */
          mpz_tdiv_qr (mx, r, r, my);
          /* oldr = mx*my + newr */
          *quo = mpz_get_si (mx);
          q_is_odd = *quo & 1;
        }
      else if (rnd_q == MPFR_RNDN) /* now 0 <= r < 2Y in the remainder case */
        {
          mpz_fdiv_q_2exp (my, my, 1);     /* back to Y */
          /* least significant bit of q */
          q_is_odd = mpz_cmpabs (r, my) >= 0;
          if (q_is_odd)
            mpz_sub (r, r, my);
        }
      /* now 0 <= |r| < |my|, and if needed,
         q_is_odd is the least significant bit of q */
    }

  if (mpz_cmp_ui (r, 0) == 0)
    {
      inex = mpfr_set_ui (rem, 0, MPFR_RNDN);
      /* take into account sign of x */
      if (signx < 0)
        mpfr_neg (rem, rem, MPFR_RNDN);
    }
  else
    {
      if (rnd_q == MPFR_RNDN)
        {
          /* FIXME: the comparison 2*r < my could be done more efficiently
             at the mpn level */
          mpz_mul_2exp (r, r, 1);
          /* if tiny=1, we should compare r with my*2^(ey-ex) */
          if (tiny)
            {
              if (ex + (mpfr_exp_t) mpz_sizeinbase (r, 2) <
                  ey + (mpfr_exp_t) mpz_sizeinbase (my, 2))
                compare = 0; /* r*2^ex < my*2^ey */
              else
                {
                  mpz_mul_2exp (my, my, ey - ex);
                  compare = mpz_cmpabs (r, my);
                }
            }
          else
            compare = mpz_cmpabs (r, my);
          mpz_fdiv_q_2exp (r, r, 1);
          compare = ((compare > 0) ||
                     ((rnd_q == MPFR_RNDN) && (compare == 0) && q_is_odd));
          /* if compare != 0, we need to subtract my to r, and add 1 to quo */
          if (compare)
            {
              mpz_sub (r, r, my);
              if (quo && (rnd_q == MPFR_RNDN))
                *quo += 1;
            }
        }
      /* take into account sign of x */
      if (signx < 0)
        mpz_neg (r, r);
      inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd);
    }

  if (quo)
    *quo *= sign;

  mpz_clear (mx);
  mpz_clear (my);
  mpz_clear (r);

  return inex;
}