Ejemplo n.º 1
0
Archivo: pow.c Proyecto: tomi500/MPC
/* fix the sign of Re(z) or Im(z) in case it is zero,
   and Re(x) is zero.
   sign_eps is 0 if Re(x) = +0, 1 if Re(x) = -0
   sign_a is the sign bit of Im(x).
   Assume y is an integer (does nothing otherwise).
*/
static void
fix_sign (mpc_ptr z, int sign_eps, int sign_a, mpfr_srcptr y)
{
  int ymod4 = -1;
  mpfr_exp_t ey;
  mpz_t my;
  unsigned long int t;

  mpz_init (my);

  ey = mpfr_get_z_exp (my, y);
  /* normalize so that my is odd */
  t = mpz_scan1 (my, 0);
  ey += (mpfr_exp_t) t;
  mpz_tdiv_q_2exp (my, my, t);
  /* y = my*2^ey */

  /* compute y mod 4 (in case y is an integer) */
  if (ey >= 2)
    ymod4 = 0;
  else if (ey == 1)
    ymod4 = mpz_tstbit (my, 0) * 2; /* correct if my < 0 */
  else if (ey == 0)
    {
      ymod4 = mpz_tstbit (my, 1) * 2 + mpz_tstbit (my, 0);
      if (mpz_cmp_ui (my , 0) < 0)
        ymod4 = 4 - ymod4;
    }
  else /* y is not an integer */
    goto end;

  if (mpfr_zero_p (mpc_realref(z)))
    {
      /* we assume y is always integer in that case (FIXME: prove it):
         (eps+I*a)^y = +0 + I*a^y for y = 1 mod 4 and sign_eps = 0
         (eps+I*a)^y = -0 - I*a^y for y = 3 mod 4 and sign_eps = 0 */
      MPC_ASSERT (ymod4 == 1 || ymod4 == 3);
      if ((ymod4 == 3 && sign_eps == 0) ||
          (ymod4 == 1 && sign_eps == 1))
        mpfr_neg (mpc_realref(z), mpc_realref(z), MPFR_RNDZ);
    }
  else if (mpfr_zero_p (mpc_imagref(z)))
    {
      /* we assume y is always integer in that case (FIXME: prove it):
         (eps+I*a)^y =  a^y - 0*I for y = 0 mod 4 and sign_a = sign_eps
         (eps+I*a)^y =  -a^y +0*I for y = 2 mod 4 and sign_a = sign_eps */
      MPC_ASSERT (ymod4 == 0 || ymod4 == 2);
      if ((ymod4 == 0 && sign_a == sign_eps) ||
          (ymod4 == 2 && sign_a != sign_eps))
        mpfr_neg (mpc_imagref(z), mpc_imagref(z), MPFR_RNDZ);
    }

 end:
  mpz_clear (my);
}
Ejemplo n.º 2
0
Archivo: pow.c Proyecto: mahdiz/mpclib
/* return non zero iff x^y is exact.
   Assumes x and y are ordinary numbers (neither NaN nor Inf),
   and y is not zero.
*/
int
mpfr_pow_is_exact (mpfr_srcptr x, mpfr_srcptr y)
{
  mp_exp_t d;
  unsigned long i, c;
  mp_limb_t *yp;
  
  if ((mpfr_sgn (x) < 0) && (mpfr_isinteger (y) == 0))
      return 0;

  if (mpfr_sgn (y) < 0)
    return mpfr_cmp_si_2exp (x, MPFR_SIGN(x), MPFR_EXP(x) - 1) == 0;

  /* compute d such that y = c*2^d with c odd integer */
  d = MPFR_EXP(y) - MPFR_PREC(y);
  /* since y is not zero, necessarily one of the mantissa limbs is not zero,
     thus we can simply loop until we find a non zero limb */
  yp = MPFR_MANT(y);
  for (i = 0; yp[i] == 0; i++, d += BITS_PER_MP_LIMB);
  /* now yp[i] is not zero */
  count_trailing_zeros (c, yp[i]);
  d += c;
  
  if (d < 0)
    {
      mpz_t a;
      mp_exp_t b;

      mpz_init (a);
      b = mpfr_get_z_exp (a, x); /* x = a * 2^b */
      c = mpz_scan1 (a, 0);
      mpz_div_2exp (a, a, c);
      b += c;
      /* now a is odd */
      while (d != 0)
        {
          if (mpz_perfect_square_p (a))
            {
              d++;
              mpz_sqrt (a, a);
            }
          else
            {
              mpz_clear (a);
              return 0;
            }
        }
      mpz_clear (a);
    }

    return 1;
}
Ejemplo n.º 3
0
void
mpfr_get_z (mpz_ptr z, mpfr_srcptr f, mp_rnd_t rnd)
{
  mpfr_t r;
  mp_exp_t exp = MPFR_EXP (f);

  /* if exp <= 0, then |f|<1, thus |o(f)|<=1 */
  MPFR_ASSERTN (exp < 0 || exp <= MPFR_PREC_MAX);
  mpfr_init2 (r, (exp < (mp_exp_t) MPFR_PREC_MIN ?
                  MPFR_PREC_MIN : (mpfr_prec_t) exp));
  mpfr_rint (r, f, rnd);
  MPFR_ASSERTN (MPFR_IS_FP (r) );
  exp = mpfr_get_z_exp (z, r);
  if (exp >= 0)
    mpz_mul_2exp (z, z, exp);
  else
    mpz_div_2exp (z, z, -exp);
  mpfr_clear (r);
}
Ejemplo n.º 4
0
/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
   using naive method with O(l) multiplications.
   Return the number of iterations l.
   The absolute error on s is less than 3*l*(l+1)*2^(-q).
   Version using fixed-point arithmetic with mpz instead
   of mpfr for internal computations.
   s must have at least qn+1 limbs (qn should be enough, but currently fails
   since mpz_mul_2exp(s, s, q-1) reallocates qn+1 limbs)
*/
static unsigned long
mpfr_exp2_aux (mpz_t s, mpfr_srcptr r, mp_prec_t q, mp_exp_t *exps)
{
  unsigned long l;
  mp_exp_t dif;
  mp_size_t qn;
  mpz_t t, rr;
  mp_exp_t expt, expr;
  TMP_DECL(marker);

  TMP_MARK(marker);
  qn = 1 + (q-1)/BITS_PER_MP_LIMB;
  expt = 0;
  *exps = 1 - (mp_exp_t) q;                   /* s = 2^(q-1) */
  MY_INIT_MPZ(t, 2*qn+1);
  MY_INIT_MPZ(rr, qn+1);
  mpz_set_ui(t, 1); 
  mpz_set_ui(s, 1); 
  mpz_mul_2exp(s, s, q-1); 
  expr = mpfr_get_z_exp(rr, r);               /* no error here */

  l = 0;
  do {
    l++;
    mpz_mul(t, t, rr); 
    expt += expr;
    dif = *exps + mpz_sizeinbase(s, 2) - expt - mpz_sizeinbase(t, 2);
    /* truncates the bits of t which are < ulp(s) = 2^(1-q) */
    expt += mpz_normalize(t, t, (mp_exp_t) q-dif); /* error at most 2^(1-q) */
    mpz_div_ui(t, t, l);                   /* error at most 2^(1-q) */
    /* the error wrt t^l/l! is here at most 3*l*ulp(s) */
    MPFR_ASSERTD (expt == *exps);
    mpz_add(s, s, t);                      /* no error here: exact */
    /* ensures rr has the same size as t: after several shifts, the error
       on rr is still at most ulp(t)=ulp(s) */
    expr += mpz_normalize(rr, rr, mpz_sizeinbase(t, 2));
  } while (mpz_cmp_ui(t, 0));

  TMP_FREE(marker);
  return l;
}
Ejemplo n.º 5
0
/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
   using naive method with O(l) multiplications.
   Return the number of iterations l.
   The absolute error on s is less than 3*l*(l+1)*2^(-q).
   Version using fixed-point arithmetic with mpz instead 
   of mpfr for internal computations.
   s must have at least qn+1 limbs (qn should be enough, but currently fails
   since mpz_mul_2exp(s, s, q-1) reallocates qn+1 limbs)
*/
static int
mpfr_exp2_aux (mpz_t s, mpfr_srcptr r, int q, int *exps)
{
  int l, dif, qn;
  mpz_t t, rr; mp_exp_t expt, expr;
  TMP_DECL(marker);

  TMP_MARK(marker);
  qn = 1 + (q-1)/BITS_PER_MP_LIMB;
  MY_INIT_MPZ(t, 2*qn+1); /* 2*qn+1 is neeeded since mpz_div_2exp may 
			      need an extra limb */
  MY_INIT_MPZ(rr, qn+1);
  mpz_set_ui(t, 1); expt=0;
  mpz_set_ui(s, 1); mpz_mul_2exp(s, s, q-1); *exps = 1-q; /* s = 2^(q-1) */
  expr = mpfr_get_z_exp(rr, r); /* no error here */

  l = 0;
  do {
    l++;
    mpz_mul(t, t, rr); expt=expt+expr;
    dif = *exps + mpz_sizeinbase(s, 2) - expt - mpz_sizeinbase(t, 2);
    /* truncates the bits of t which are < ulp(s) = 2^(1-q) */
    expt += mpz_normalize(t, t, q-dif); /* error at most 2^(1-q) */
    mpz_div_ui(t, t, l); /* error at most 2^(1-q) */
    /* the error wrt t^l/l! is here at most 3*l*ulp(s) */
#ifdef DEBUG
    if (expt != *exps) {
      fprintf(stderr, "Error: expt != exps %d %d\n", expt, *exps); exit(1);
    }
#endif
    mpz_add(s, s, t); /* no error here: exact */
    /* ensures rr has the same size as t: after several shifts, the error
       on rr is still at most ulp(t)=ulp(s) */
    expr += mpz_normalize(rr, rr, mpz_sizeinbase(t, 2));
  } while (mpz_cmp_ui(t, 0));

  TMP_FREE(marker);
  return l;
}
Ejemplo n.º 6
0
Archivo: pow.c Proyecto: tomi500/MPC
/* If x^y is exactly representable (with maybe a larger precision than z),
   round it in z and return the (mpc) inexact flag in [0, 10].

   If x^y is not exactly representable, return -1.

   If intermediate computations lead to numbers of more than maxprec bits,
   then abort and return -2 (in that case, to avoid loops, mpc_pow_exact
   should be called again with a larger value of maxprec).

   Assume one of Re(x) or Im(x) is non-zero, and y is non-zero (y is real).

   Warning: z and x might be the same variable, same for Re(z) or Im(z) and y.

   In case -1 or -2 is returned, z is not modified.
*/
static int
mpc_pow_exact (mpc_ptr z, mpc_srcptr x, mpfr_srcptr y, mpc_rnd_t rnd,
               mpfr_prec_t maxprec)
{
  mpfr_exp_t ec, ed, ey;
  mpz_t my, a, b, c, d, u;
  unsigned long int t;
  int ret = -2;
  int sign_rex = mpfr_signbit (mpc_realref(x));
  int sign_imx = mpfr_signbit (mpc_imagref(x));
  int x_imag = mpfr_zero_p (mpc_realref(x));
  int z_is_y = 0;
  mpfr_t copy_of_y;

  if (mpc_realref (z) == y || mpc_imagref (z) == y)
    {
      z_is_y = 1;
      mpfr_init2 (copy_of_y, mpfr_get_prec (y));
      mpfr_set (copy_of_y, y, MPFR_RNDN);
    }

  mpz_init (my);
  mpz_init (a);
  mpz_init (b);
  mpz_init (c);
  mpz_init (d);
  mpz_init (u);

  ey = mpfr_get_z_exp (my, y);
  /* normalize so that my is odd */
  t = mpz_scan1 (my, 0);
  ey += (mpfr_exp_t) t;
  mpz_tdiv_q_2exp (my, my, t);
  /* y = my*2^ey with my odd */

  if (x_imag)
    {
      mpz_set_ui (c, 0);
      ec = 0;
    }
  else
    ec = mpfr_get_z_exp (c, mpc_realref(x));
  if (mpfr_zero_p (mpc_imagref(x)))
    {
      mpz_set_ui (d, 0);
      ed = ec;
    }
  else
    {
      ed = mpfr_get_z_exp (d, mpc_imagref(x));
      if (x_imag)
        ec = ed;
    }
  /* x = c*2^ec + I * d*2^ed */
  /* equalize the exponents of x */
  if (ec < ed)
    {
      mpz_mul_2exp (d, d, (unsigned long int) (ed - ec));
      if ((mpfr_prec_t) mpz_sizeinbase (d, 2) > maxprec)
        goto end;
    }
  else if (ed < ec)
    {
      mpz_mul_2exp (c, c, (unsigned long int) (ec - ed));
      if ((mpfr_prec_t) mpz_sizeinbase (c, 2) > maxprec)
        goto end;
      ec = ed;
    }
  /* now ec=ed and x = (c + I * d) * 2^ec */

  /* divide by two if possible */
  if (mpz_cmp_ui (c, 0) == 0)
    {
      t = mpz_scan1 (d, 0);
      mpz_tdiv_q_2exp (d, d, t);
      ec += (mpfr_exp_t) t;
    }
  else if (mpz_cmp_ui (d, 0) == 0)
    {
      t = mpz_scan1 (c, 0);
      mpz_tdiv_q_2exp (c, c, t);
      ec += (mpfr_exp_t) t;
    }
  else /* neither c nor d is zero */
    {
      unsigned long v;
      t = mpz_scan1 (c, 0);
      v = mpz_scan1 (d, 0);
      if (v < t)
        t = v;
      mpz_tdiv_q_2exp (c, c, t);
      mpz_tdiv_q_2exp (d, d, t);
      ec += (mpfr_exp_t) t;
    }

  /* now either one of c, d is odd */

  while (ey < 0)
    {
      /* check if x is a square */
      if (ec & 1)
        {
          mpz_mul_2exp (c, c, 1);
          mpz_mul_2exp (d, d, 1);
          ec --;
        }
      /* now ec is even */
      if (mpc_perfect_square_p (a, b, c, d) == 0)
        break;
      mpz_swap (a, c);
      mpz_swap (b, d);
      ec /= 2;
      ey ++;
    }

  if (ey < 0)
    {
      ret = -1; /* not representable */
      goto end;
    }

  /* Now ey >= 0, it thus suffices to check that x^my is representable.
     If my > 0, this is always true. If my < 0, we first try to invert
     (c+I*d)*2^ec.
  */
  if (mpz_cmp_ui (my, 0) < 0)
    {
      /* If my < 0, 1 / (c + I*d) = (c - I*d)/(c^2 + d^2), thus a sufficient
         condition is that c^2 + d^2 is a power of two, assuming |c| <> |d|.
         Assume a prime p <> 2 divides c^2 + d^2,
         then if p does not divide c or d, 1 / (c + I*d) cannot be exact.
         If p divides both c and d, then we can write c = p*c', d = p*d',
         and 1 / (c + I*d) = 1/p * 1/(c' + I*d'). This shows that if 1/(c+I*d)
         is exact, then 1/(c' + I*d') is exact too, and we are back to the
         previous case. In conclusion, a necessary and sufficient condition
         is that c^2 + d^2 is a power of two.
      */
      /* FIXME: we could first compute c^2+d^2 mod a limb for example */
      mpz_mul (a, c, c);
      mpz_addmul (a, d, d);
      t = mpz_scan1 (a, 0);
      if (mpz_sizeinbase (a, 2) != 1 + t) /* a is not a power of two */
        {
          ret = -1; /* not representable */
          goto end;
        }
      /* replace (c,d) by (c/(c^2+d^2), -d/(c^2+d^2)) */
      mpz_neg (d, d);
      ec = -ec - (mpfr_exp_t) t;
      mpz_neg (my, my);
    }

  /* now ey >= 0 and my >= 0, and we want to compute
     [(c + I * d) * 2^ec] ^ (my * 2^ey).

     We first compute [(c + I * d) * 2^ec]^my, then square ey times. */
  t = mpz_sizeinbase (my, 2) - 1;
  mpz_set (a, c);
  mpz_set (b, d);
  ed = ec;
  /* invariant: (a + I*b) * 2^ed = ((c + I*d) * 2^ec)^trunc(my/2^t) */
  while (t-- > 0)
    {
      unsigned long int v, w;
      /* square a + I*b */
      mpz_mul (u, a, b);
      mpz_mul (a, a, a);
      mpz_submul (a, b, b);
      mpz_mul_2exp (b, u, 1);
      ed *= 2;
      if (mpz_tstbit (my, t)) /* multiply by c + I*d */
        {
          mpz_mul (u, a, c);
          mpz_submul (u, b, d); /* ac-bd */
          mpz_mul (b, b, c);
          mpz_addmul (b, a, d); /* bc+ad */
          mpz_swap (a, u);
          ed += ec;
        }
      /* remove powers of two in (a,b) */
      if (mpz_cmp_ui (a, 0) == 0)
        {
          w = mpz_scan1 (b, 0);
          mpz_tdiv_q_2exp (b, b, w);
          ed += (mpfr_exp_t) w;
        }
      else if (mpz_cmp_ui (b, 0) == 0)
        {
          w = mpz_scan1 (a, 0);
          mpz_tdiv_q_2exp (a, a, w);
          ed += (mpfr_exp_t) w;
        }
      else
        {
          w = mpz_scan1 (a, 0);
          v = mpz_scan1 (b, 0);
          if (v < w)
            w = v;
          mpz_tdiv_q_2exp (a, a, w);
          mpz_tdiv_q_2exp (b, b, w);
          ed += (mpfr_exp_t) w;
        }
      if (   (mpfr_prec_t) mpz_sizeinbase (a, 2) > maxprec
          || (mpfr_prec_t) mpz_sizeinbase (b, 2) > maxprec)
        goto end;
    }
  /* now a+I*b = (c+I*d)^my */

  while (ey-- > 0)
    {
      unsigned long sa, sb;

      /* square a + I*b */
      mpz_mul (u, a, b);
      mpz_mul (a, a, a);
      mpz_submul (a, b, b);
      mpz_mul_2exp (b, u, 1);
      ed *= 2;

      /* divide by largest 2^n possible, to avoid many loops for e.g.,
         (2+2*I)^16777216 */
      sa = mpz_scan1 (a, 0);
      sb = mpz_scan1 (b, 0);
      sa = (sa <= sb) ? sa : sb;
      mpz_tdiv_q_2exp (a, a, sa);
      mpz_tdiv_q_2exp (b, b, sa);
      ed += (mpfr_exp_t) sa;

      if (   (mpfr_prec_t) mpz_sizeinbase (a, 2) > maxprec
          || (mpfr_prec_t) mpz_sizeinbase (b, 2) > maxprec)
        goto end;
    }

  ret = mpfr_set_z (mpc_realref(z), a, MPC_RND_RE(rnd));
  ret = MPC_INEX(ret, mpfr_set_z (mpc_imagref(z), b, MPC_RND_IM(rnd)));
  mpfr_mul_2si (mpc_realref(z), mpc_realref(z), ed, MPC_RND_RE(rnd));
  mpfr_mul_2si (mpc_imagref(z), mpc_imagref(z), ed, MPC_RND_IM(rnd));

 end:
  mpz_clear (my);
  mpz_clear (a);
  mpz_clear (b);
  mpz_clear (c);
  mpz_clear (d);
  mpz_clear (u);

  if (ret >= 0 && x_imag)
    fix_sign (z, sign_rex, sign_imx, (z_is_y) ? copy_of_y : y);

  if (z_is_y)
    mpfr_clear (copy_of_y);

  return ret;
}
Ejemplo n.º 7
0
/* use Brent's formula exp(x) = (1+r+r^2/2!+r^3/3!+...)^(2^K)*2^n
   where x = n*log(2)+(2^K)*r
   together with Brent-Kung O(t^(1/2)) algorithm for the evaluation of
   power series. The resulting complexity is O(n^(1/3)*M(n)).
*/
int
mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
{
  long n;
  unsigned long K, k, l, err; /* FIXME: Which type ? */
  int error_r;
  mp_exp_t exps;
  mp_prec_t q, precy;
  int inexact;
  mpfr_t r, s, t;
  mpz_t ss;
  TMP_DECL(marker);

  precy = MPFR_PREC(y);
  
  MPFR_TRACE ( printf("Py=%d Px=%d", MPFR_PREC(y), MPFR_PREC(x)) );
  MPFR_TRACE ( MPFR_DUMP (x) );

  n = (long) (mpfr_get_d1 (x) / LOG2);

  /* error bounds the cancelled bits in x - n*log(2) */
  if (MPFR_UNLIKELY(n == 0))
    error_r = 0;
  else
    count_leading_zeros (error_r, (mp_limb_t) (n < 0) ? -n : n);
  error_r = BITS_PER_MP_LIMB - error_r + 2;

  /* for the O(n^(1/2)*M(n)) method, the Taylor series computation of
     n/K terms costs about n/(2K) multiplications when computed in fixed
     point */
  K = (precy < SWITCH) ? __gmpfr_isqrt ((precy + 1) / 2)
    : __gmpfr_cuberoot (4*precy);
  l = (precy - 1) / K + 1;
  err = K + MPFR_INT_CEIL_LOG2 (2 * l + 18);
  /* add K extra bits, i.e. failure probability <= 1/2^K = O(1/precy) */
  q = precy + err + K + 5;
  
  /*q = ( (q-1)/BITS_PER_MP_LIMB + 1) * BITS_PER_MP_LIMB; */

  mpfr_init2 (r, q + error_r);
  mpfr_init2 (s, q + error_r);
  mpfr_init2 (t, q);

  /* the algorithm consists in computing an upper bound of exp(x) using
     a precision of q bits, and see if we can round to MPFR_PREC(y) taking
     into account the maximal error. Otherwise we increase q. */
  for (;;)
    {
      MPFR_TRACE ( printf("n=%d K=%d l=%d q=%d\n",n,K,l,q) );
      
      /* if n<0, we have to get an upper bound of log(2)
	 in order to get an upper bound of r = x-n*log(2) */
      mpfr_const_log2 (s, (n >= 0) ? GMP_RNDZ : GMP_RNDU);
      /* s is within 1 ulp of log(2) */
      
      mpfr_mul_ui (r, s, (n < 0) ? -n : n, (n >= 0) ? GMP_RNDZ : GMP_RNDU);
      /* r is within 3 ulps of n*log(2) */
      if (n < 0)
	mpfr_neg (r, r, GMP_RNDD); /* exact */
      /* r = floor(n*log(2)), within 3 ulps */
      
      MPFR_TRACE ( MPFR_DUMP (x) );
      MPFR_TRACE ( MPFR_DUMP (r) );
      
      mpfr_sub (r, x, r, GMP_RNDU);
      /* possible cancellation here: the error on r is at most
	 3*2^(EXP(old_r)-EXP(new_r)) */
      while (MPFR_IS_NEG (r))
	{ /* initial approximation n was too large */
	  n--;
	  mpfr_add (r, r, s, GMP_RNDU);
	}
      mpfr_prec_round (r, q, GMP_RNDU);
      MPFR_TRACE ( MPFR_DUMP (r) );
      MPFR_ASSERTD (MPFR_IS_POS (r));
      mpfr_div_2ui (r, r, K, GMP_RNDU); /* r = (x-n*log(2))/2^K, exact */
      
      TMP_MARK(marker);
      MY_INIT_MPZ(ss, 3 + 2*((q-1)/BITS_PER_MP_LIMB));
      exps = mpfr_get_z_exp (ss, s);
      /* s <- 1 + r/1! + r^2/2! + ... + r^l/l! */
      l = (precy < SWITCH) ? 
	mpfr_exp2_aux (ss, r, q, &exps)      /* naive method */
	: mpfr_exp2_aux2 (ss, r, q, &exps);  /* Brent/Kung method */
      
      MPFR_TRACE(printf("l=%d q=%d (K+l)*q^2=%1.3e\n", l, q, (K+l)*(double)q*q));
      
      for (k = 0; k < K; k++)
	{
	  mpz_mul (ss, ss, ss);
	  exps <<= 1;
	  exps += mpz_normalize (ss, ss, q);
	}
      mpfr_set_z (s, ss, GMP_RNDN);
      
      MPFR_SET_EXP(s, MPFR_GET_EXP (s) + exps);
      TMP_FREE(marker); /* don't need ss anymore */
      
      if (n>0) 
	mpfr_mul_2ui(s, s, n, GMP_RNDU);
      else 
	mpfr_div_2ui(s, s, -n, GMP_RNDU);
      
      /* error is at most 2^K*(3l*(l+1)) ulp for mpfr_exp2_aux */
      l = (precy < SWITCH) ? 3*l*(l+1) : l*(l+4) ;
      k = MPFR_INT_CEIL_LOG2 (l);
      /* k = 0; while (l) { k++; l >>= 1; } */

      /* now k = ceil(log(error in ulps)/log(2)) */
      K += k;

      MPFR_TRACE ( printf("after mult. by 2^n:\n") );
      MPFR_TRACE ( MPFR_DUMP (s) );
      MPFR_TRACE ( printf("err=%d bits\n", K) );
      
      if (mpfr_can_round (s, q - K, GMP_RNDN, GMP_RNDZ,
			  precy + (rnd_mode == GMP_RNDN)) )
	break;
      MPFR_TRACE (printf("prec++, use %d\n", q+BITS_PER_MP_LIMB) );
      MPFR_TRACE (printf("q=%d q-K=%d precy=%d\n",q,q-K,precy) );
      q += BITS_PER_MP_LIMB;
      mpfr_set_prec (r, q);
      mpfr_set_prec (s, q);
      mpfr_set_prec (t, q);
    }
  
  inexact = mpfr_set (y, s, rnd_mode);

  mpfr_clear (r); 
  mpfr_clear (s); 
  mpfr_clear (t);

  return inexact;
}
Ejemplo n.º 8
0
/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
   using Brent/Kung method with O(sqrt(l)) multiplications.
   Return l.
   Uses m multiplications of full size and 2l/m of decreasing size,
   i.e. a total equivalent to about m+l/m full multiplications,
   i.e. 2*sqrt(l) for m=sqrt(l).
   Version using mpz. ss must have at least (sizer+1) limbs.
   The error is bounded by (l^2+4*l) ulps where l is the return value.
*/
static unsigned long
mpfr_exp2_aux2 (mpz_t s, mpfr_srcptr r, mp_prec_t q, mp_exp_t *exps)
{
  mp_exp_t expr, *expR, expt;
  mp_size_t sizer;
  mp_prec_t ql;
  unsigned long l, m, i;
  mpz_t t, *R, rr, tmp;
  TMP_DECL(marker);

  /* estimate value of l */
  MPFR_ASSERTD (MPFR_GET_EXP (r) < 0);
  l = q / (- MPFR_GET_EXP (r));
  m = __gmpfr_isqrt (l);
  /* we access R[2], thus we need m >= 2 */
  if (m < 2)
    m = 2;

  TMP_MARK(marker);
  R = (mpz_t*) TMP_ALLOC((m+1)*sizeof(mpz_t));          /* R[i] is r^i */
  expR = (mp_exp_t*) TMP_ALLOC((m+1)*sizeof(mp_exp_t)); /* exponent for R[i] */
  sizer = 1 + (MPFR_PREC(r)-1)/BITS_PER_MP_LIMB;
  mpz_init(tmp);
  MY_INIT_MPZ(rr, sizer+2);
  MY_INIT_MPZ(t, 2*sizer);            /* double size for products */
  mpz_set_ui(s, 0); 
  *exps = 1-q;                        /* 1 ulp = 2^(1-q) */
  for (i = 0 ; i <= m ; i++)
    MY_INIT_MPZ(R[i], sizer+2);
  expR[1] = mpfr_get_z_exp(R[1], r); /* exact operation: no error */
  expR[1] = mpz_normalize2(R[1], R[1], expR[1], 1-q); /* error <= 1 ulp */
  mpz_mul(t, R[1], R[1]); /* err(t) <= 2 ulps */
  mpz_div_2exp(R[2], t, q-1); /* err(R[2]) <= 3 ulps */
  expR[2] = 1-q;
  for (i = 3 ; i <= m ; i++)
    {
      mpz_mul(t, R[i-1], R[1]); /* err(t) <= 2*i-2 */
      mpz_div_2exp(R[i], t, q-1); /* err(R[i]) <= 2*i-1 ulps */
      expR[i] = 1-q;
    }
  mpz_set_ui (R[0], 1);
  mpz_mul_2exp (R[0], R[0], q-1);
  expR[0] = 1-q; /* R[0]=1 */
  mpz_set_ui (rr, 1);
  expr = 0; /* rr contains r^l/l! */
  /* by induction: err(rr) <= 2*l ulps */

  l = 0;
  ql = q; /* precision used for current giant step */
  do
    {
      /* all R[i] must have exponent 1-ql */
      if (l != 0)
        for (i = 0 ; i < m ; i++)
	  expR[i] = mpz_normalize2 (R[i], R[i], expR[i], 1-ql);
      /* the absolute error on R[i]*rr is still 2*i-1 ulps */
      expt = mpz_normalize2 (t, R[m-1], expR[m-1], 1-ql);
      /* err(t) <= 2*m-1 ulps */
      /* computes t = 1 + r/(l+1) + ... + r^(m-1)*l!/(l+m-1)!
         using Horner's scheme */
      for (i = m-1 ; i-- != 0 ; )
        {
          mpz_div_ui(t, t, l+i+1); /* err(t) += 1 ulp */
          mpz_add(t, t, R[i]);
        }
      /* now err(t) <= (3m-2) ulps */

      /* now multiplies t by r^l/l! and adds to s */
      mpz_mul(t, t, rr);
      expt += expr;
      expt = mpz_normalize2(t, t, expt, *exps);
      /* err(t) <= (3m-1) + err_rr(l) <= (3m-2) + 2*l */
      MPFR_ASSERTD (expt == *exps);
      mpz_add(s, s, t); /* no error here */

      /* updates rr, the multiplication of the factors l+i could be done
         using binary splitting too, but it is not sure it would save much */
      mpz_mul(t, rr, R[m]); /* err(t) <= err(rr) + 2m-1 */
      expr += expR[m];
      mpz_set_ui (tmp, 1);
      for (i = 1 ; i <= m ; i++)
	mpz_mul_ui (tmp, tmp, l + i);
      mpz_fdiv_q(t, t, tmp); /* err(t) <= err(rr) + 2m */
      expr += mpz_normalize(rr, t, ql); /* err_rr(l+1) <= err_rr(l) + 2m+1 */
      ql = q - *exps - mpz_sizeinbase(s, 2) + expr + mpz_sizeinbase(rr, 2);
      l += m;
    }
  while ((size_t) expr+mpz_sizeinbase(rr, 2) > (size_t)((int)-q));

  TMP_FREE(marker);
  mpz_clear(tmp);
  return l;
}
Ejemplo n.º 9
0
/* compute in y an approximation of sum(x^k/k/k!, k=1..infinity),
   and return e such that the absolute error is bound by 2^e ulp(y) */
static mp_exp_t
mpfr_eint_aux (mpfr_t y, mpfr_srcptr x)
{
  mpfr_t eps; /* dynamic (absolute) error bound on t */
  mpfr_t erru, errs;
  mpz_t m, s, t, u;
  mp_exp_t e, sizeinbase;
  mp_prec_t w = MPFR_PREC(y);
  unsigned long k;
  MPFR_GROUP_DECL (group);

  /* for |x| <= 1, we have S := sum(x^k/k/k!, k=1..infinity) = x + R(x)
     where |R(x)| <= (x/2)^2/(1-x/2) <= 2*(x/2)^2
     thus |R(x)/x| <= |x|/2
     thus if |x| <= 2^(-PREC(y)) we have |S - o(x)| <= ulp(y) */

  if (MPFR_GET_EXP(x) <= - (mp_exp_t) w)
    {
      mpfr_set (y, x, GMP_RNDN);
      return 0;
    }

  mpz_init (s); /* initializes to 0 */
  mpz_init (t);
  mpz_init (u);
  mpz_init (m);
  MPFR_GROUP_INIT_3 (group, 31, eps, erru, errs);
  e = mpfr_get_z_exp (m, x); /* x = m * 2^e */
  MPFR_ASSERTD (mpz_sizeinbase (m, 2) == MPFR_PREC (x));
  if (MPFR_PREC (x) > w)
    {
      e += MPFR_PREC (x) - w;
      mpz_tdiv_q_2exp (m, m, MPFR_PREC (x) - w);
    }
  /* remove trailing zeroes from m: this will speed up much cases where
     x is a small integer divided by a power of 2 */
  k = mpz_scan1 (m, 0);
  mpz_tdiv_q_2exp (m, m, k);
  e += k;
  /* initialize t to 2^w */
  mpz_set_ui (t, 1);
  mpz_mul_2exp (t, t, w);
  mpfr_set_ui (eps, 0, GMP_RNDN); /* eps[0] = 0 */
  mpfr_set_ui (errs, 0, GMP_RNDN);
  for (k = 1;; k++)
    {
      /* let eps[k] be the absolute error on t[k]:
         since t[k] = trunc(t[k-1]*m*2^e/k), we have
         eps[k+1] <= 1 + eps[k-1]*m*2^e/k + t[k-1]*m*2^(1-w)*2^e/k
                  =  1 + (eps[k-1] + t[k-1]*2^(1-w))*m*2^e/k
                  = 1 + (eps[k-1]*2^(w-1) + t[k-1])*2^(1-w)*m*2^e/k */
      mpfr_mul_2ui (eps, eps, w - 1, GMP_RNDU);
      mpfr_add_z (eps, eps, t, GMP_RNDU);
      MPFR_MPZ_SIZEINBASE2 (sizeinbase, m);
      mpfr_mul_2si (eps, eps, sizeinbase - (w - 1) + e, GMP_RNDU);
      mpfr_div_ui (eps, eps, k, GMP_RNDU);
      mpfr_add_ui (eps, eps, 1, GMP_RNDU);
      mpz_mul (t, t, m);
      if (e < 0)
        mpz_tdiv_q_2exp (t, t, -e);
      else
        mpz_mul_2exp (t, t, e);
      mpz_tdiv_q_ui (t, t, k);
      mpz_tdiv_q_ui (u, t, k);
      mpz_add (s, s, u);
      /* the absolute error on u is <= 1 + eps[k]/k */
      mpfr_div_ui (erru, eps, k, GMP_RNDU);
      mpfr_add_ui (erru, erru, 1, GMP_RNDU);
      /* and that on s is the sum of all errors on u */
      mpfr_add (errs, errs, erru, GMP_RNDU);
      /* we are done when t is smaller than errs */
      if (mpz_sgn (t) == 0)
        sizeinbase = 0;
      else
        MPFR_MPZ_SIZEINBASE2 (sizeinbase, t);
      if (sizeinbase < MPFR_GET_EXP (errs))
        break;
    }
  /* the truncation error is bounded by (|t|+eps)/k*(|x|/k + |x|^2/k^2 + ...)
     <= (|t|+eps)/k*|x|/(k-|x|) */
  mpz_abs (t, t);
  mpfr_add_z (eps, eps, t, GMP_RNDU);
  mpfr_div_ui (eps, eps, k, GMP_RNDU);
  mpfr_abs (erru, x, GMP_RNDU); /* |x| */
  mpfr_mul (eps, eps, erru, GMP_RNDU);
  mpfr_ui_sub (erru, k, erru, GMP_RNDD);
  if (MPFR_IS_NEG (erru))
    {
      /* the truncated series does not converge, return fail */
      e = w;
    }
  else
    {
      mpfr_div (eps, eps, erru, GMP_RNDU);
      mpfr_add (errs, errs, eps, GMP_RNDU);
      mpfr_set_z (y, s, GMP_RNDN);
      mpfr_div_2ui (y, y, w, GMP_RNDN);
      /* errs was an absolute error bound on s. We must convert it to an error
         in terms of ulp(y). Since ulp(y) = 2^(EXP(y)-PREC(y)), we must
         divide the error by 2^(EXP(y)-PREC(y)), but since we divided also
         y by 2^w = 2^PREC(y), we must simply divide by 2^EXP(y). */
      e = MPFR_GET_EXP (errs) - MPFR_GET_EXP (y);
    }
  MPFR_GROUP_CLEAR (group);
  mpz_clear (s);
  mpz_clear (t);
  mpz_clear (u);
  mpz_clear (m);
  return e;
}
Ejemplo n.º 10
0
int
mpfr_cbrt (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
{
  mpz_t m;
  mp_exp_t e, r, sh;
  mp_prec_t n, size_m, tmp;
  int inexact, negative;
  MPFR_SAVE_EXPO_DECL (expo);

  /* special values */
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN (x))
        {
          MPFR_SET_NAN (y);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF (x))
        {
          MPFR_SET_INF (y);
          MPFR_SET_SAME_SIGN (y, x);
          MPFR_RET (0);
        }
      /* case 0: cbrt(+/- 0) = +/- 0 */
      else /* x is necessarily 0 */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          MPFR_SET_ZERO (y);
          MPFR_SET_SAME_SIGN (y, x);
          MPFR_RET (0);
        }
    }

  /* General case */
  MPFR_SAVE_EXPO_MARK (expo);
  mpz_init (m);

  e = mpfr_get_z_exp (m, x);                /* x = m * 2^e */
  if ((negative = MPFR_IS_NEG(x)))
    mpz_neg (m, m);
  r = e % 3;
  if (r < 0)
    r += 3;
  /* x = (m*2^r) * 2^(e-r) = (m*2^r) * 2^(3*q) */

  MPFR_MPZ_SIZEINBASE2 (size_m, m);
  n = MPFR_PREC (y) + (rnd_mode == GMP_RNDN);

  /* we want 3*n-2 <= size_m + 3*sh + r <= 3*n
     i.e. 3*sh + size_m + r <= 3*n */
  sh = (3 * (mp_exp_t) n - (mp_exp_t) size_m - r) / 3;
  sh = 3 * sh + r;
  if (sh >= 0)
    {
      mpz_mul_2exp (m, m, sh);
      e = e - sh;
    }
  else if (r > 0)
    {
      mpz_mul_2exp (m, m, r);
      e = e - r;
    }

  /* invariant: x = m*2^e, with e divisible by 3 */

  /* we reuse the variable m to store the cube root, since it is not needed
     any more: we just need to know if the root is exact */
  inexact = mpz_root (m, m, 3) == 0;

  MPFR_MPZ_SIZEINBASE2 (tmp, m);
  sh = tmp - n;
  if (sh > 0) /* we have to flush to 0 the last sh bits from m */
    {
      inexact = inexact || ((mp_exp_t) mpz_scan1 (m, 0) < sh);
      mpz_div_2exp (m, m, sh);
      e += 3 * sh;
    }

  if (inexact)
    {
      if (negative)
        rnd_mode = MPFR_INVERT_RND (rnd_mode);
      if (rnd_mode == GMP_RNDU
          || (rnd_mode == GMP_RNDN && mpz_tstbit (m, 0)))
        inexact = 1, mpz_add_ui (m, m, 1);
      else
        inexact = -1;
    }

  /* either inexact is not zero, and the conversion is exact, i.e. inexact
     is not changed; or inexact=0, and inexact is set only when
     rnd_mode=GMP_RNDN and bit (n+1) from m is 1 */
  inexact += mpfr_set_z (y, m, GMP_RNDN);
  MPFR_SET_EXP (y, MPFR_GET_EXP (y) + e / 3);

  if (negative)
    {
      MPFR_CHANGE_SIGN (y);
      inexact = -inexact;
    }

  mpz_clear (m);
  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (y, inexact, rnd_mode);
}
Ejemplo n.º 11
0
Archivo: rem1.c Proyecto: sriramnrn/gcc
static int
mpfr_rem1 (mpfr_ptr rem, long *quo, mp_rnd_t rnd_q,
           mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd)
{
  mp_exp_t ex, ey;
  int compare, inex, q_is_odd, sign, signx = MPFR_SIGN (x);
  mpz_t mx, my, r;

  MPFR_ASSERTD (rnd_q == GMP_RNDN || rnd_q == GMP_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_exp (mx, x);  /* x = mx*2^ex */
  ey = mpfr_get_z_exp (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_div_2exp (my, my, k);
  }

  if (ex <= ey)
    {
      /* q = x/y = mx/(my*2^(ey-ex)) */
      mpz_mul_2exp (my, my, ey - ex);   /* divide mx by my*2^(ey-ex) */
      if (rnd_q == GMP_RNDZ)
        /* 0 <= |r| <= |my|, r has the same sign as mx */
        mpz_tdiv_qr (mx, r, mx, my);
      else
        /* 0 <= |r| <= |my|, r has the same sign as my */
        mpz_fdiv_qr (mx, r, mx, my);

      if (rnd_q == GMP_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)
        /* 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
        /* 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_div_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                      /* now 0 <= r < 2Y */
        {
          mpz_div_2exp (my, my, 1);     /* back to Y */
          if (rnd_q == GMP_RNDN)
            {
              /* 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, GMP_RNDN);
  else
    {
      if (rnd_q == GMP_RNDN)
        {
          /* FIXME: the comparison 2*r < my could be done more efficiently
             at the mpn level */
          mpz_mul_2exp (r, r, 1);
          compare = mpz_cmpabs (r, my);
          mpz_div_2exp (r, r, 1);
          compare = ((compare > 0) ||
                     ((rnd_q == GMP_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 == GMP_RNDN))
                *quo += 1;
            }
        }
      inex = mpfr_set_z (rem, r, rnd);
      /* if ex > ey, rem should be multiplied by 2^ey, else by 2^ex */
      MPFR_EXP (rem) += (ex > ey) ? ey : ex;
    }

  if (quo)
    *quo *= sign;

  /* take into account sign of x */
  if (signx < 0)
    {
      mpfr_neg (rem, rem, GMP_RNDN);
      inex = -inex;
    }

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

  return inex;
}
Ejemplo n.º 12
0
/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
   using Brent/Kung method with O(sqrt(l)) multiplications.
   Return l.
   Uses m multiplications of full size and 2l/m of decreasing size, 
   i.e. a total equivalent to about m+l/m full multiplications,
   i.e. 2*sqrt(l) for m=sqrt(l).
   Version using mpz. ss must have at least (sizer+1) limbs.
   The error is bounded by (l^2+4*l) ulps where l is the return value.
*/
static int
mpfr_exp2_aux2 (mpz_t s, mpfr_srcptr r, int q, int *exps)
{
  int expr, l, m, i, sizer, *expR, expt, ql;
  unsigned long int c;
  mpz_t t, *R, rr, tmp;
  TMP_DECL(marker);

  /* estimate value of l */
  l = q / (-MPFR_EXP(r));
  m = (int) _mpfr_isqrt (l);
  /* we access R[2], thus we need m >= 2 */
  if (m < 2) m = 2;
  TMP_MARK(marker);
  R = (mpz_t*) TMP_ALLOC((m+1)*sizeof(mpz_t)); /* R[i] stands for r^i */
  expR = (int*) TMP_ALLOC((m+1)*sizeof(int)); /* exponent for R[i] */
  sizer = 1 + (MPFR_PREC(r)-1)/BITS_PER_MP_LIMB;
  mpz_init(tmp);
  MY_INIT_MPZ(rr, sizer+2);
  MY_INIT_MPZ(t, 2*sizer); /* double size for products */
  mpz_set_ui(s, 0); *exps = 1-q; /* initialize s to zero, 1 ulp = 2^(1-q) */
  for (i=0;i<=m;i++) MY_INIT_MPZ(R[i], sizer+2);
  expR[1] = mpfr_get_z_exp(R[1], r); /* exact operation: no error */
  expR[1] = mpz_normalize2(R[1], R[1], expR[1], 1-q); /* error <= 1 ulp */
  mpz_mul(t, R[1], R[1]); /* err(t) <= 2 ulps */
  mpz_div_2exp(R[2], t, q-1); /* err(R[2]) <= 3 ulps */
  expR[2] = 1-q;
  for (i=3;i<=m;i++) {
    mpz_mul(t, R[i-1], R[1]); /* err(t) <= 2*i-2 */
    mpz_div_2exp(R[i], t, q-1); /* err(R[i]) <= 2*i-1 ulps */
    expR[i] = 1-q;
  }
  mpz_set_ui(R[0], 1); mpz_mul_2exp(R[0], R[0], q-1); expR[0]=1-q; /* R[0]=1 */
  mpz_set_ui(rr, 1); expr=0; /* rr contains r^l/l! */
  /* by induction: err(rr) <= 2*l ulps */

  l = 0;
  ql = q; /* precision used for current giant step */
  do {
    /* all R[i] must have exponent 1-ql */
    if (l) for (i=0;i<m;i++) {
      expR[i] = mpz_normalize2(R[i], R[i], expR[i], 1-ql);
    }
    /* the absolute error on R[i]*rr is still 2*i-1 ulps */
    expt = mpz_normalize2(t, R[m-1], expR[m-1], 1-ql); 
    /* err(t) <= 2*m-1 ulps */
    /* computes t = 1 + r/(l+1) + ... + r^(m-1)*l!/(l+m-1)! 
       using Horner's scheme */
    for (i=m-2;i>=0;i--) {
      mpz_div_ui(t, t, l+i+1); /* err(t) += 1 ulp */
      mpz_add(t, t, R[i]);
    }
    /* now err(t) <= (3m-2) ulps */
    
    /* now multiplies t by r^l/l! and adds to s */
    mpz_mul(t, t, rr); expt += expr;
    expt = mpz_normalize2(t, t, expt, *exps);
    /* err(t) <= (3m-1) + err_rr(l) <= (3m-2) + 2*l */
#ifdef DEBUG
    if (expt != *exps) {
      fprintf(stderr, "Error: expt != exps %d %d\n", expt, *exps); exit(1);
    }
#endif
    mpz_add(s, s, t); /* no error here */

    /* updates rr, the multiplication of the factors l+i could be done 
       using binary splitting too, but it is not sure it would save much */
    mpz_mul(t, rr, R[m]); /* err(t) <= err(rr) + 2m-1 */
    expr += expR[m];
    mpz_set_ui (tmp, 1);
    for (i=1, c=1; i<=m; i++) {
      if (l+i > ~((unsigned long int) 0)/c) {
	mpz_mul_ui(tmp, tmp, c);
	c = l+i;
      }
      else c *= (unsigned long int) l+i;
    }
    if (c != 1) mpz_mul_ui (tmp, tmp, c); /* tmp is exact */
    mpz_fdiv_q(t, t, tmp); /* err(t) <= err(rr) + 2m */
    expr += mpz_normalize(rr, t, ql); /* err_rr(l+1) <= err_rr(l) + 2m+1 */
    ql = q - *exps - mpz_sizeinbase(s, 2) + expr + mpz_sizeinbase(rr, 2);
    l+=m;
  } while (expr+mpz_sizeinbase(rr, 2) > -q);

  TMP_FREE(marker);
  mpz_clear(tmp);
  return l;
}
Ejemplo n.º 13
0
/* use Brent's formula exp(x) = (1+r+r^2/2!+r^3/3!+...)^(2^K)*2^n
   where x = n*log(2)+(2^K)*r
   together with Brent-Kung O(t^(1/2)) algorithm for the evaluation of
   power series. The resulting complexity is O(n^(1/3)*M(n)).
*/
int 
mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) 
{
  int n, K, precy, q, k, l, err, exps, inexact;
  mpfr_t r, s, t; mpz_t ss;
  TMP_DECL(marker);

  precy = MPFR_PREC(y);

  n = (int) (mpfr_get_d1 (x) / LOG2);

  /* for the O(n^(1/2)*M(n)) method, the Taylor series computation of
     n/K terms costs about n/(2K) multiplications when computed in fixed
     point */
  K = (precy<SWITCH) ? _mpfr_isqrt((precy + 1) / 2) : _mpfr_cuberoot (4*precy);
  l = (precy-1)/K + 1;
  err = K + (int) _mpfr_ceil_log2 (2.0 * (double) l + 18.0);
  /* add K extra bits, i.e. failure probability <= 1/2^K = O(1/precy) */
  q = precy + err + K + 3;
  mpfr_init2 (r, q);
  mpfr_init2 (s, q);
  mpfr_init2 (t, q);
  /* the algorithm consists in computing an upper bound of exp(x) using
     a precision of q bits, and see if we can round to MPFR_PREC(y) taking
     into account the maximal error. Otherwise we increase q. */
  do {
#ifdef DEBUG
  printf("n=%d K=%d l=%d q=%d\n",n,K,l,q);
#endif

  /* if n<0, we have to get an upper bound of log(2)
     in order to get an upper bound of r = x-n*log(2) */
  mpfr_const_log2 (s, (n>=0) ? GMP_RNDZ : GMP_RNDU);
#ifdef DEBUG
  printf("n=%d log(2)=",n); mpfr_print_binary(s); putchar('\n');
#endif
  mpfr_mul_ui (r, s, (n<0) ? -n : n, (n>=0) ? GMP_RNDZ : GMP_RNDU); 
  if (n<0) mpfr_neg(r, r, GMP_RNDD);
  /* r = floor(n*log(2)) */

#ifdef DEBUG
  printf("x=%1.20e\n", mpfr_get_d1 (x));
  printf(" ="); mpfr_print_binary(x); putchar('\n');
  printf("r=%1.20e\n", mpfr_get_d1 (r));
  printf(" ="); mpfr_print_binary(r); putchar('\n');
#endif
  mpfr_sub(r, x, r, GMP_RNDU);
  if (MPFR_SIGN(r)<0) { /* initial approximation n was too large */
    n--;
    mpfr_mul_ui(r, s, (n<0) ? -n : n, GMP_RNDZ);
    if (n<0) mpfr_neg(r, r, GMP_RNDD);
    mpfr_sub(r, x, r, GMP_RNDU);
  }
#ifdef DEBUG
  printf("x-r=%1.20e\n", mpfr_get_d1 (r));
  printf(" ="); mpfr_print_binary(r); putchar('\n');
  if (MPFR_SIGN(r)<0) { fprintf(stderr,"Error in mpfr_exp: r<0\n"); exit(1); }
#endif
  mpfr_div_2ui(r, r, K, GMP_RNDU); /* r = (x-n*log(2))/2^K */

  TMP_MARK(marker);
  MY_INIT_MPZ(ss, 3 + 2*((q-1)/BITS_PER_MP_LIMB));
  exps = mpfr_get_z_exp(ss, s);
  /* s <- 1 + r/1! + r^2/2! + ... + r^l/l! */
  l = (precy<SWITCH) ? mpfr_exp2_aux(ss, r, q, &exps) /* naive method */
    : mpfr_exp2_aux2(ss, r, q, &exps); /* Brent/Kung method */

#ifdef DEBUG
  printf("l=%d q=%d (K+l)*q^2=%1.3e\n", l, q, (K+l)*(double)q*q);
#endif

  for (k=0;k<K;k++) {
    mpz_mul(ss, ss, ss); exps <<= 1;
    exps += mpz_normalize(ss, ss, q);
  }
  mpfr_set_z(s, ss, GMP_RNDN); MPFR_EXP(s) += exps;
  TMP_FREE(marker); /* don't need ss anymore */

  if (n>0) mpfr_mul_2ui(s, s, n, GMP_RNDU);
  else mpfr_div_2ui(s, s, -n, GMP_RNDU);

  /* error is at most 2^K*(3l*(l+1)) ulp for mpfr_exp2_aux */
  if (precy<SWITCH) l = 3*l*(l+1);
  else l = l*(l+4);
  k=0; while (l) { k++; l >>= 1; }
  /* now k = ceil(log(error in ulps)/log(2)) */
  K += k;
#ifdef DEBUG
    printf("after mult. by 2^n:\n");
    if (MPFR_EXP(s) > -1024)
      printf("s=%1.20e\n", mpfr_get_d1 (s));
    printf(" ="); mpfr_print_binary(s); putchar('\n');
    printf("err=%d bits\n", K);
#endif

  l = mpfr_can_round(s, q-K, GMP_RNDN, rnd_mode, precy);
  if (l==0) {
#ifdef DEBUG
     printf("not enough precision, use %d\n", q+BITS_PER_MP_LIMB);
     printf("q=%d q-K=%d precy=%d\n",q,q-K,precy);
#endif
     q += BITS_PER_MP_LIMB;
     mpfr_set_prec(r, q); mpfr_set_prec(s, q); mpfr_set_prec(t, q);
  }
  } while (l==0);

  inexact = mpfr_set (y, s, rnd_mode);

  mpfr_clear(r); mpfr_clear(s); mpfr_clear(t);
  return inexact;
}
Ejemplo n.º 14
0
Archivo: pow.c Proyecto: mahdiz/mpclib
/* The computation of z = pow(x,y) is done by
   z = exp(y * log(x)) = x^y */
int
mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode)
{
  int inexact = 0;
 
  if (MPFR_IS_NAN(x) || MPFR_IS_NAN(y))
    {
      MPFR_SET_NAN(z);
      MPFR_RET_NAN;
    }

  if (MPFR_IS_INF(y))
    {
      mpfr_t one;
      int cmp;

      if (MPFR_SIGN(y) > 0)
        {
          if (MPFR_IS_INF(x))
            {
              MPFR_CLEAR_FLAGS(z);
              if (MPFR_SIGN(x) > 0)
                MPFR_SET_INF(z);
              else
                MPFR_SET_ZERO(z);
              MPFR_SET_POS(z);
              MPFR_RET(0);
            }
          MPFR_CLEAR_FLAGS(z);
          if (MPFR_IS_ZERO(x))
            {
              MPFR_SET_ZERO(z);
              MPFR_SET_POS(z);
              MPFR_RET(0);
            }
          mpfr_init2(one, BITS_PER_MP_LIMB);
          mpfr_set_ui(one, 1, GMP_RNDN);
          cmp = mpfr_cmp_abs(x, one);
          mpfr_clear(one);
          if (cmp > 0)
            {
              MPFR_SET_INF(z);
              MPFR_SET_POS(z);
              MPFR_RET(0);
            }
          else if (cmp < 0)
            {
              MPFR_SET_ZERO(z);
              MPFR_SET_POS(z);
              MPFR_RET(0);
            }
          else
            {
              MPFR_SET_NAN(z);
              MPFR_RET_NAN;
            }
        }
      else
        {
          if (MPFR_IS_INF(x))
            {
              MPFR_CLEAR_FLAGS(z);
              if (MPFR_SIGN(x) > 0)
                MPFR_SET_ZERO(z);
              else
                MPFR_SET_INF(z);
              MPFR_SET_POS(z);
              MPFR_RET(0);
            }
          if (MPFR_IS_ZERO(x))
            {
              MPFR_SET_INF(z);
              MPFR_SET_POS(z);
              MPFR_RET(0);
            }
          mpfr_init2(one, BITS_PER_MP_LIMB);
          mpfr_set_ui(one, 1, GMP_RNDN);
          cmp = mpfr_cmp_abs(x, one);
          mpfr_clear(one);
          MPFR_CLEAR_FLAGS(z);
          if (cmp > 0)
            {
              MPFR_SET_ZERO(z);
              MPFR_SET_POS(z);
              MPFR_RET(0);
            }
          else if (cmp < 0)
            {
              MPFR_SET_INF(z);
              MPFR_SET_POS(z);
              MPFR_RET(0);
            }
          else
            {
              MPFR_SET_NAN(z);
              MPFR_RET_NAN;
            }
        }
    }

  if (MPFR_IS_ZERO(y))
    {
      return mpfr_set_ui (z, 1, GMP_RNDN);
    }

  if (mpfr_isinteger (y))
    {
      mpz_t zi;
      long int zii;
      int exptol;
    
      mpz_init(zi);  
      exptol = mpfr_get_z_exp (zi, y);
        
      if (exptol>0)
        mpz_mul_2exp(zi, zi, exptol);
      else
        mpz_tdiv_q_2exp(zi, zi, (unsigned long int) (-exptol));

      zii=mpz_get_ui(zi);
        
      mpz_clear(zi);
      return mpfr_pow_si (z, x, zii, rnd_mode); 
    }

  if (MPFR_IS_INF(x))
    {
      if (MPFR_SIGN(x) > 0)
        {
          MPFR_CLEAR_FLAGS(z);
          if (MPFR_SIGN(y) > 0)
            MPFR_SET_INF(z);
          else
            MPFR_SET_ZERO(z);
          MPFR_SET_POS(z);
          MPFR_RET(0);
        }
      else
        {
          MPFR_SET_NAN(z);
          MPFR_RET_NAN;
        }
    }

  if (MPFR_IS_ZERO(x))
    {
      MPFR_CLEAR_FLAGS(z);
      MPFR_SET_ZERO(z);
      MPFR_SET_SAME_SIGN(z, x);
      MPFR_RET(0);
    }

  if (MPFR_SIGN(x) < 0)
    {
      MPFR_SET_NAN(z);
      MPFR_RET_NAN;
    }

  MPFR_CLEAR_FLAGS(z);

  /* General case */
  {
    /* Declaration of the intermediary variable */
      mpfr_t t, te, ti;
      int loop = 0, ok;

      /* Declaration of the size variable */
      mp_prec_t Nx = MPFR_PREC(x);   /* Precision of input variable */
      mp_prec_t Ny = MPFR_PREC(y);   /* Precision of input variable */

      mp_prec_t Nt;   /* Precision of the intermediary variable */
      long int err;  /* Precision of error */
                
      /* compute the precision of intermediary variable */
      Nt=MAX(Nx,Ny);
      /* the optimal number of bits : see algorithms.ps */
      Nt=Nt+5+_mpfr_ceil_log2(Nt);

      /* initialise of intermediary	variable */
      mpfr_init(t);
      mpfr_init(ti);
      mpfr_init(te);             

      do
        {

          loop ++;

          /* reactualisation of the precision */
          mpfr_set_prec (t, Nt);
          mpfr_set_prec (ti, Nt);
          mpfr_set_prec (te, Nt);

          /* compute exp(y*ln(x)) */
          mpfr_log (ti, x, GMP_RNDU);         /* ln(n) */
          mpfr_mul (te, y, ti, GMP_RNDU);       /* y*ln(n) */
          mpfr_exp (t, te, GMP_RNDN);         /* exp(x*ln(n))*/

	/* estimation of the error -- see pow function in algorithms.ps*/
          err = Nt - (MPFR_EXP(te) + 3);

	/* actualisation of the precision */
          Nt += 10;

          ok = mpfr_can_round (t, err, GMP_RNDN, rnd_mode, Ny);

          /* check exact power */
          if (ok == 0 && loop == 1)
            ok = mpfr_pow_is_exact (x, y);

        }
      while (err < 0 || ok == 0);
      
      inexact = mpfr_set (z, t, rnd_mode);

      mpfr_clear (t);
      mpfr_clear (ti);
      mpfr_clear (te);
    }
    return inexact;
}