コード例 #1
0
ファイル: rmath.cpp プロジェクト: GilesBathgate/RapCAD
decimal r_log(const decimal& a,bool round)
{
#ifdef USE_CGAL
	CGAL::Gmpfr m;
	CGAL::Gmpfr n=to_gmpfr(a);
	mpfr_log(m.fr(),n.fr(),MPFR_RNDN);
	return r_round_preference(decimal(m),round);
#else
	return r_round_preference(log(a),round);
#endif
}
コード例 #2
0
/**
 * Wrapper function to find the square of the log of a number of type mpz_t.
 */
void compute_logn2(mpz_t rop, mpz_t n) {
  mpfr_t tmp;
  mpfr_init(tmp);

  mpfr_set_z(tmp, n, MPFR_RNDN);
  mpfr_log(tmp, tmp, MPFR_RNDA);
  mpfr_pow_ui(tmp, tmp, 2, MPFR_RNDA);
  mpfr_ceil(tmp, tmp);

  mpfr_get_z(rop, tmp, MPFR_RNDA);
  mpfr_clear(tmp);
}
コード例 #3
0
ファイル: t-const_log10.c プロジェクト: bluescarni/arb
int main()
{
    long iter;
    flint_rand_t state;

    printf("const_log10....");
    fflush(stdout);
    flint_randinit(state);

    for (iter = 0; iter < 250; iter++)
    {
        fmprb_t r;
        mpfr_t s;
        long accuracy, prec;

        prec = 2 + n_randint(state, 1 << n_randint(state, 16));

        fmprb_init(r);
        mpfr_init2(s, prec + 1000);

        fmprb_const_log10(r, prec);
        mpfr_set_ui(s, 10, MPFR_RNDN);
        mpfr_log(s, s, MPFR_RNDN);

        if (!fmprb_contains_mpfr(r, s))
        {
            printf("FAIL: containment\n\n");
            printf("prec = %ld\n", prec);
            printf("r = "); fmprb_printd(r, prec / 3.33); printf("\n\n");
            abort();
        }

        accuracy = fmprb_rel_accuracy_bits(r);

        if (accuracy < prec - 4)
        {
            printf("FAIL: poor accuracy\n\n");
            printf("prec = %ld\n", prec);
            printf("r = "); fmprb_printd(r, prec / 3.33); printf("\n\n");
            abort();
        }

        fmprb_clear(r);
        mpfr_clear(s);
    }

    flint_randclear(state);
    flint_cleanup();
    printf("PASS\n");
    return EXIT_SUCCESS;
}
コード例 #4
0
void MathUtils::GetSmoothnessBase(mpz_class& ret_base, mpz_class& N)
{
	mpfr_t f_N, log_N, log_log_N;
	mpz_t base_mpz;
	mpz_init(base_mpz);

	mpfr_init(f_N); mpfr_init(log_N); mpfr_init(log_log_N);

	mpfr_set_z(f_N, N.get_mpz_t(), MPFR_RNDU);		//f_N = N
	mpfr_log(log_N, f_N, MPFR_RNDU); 				//log_N = log(N)
	mpfr_log(log_log_N, log_N, MPFR_RNDU); 			//log_log_N = log(log(N))

	mpfr_mul(f_N, log_N, log_log_N, MPFR_RNDU); 	//f_N = log(N) * log(log(N))
	mpfr_sqrt(f_N, f_N, MPFR_RNDU); 				//f_N = sqrt(f_N)

	mpfr_div_ui(f_N, f_N, 2, MPFR_RNDU);  			//f_N = f_N/2
	mpfr_exp(f_N, f_N, MPFR_RNDU);					//f_N = e^f_N

	mpfr_get_z(base_mpz, f_N, MPFR_RNDU);
	ret_base = mpz_class(base_mpz);

	mpfr_clears(f_N, log_N, log_log_N, NULL);
}
コード例 #5
0
ファイル: MPFRNormalR.hpp プロジェクト: 23119841/openbr
    // Evaluate the sign of the rejection condition v^2 + 4*u^2*log(u)
    int Reject(mpfr_t u, mpfr_t v, mpfr_prec_t prec, mpfr_rnd_t round) const {
      // Use x1, x2 as scratch
      mpfr_set_prec(_x1, prec);

      mpfr_log(_x1, u, round);
      mpfr_mul(_x1, _x1, u, round); // Important to do the multiplications in
      mpfr_mul(_x1, _x1, u, round); // this order so that rounding works right.
      mpfr_mul_2ui(_x1, _x1, 2u, round); // 4*u^2*log(u)

      mpfr_set_prec(_x2, prec);
      mpfr_mul(_x2, v, v, round);        // v^2

      mpfr_add(_x1, _x1, _x2, round);    // v^2 + 4*u^2*log(u)

      return mpfr_sgn(_x1);
    }
コード例 #6
0
ファイル: dgsl.c プロジェクト: malb/gghlite-flint
void fmpq_poly_sample_D1(fmpq_poly_t f, int n, mpfr_prec_t prec, gmp_randstate_t state) {
  mpfr_t u1; mpfr_init2(u1, prec);
  mpfr_t u2; mpfr_init2(u2, prec);
  mpfr_t z1; mpfr_init2(z1, prec);
  mpfr_t z2; mpfr_init2(z2, prec);

  mpfr_t pi2; mpfr_init2(pi2, prec);
  mpfr_const_pi(pi2, MPFR_RNDN);
  mpfr_mul_si(pi2, pi2, 2, MPFR_RNDN);

  mpf_t tmp_f;
  mpq_t tmp_q;
  mpf_init(tmp_f);
  mpq_init(tmp_q);

  assert(n%2==0);

  for(long i=0; i<n; i+=2) {
    mpfr_urandomb(u1, state);
    mpfr_urandomb(u2, state);
    mpfr_log(u1, u1, MPFR_RNDN);
    mpfr_mul_si(u1, u1, -2, MPFR_RNDN);
    mpfr_sqrt(u1, u1, MPFR_RNDN);
    mpfr_mul(u2, pi2, u2, MPFR_RNDN);
    mpfr_cos(z1, u2, MPFR_RNDN);
    mpfr_mul(z1, z1, u1, MPFR_RNDN); //z1 = sqrt(-2*log(u1)) * cos(2*pi*u2)
    mpfr_sin(z2, u2, MPFR_RNDN);
    mpfr_mul(z2, z2, u1, MPFR_RNDN); //z1 = sqrt(-2*log(u1)) * sin(2*pi*U2)

    mpfr_get_f(tmp_f, z1, MPFR_RNDN);
    mpq_set_f(tmp_q, tmp_f);
    fmpq_poly_set_coeff_mpq(f, i, tmp_q);

    mpfr_get_f(tmp_f, z2, MPFR_RNDN);
    mpq_set_f(tmp_q, tmp_f);
    fmpq_poly_set_coeff_mpq(f, i+1, tmp_q);
  }
  mpf_clear(tmp_f);
  mpq_clear(tmp_q);
  mpfr_clear(pi2);
  mpfr_clear(u1);
  mpfr_clear(u2);
  mpfr_clear(z1);
  mpfr_clear(z2);
}
コード例 #7
0
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_float::ln() {
#ifdef KNUMBER_USE_MPFR
	mpfr_t mpfr;
	mpfr_init_set_f(mpfr, mpf_, rounding_mode);
	mpfr_log(mpfr, mpfr, rounding_mode);
	mpfr_get_f(mpf_, mpfr, rounding_mode);
	mpfr_clear(mpfr);
	return this;
#else
	const double x = mpf_get_d(mpf_);
	if(isinf(x)) {
		delete this;
		return new knumber_error(knumber_error::ERROR_POS_INFINITY);
	} else {
		return execute_libc_func< ::log>(x);
	}
#endif
}
コード例 #8
0
ファイル: functions_for_eval.cpp プロジェクト: hozblok/CAPSYS
REAL _ln(REAL a, REAL, QByteArray &error)
{
    if (a <= ZERO)
    {
        error = QByteArray("ERROR: ln(a <= 0!!!)!");
        print(error.constData());
        return ZERO;
    }
    mpfr_t tmp1; mpfr_init2(tmp1, NUMBITS);
    mpfr_t result; mpfr_init2(result, NUMBITS);
//    mpfr_init_set_f(tmp1, a.get_mpf_t(), MPFR_RNDN);
    mpfr_set_str(tmp1, getString(a).data(), 10, MPFR_RNDN);
    mpfr_log(result, tmp1, MPFR_RNDN);
    mpfr_get_f(a.get_mpf_t(), result, MPFR_RNDN);
    mpfr_clear(tmp1);
    mpfr_clear(result);
    return a;
}
コード例 #9
0
ファイル: tlog.c プロジェクト: STAR111/GCC_parser
static int
test_log (mpfr_ptr a, mpfr_srcptr b, mp_rnd_t rnd_mode)
{
  int res;
  int ok = rnd_mode == GMP_RNDN && mpfr_number_p (b) && mpfr_get_prec (a)>=53;
  if (ok)
    {
      mpfr_print_raw (b);
    }
  res = mpfr_log (a, b, rnd_mode);
  if (ok)
    {
      printf (" ");
      mpfr_print_raw (a);
      printf ("\n");
    }
  return res;
}
コード例 #10
0
ファイル: log.c プロジェクト: isuruf/arb
/* requires x != 1 */
static void
arf_log_via_mpfr(arf_t z, const arf_t x, slong prec, arf_rnd_t rnd)
{
    mpfr_t xf, zf;
    mp_ptr zptr, tmp;
    mp_srcptr xptr;
    mp_size_t xn, zn, val;
    TMP_INIT;
    TMP_START;

    zn = (prec + FLINT_BITS - 1) / FLINT_BITS;
    tmp = TMP_ALLOC(zn * sizeof(mp_limb_t));

    ARF_GET_MPN_READONLY(xptr, xn, x);

    xf->_mpfr_d = (mp_ptr) xptr;
    xf->_mpfr_prec = xn * FLINT_BITS;
    xf->_mpfr_sign = ARF_SGNBIT(x) ? -1 : 1;
    xf->_mpfr_exp = ARF_EXP(x);

    zf->_mpfr_d = tmp;
    zf->_mpfr_prec = prec;
    zf->_mpfr_sign = 1;
    zf->_mpfr_exp = 0;

    mpfr_set_emin(MPFR_EMIN_MIN);
    mpfr_set_emax(MPFR_EMAX_MAX);

    mpfr_log(zf, xf, arf_rnd_to_mpfr(rnd));

    val = 0;
    while (tmp[val] == 0)
        val++;

    ARF_GET_MPN_WRITE(zptr, zn - val, z);
    flint_mpn_copyi(zptr, tmp + val, zn - val);
    if (zf->_mpfr_sign < 0)
        ARF_NEG(z);

    fmpz_set_si(ARF_EXPREF(z), zf->_mpfr_exp);

    TMP_END;
}
コード例 #11
0
ファイル: FirstLogTable.cpp プロジェクト: hoangt/PandA-bambu
	mpz_class FirstLogTable::function(int x)
	{ 
		mpz_class result;
		double apprinv;
		mpfr_t i,l;
		mpz_t r;

		mpfr_init(i);
		mpfr_init2(l,wOut);
		mpz_init2(r,400);
		apprinv = fit->output2double(fit->function(x));;
		// result = double2output(log(apprinv));
		mpfr_set_d(i, apprinv, GMP_RNDN);
		mpfr_log(l, i, GMP_RNDN);
		mpfr_neg(l, l, GMP_RNDN);

		// Remove the sum of small offsets that are added to the other log tables
		for(int j=1; j<=op->stages; j++){
			mpfr_set_d(i, 1.0, GMP_RNDN);
			int pi=op->p[j];
			mpfr_mul_2si(i, i, -2*pi, GMP_RNDN);
			mpfr_sub(l, l, i,  GMP_RNDN);
		}

 

		// code the log in 2's compliment
		mpfr_mul_2si(l, l, wOut, GMP_RNDN);
		mpfr_get_z(r, l, GMP_RNDN);
		result = mpz_class(r); // signed

		// This is a very inefficient way of converting
		mpz_class t = mpz_class(1) << wOut; 
		result = t+result;
		if(result>t) result-=t;

		//  cout << "x="<<x<<" apprinv="<<apprinv<<" logapprinv="<<log(apprinv)<<" result="<<result<<endl;
		mpfr_clear(i);
		mpfr_clear(l);
		mpz_clear(r);
		return  result;
	}
コード例 #12
0
ファイル: tlog.c プロジェクト: STAR111/GCC_parser
static void
x_near_one (void)
{
  mpfr_t x, y;
  int inex;

  mpfr_init2 (x, 32);
  mpfr_init2 (y, 16);

  mpfr_set_ui (x, 1, GMP_RNDN);
  mpfr_nextbelow (x);
  inex = mpfr_log (y, x, GMP_RNDD);
  if (mpfr_cmp_str (y, "-0.1000000000000001E-31", 2, GMP_RNDN)
      || inex >= 0)
    {
      printf ("Failure in x_near_one, got inex = %d and\ny = ", inex);
      mpfr_dump (y);
    }

  mpfr_clears (x, y, (mpfr_ptr) 0);
}
コード例 #13
0
ファイル: tsub.c プロジェクト: axDev-toolchain/mpfr
static void
bug_ddefour(void)
{
    mpfr_t ex, ex1, ex2, ex3, tot, tot1;

    mpfr_init2(ex, 53);
    mpfr_init2(ex1, 53);
    mpfr_init2(ex2, 53);
    mpfr_init2(ex3, 53);
    mpfr_init2(tot, 150);
    mpfr_init2(tot1, 150);

    mpfr_set_ui( ex, 1, MPFR_RNDN);
    mpfr_mul_2exp( ex, ex, 906, MPFR_RNDN);
    mpfr_log( tot, ex, MPFR_RNDN);
    mpfr_set( ex1, tot, MPFR_RNDN); /* ex1 = high(tot) */
    test_sub( ex2, tot, ex1, MPFR_RNDN); /* ex2 = high(tot - ex1) */
    test_sub( tot1, tot, ex1, MPFR_RNDN); /* tot1 = tot - ex1 */
    mpfr_set( ex3, tot1, MPFR_RNDN); /* ex3 = high(tot - ex1) */

    if (mpfr_cmp(ex2, ex3))
    {
        printf ("Error in ddefour test.\n");
        printf ("ex2=");
        mpfr_print_binary (ex2);
        puts ("");
        printf ("ex3=");
        mpfr_print_binary (ex3);
        puts ("");
        exit (1);
    }

    mpfr_clear (ex);
    mpfr_clear (ex1);
    mpfr_clear (ex2);
    mpfr_clear (ex3);
    mpfr_clear (tot);
    mpfr_clear (tot1);
}
コード例 #14
0
ファイル: li2.c プロジェクト: Scorpiion/Renux_cross_gcc
/* try asymptotic expansion when x is large and positive:
   Li2(x) = -log(x)^2/2 + Pi^2/3 - 1/x + O(1/x^2).
   More precisely for x >= 2 we have for g(x) = -log(x)^2/2 + Pi^2/3:
   -2 <= x * (Li2(x) - g(x)) <= -1
   thus |Li2(x) - g(x)| <= 2/x.
   Assumes x >= 38, which ensures log(x)^2/2 >= 2*Pi^2/3, and g(x) <= -3.3.
   Return 0 if asymptotic expansion failed (unable to round), otherwise
   returns correct ternary value.
*/
static int
mpfr_li2_asympt_pos (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  mpfr_t g, h;
  mp_prec_t w = MPFR_PREC (y) + 20;
  int inex = 0;

  MPFR_ASSERTN (mpfr_cmp_ui (x, 38) >= 0);

  mpfr_init2 (g, w);
  mpfr_init2 (h, w);
  mpfr_log (g, x, GMP_RNDN);    /* rel. error <= |(1 + theta) - 1| */
  mpfr_sqr (g, g, GMP_RNDN);    /* rel. error <= |(1 + theta)^3 - 1| <= 2^(2-w) */
  mpfr_div_2ui (g, g, 1, GMP_RNDN);     /* rel. error <= 2^(2-w) */
  mpfr_const_pi (h, GMP_RNDN);  /* error <= 2^(1-w) */
  mpfr_sqr (h, h, GMP_RNDN);    /* rel. error <= 2^(2-w) */
  mpfr_div_ui (h, h, 3, GMP_RNDN);      /* rel. error <= |(1 + theta)^4 - 1|
                                           <= 5 * 2^(-w) */
  /* since x is chosen such that log(x)^2/2 >= 2 * (Pi^2/3), we should have
     g >= 2*h, thus |g-h| >= |h|, and the relative error on g is at most
     multiplied by 2 in the difference, and that by h is unchanged. */
  MPFR_ASSERTN (MPFR_EXP (g) > MPFR_EXP (h));
  mpfr_sub (g, h, g, GMP_RNDN); /* err <= ulp(g)/2 + g*2^(3-w) + g*5*2^(-w)
                                   <= ulp(g) * (1/2 + 8 + 5) < 14 ulp(g).

                                   If in addition 2/x <= 2 ulp(g), i.e.,
                                   1/x <= ulp(g), then the total error is
                                   bounded by 16 ulp(g). */
  if ((MPFR_EXP (x) >= (mp_exp_t) w - MPFR_EXP (g)) &&
      MPFR_CAN_ROUND (g, w - 4, MPFR_PREC (y), rnd_mode))
    inex = mpfr_set (y, g, rnd_mode);

  mpfr_clear (g);
  mpfr_clear (h);

  return inex;
}
コード例 #15
0
ファイル: grandom.c プロジェクト: BrianGladman/mpfr
int
mpfr_grandom (mpfr_ptr rop1, mpfr_ptr rop2, gmp_randstate_t rstate,
              mpfr_rnd_t rnd)
{
  int inex1, inex2, s1, s2;
  mpz_t x, y, xp, yp, t, a, b, s;
  mpfr_t sfr, l, r1, r2;
  mpfr_prec_t tprec, tprec0;

  inex2 = inex1 = 0;

  if (rop2 == NULL) /* only one output requested. */
    {
      tprec0 = MPFR_PREC (rop1);
    }
  else
    {
      tprec0 = MAX (MPFR_PREC (rop1), MPFR_PREC (rop2));
    }

  tprec0 += 11;

  /* We use "Marsaglia polar method" here (cf.
     George Marsaglia, Normal (Gaussian) random variables for supercomputers
     The Journal of Supercomputing, Volume 5, Number 1, 49–55
     DOI: 10.1007/BF00155857).

     First we draw uniform x and y in [0,1] using mpz_urandomb (in
     fixed precision), and scale them to [-1, 1].
  */

  mpz_init (xp);
  mpz_init (yp);
  mpz_init (x);
  mpz_init (y);
  mpz_init (t);
  mpz_init (s);
  mpz_init (a);
  mpz_init (b);
  mpfr_init2 (sfr, MPFR_PREC_MIN);
  mpfr_init2 (l, MPFR_PREC_MIN);
  mpfr_init2 (r1, MPFR_PREC_MIN);
  if (rop2 != NULL)
    mpfr_init2 (r2, MPFR_PREC_MIN);

  mpz_set_ui (xp, 0);
  mpz_set_ui (yp, 0);

  for (;;)
    {
      tprec = tprec0;
      do
        {
          mpz_urandomb (xp, rstate, tprec);
          mpz_urandomb (yp, rstate, tprec);
          mpz_mul (a, xp, xp);
          mpz_mul (b, yp, yp);
          mpz_add (s, a, b);
        }
      while (mpz_sizeinbase (s, 2) > tprec * 2); /* x^2 + y^2 <= 2^{2tprec} */

      for (;;)
        {
          /* FIXME: compute s as s += 2x + 2y + 2 */
          mpz_add_ui (a, xp, 1);
          mpz_add_ui (b, yp, 1);
          mpz_mul (a, a, a);
          mpz_mul (b, b, b);
          mpz_add (s, a, b);
          if ((mpz_sizeinbase (s, 2) <= 2 * tprec) ||
              ((mpz_sizeinbase (s, 2) == 2 * tprec + 1) &&
               (mpz_scan1 (s, 0) == 2 * tprec)))
            goto yeepee;
          /* Extend by 32 bits */
          mpz_mul_2exp (xp, xp, 32);
          mpz_mul_2exp (yp, yp, 32);
          mpz_urandomb (x, rstate, 32);
          mpz_urandomb (y, rstate, 32);
          mpz_add (xp, xp, x);
          mpz_add (yp, yp, y);
          tprec += 32;

          mpz_mul (a, xp, xp);
          mpz_mul (b, yp, yp);
          mpz_add (s, a, b);
          if (mpz_sizeinbase (s, 2) > tprec * 2)
            break;
        }
    }
 yeepee:

  /* FIXME: compute s with s -= 2x + 2y + 2 */
  mpz_mul (a, xp, xp);
  mpz_mul (b, yp, yp);
  mpz_add (s, a, b);
  /* Compute the signs of the output */
  mpz_urandomb (x, rstate, 2);
  s1 = mpz_tstbit (x, 0);
  s2 = mpz_tstbit (x, 1);
  for (;;)
    {
      /* s = xp^2 + yp^2 (loop invariant) */
      mpfr_set_prec (sfr, 2 * tprec);
      mpfr_set_prec (l, tprec);
      mpfr_set_z (sfr, s, MPFR_RNDN); /* exact */
      mpfr_mul_2si (sfr, sfr, -2 * tprec, MPFR_RNDN); /* exact */
      mpfr_log (l, sfr, MPFR_RNDN);
      mpfr_neg (l, l, MPFR_RNDN);
      mpfr_mul_2si (l, l, 1, MPFR_RNDN);
      mpfr_div (l, l, sfr, MPFR_RNDN);
      mpfr_sqrt (l, l, MPFR_RNDN);

      mpfr_set_prec (r1, tprec);
      mpfr_mul_z (r1, l, xp, MPFR_RNDN);
      mpfr_div_2ui (r1, r1, tprec, MPFR_RNDN); /* exact */
      if (s1)
        mpfr_neg (r1, r1, MPFR_RNDN);
      if (MPFR_CAN_ROUND (r1, tprec - 2, MPFR_PREC (rop1), rnd))
        {
          if (rop2 != NULL)
            {
              mpfr_set_prec (r2, tprec);
              mpfr_mul_z (r2, l, yp, MPFR_RNDN);
              mpfr_div_2ui (r2, r2, tprec, MPFR_RNDN); /* exact */
              if (s2)
                mpfr_neg (r2, r2, MPFR_RNDN);
              if (MPFR_CAN_ROUND (r2, tprec - 2, MPFR_PREC (rop2), rnd))
                break;
            }
          else
            break;
        }
      /* Extend by 32 bits */
      mpz_mul_2exp (xp, xp, 32);
      mpz_mul_2exp (yp, yp, 32);
      mpz_urandomb (x, rstate, 32);
      mpz_urandomb (y, rstate, 32);
      mpz_add (xp, xp, x);
      mpz_add (yp, yp, y);
      tprec += 32;
      mpz_mul (a, xp, xp);
      mpz_mul (b, yp, yp);
      mpz_add (s, a, b);
    }
  inex1 = mpfr_set (rop1, r1, rnd);
  if (rop2 != NULL)
    {
      inex2 = mpfr_set (rop2, r2, rnd);
      inex2 = mpfr_check_range (rop2, inex2, rnd);
    }
  inex1 = mpfr_check_range (rop1, inex1, rnd);

  if (rop2 != NULL)
    mpfr_clear (r2);
  mpfr_clear (r1);
  mpfr_clear (l);
  mpfr_clear (sfr);
  mpz_clear (b);
  mpz_clear (a);
  mpz_clear (s);
  mpz_clear (t);
  mpz_clear (y);
  mpz_clear (x);
  mpz_clear (yp);
  mpz_clear (xp);

  return INEX (inex1, inex2);
}
コード例 #16
0
ファイル: log1p.c プロジェクト: Scorpiion/Renux_cross_gcc
int
mpfr_log1p (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
{
  int comp, inexact;
  mp_exp_t ex;
  MPFR_SAVE_EXPO_DECL (expo);

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN (x))
        {
          MPFR_SET_NAN (y);
          MPFR_RET_NAN;
        }
      /* check for inf or -inf (result is not defined) */
      else if (MPFR_IS_INF (x))
        {
          if (MPFR_IS_POS (x))
            {
              MPFR_SET_INF (y);
              MPFR_SET_POS (y);
              MPFR_RET (0);
            }
          else
            {
              MPFR_SET_NAN (y);
              MPFR_RET_NAN;
            }
        }
      else /* x is zero */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          MPFR_SET_ZERO (y);   /* log1p(+/- 0) = +/- 0 */
          MPFR_SET_SAME_SIGN (y, x);
          MPFR_RET (0);
        }
    }

  ex = MPFR_GET_EXP (x);
  if (ex < 0)  /* -0.5 < x < 0.5 */
    {
      /* For x > 0,    abs(log(1+x)-x) < x^2/2.
         For x > -0.5, abs(log(1+x)-x) < x^2. */
      if (MPFR_IS_POS (x))
        MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, - ex - 1, 0, 0, rnd_mode, {});
      else
        MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, - ex, 0, 1, rnd_mode, {});
    }

  comp = mpfr_cmp_si (x, -1);
  /* log1p(x) is undefined for x < -1 */
  if (MPFR_UNLIKELY(comp <= 0))
    {
      if (comp == 0)
        /* x=0: log1p(-1)=-inf (division by zero) */
        {
          MPFR_SET_INF (y);
          MPFR_SET_NEG (y);
          MPFR_RET (0);
        }
      MPFR_SET_NAN (y);
      MPFR_RET_NAN;
    }

  MPFR_SAVE_EXPO_MARK (expo);

  /* General case */
  {
    /* Declaration of the intermediary variable */
    mpfr_t t;
    /* Declaration of the size variable */
    mp_prec_t Ny = MPFR_PREC(y);             /* target precision */
    mp_prec_t Nt;                            /* working precision */
    mp_exp_t err;                            /* error */
    MPFR_ZIV_DECL (loop);

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

    /* if |x| is smaller than 2^(-e), we will loose about e bits
       in log(1+x) */
    if (MPFR_EXP(x) < 0)
      Nt += -MPFR_EXP(x);

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

    /* First computation of log1p */
    MPFR_ZIV_INIT (loop, Nt);
    for (;;)
      {
        /* compute log1p */
        inexact = mpfr_add_ui (t, x, 1, GMP_RNDN);      /* 1+x */
        /* if inexact = 0, then t = x+1, and the result is simply log(t) */
        if (inexact == 0)
          {
            inexact = mpfr_log (y, t, rnd_mode);
            goto end;
          }
        mpfr_log (t, t, GMP_RNDN);        /* log(1+x) */

        /* the error is bounded by (1/2+2^(1-EXP(t))*ulp(t) (cf algorithms.tex)
           if EXP(t)>=2, then error <= ulp(t)
           if EXP(t)<=1, then error <= 2^(2-EXP(t))*ulp(t) */
        err = Nt - MAX (0, 2 - MPFR_GET_EXP (t));

        if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
          break;

        /* increase the precision */
        MPFR_ZIV_NEXT (loop, Nt);
        mpfr_set_prec (t, Nt);
      }
    inexact = mpfr_set (y, t, rnd_mode);

  end:
    MPFR_ZIV_FREE (loop);
    mpfr_clear (t);
  }

  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (y, inexact, rnd_mode);
}
コード例 #17
0
ファイル: pow.c プロジェクト: Distrotech/mpfr
/* The computation of z = pow(x,y) is done by
   z = exp(y * log(x)) = x^y
   For the special cases, see Section F.9.4.4 of the C standard:
     _ pow(±0, y) = ±inf for y an odd integer < 0.
     _ pow(±0, y) = +inf for y < 0 and not an odd integer.
     _ pow(±0, y) = ±0 for y an odd integer > 0.
     _ pow(±0, y) = +0 for y > 0 and not an odd integer.
     _ pow(-1, ±inf) = 1.
     _ pow(+1, y) = 1 for any y, even a NaN.
     _ pow(x, ±0) = 1 for any x, even a NaN.
     _ pow(x, y) = NaN for finite x < 0 and finite non-integer y.
     _ pow(x, -inf) = +inf for |x| < 1.
     _ pow(x, -inf) = +0 for |x| > 1.
     _ pow(x, +inf) = +0 for |x| < 1.
     _ pow(x, +inf) = +inf for |x| > 1.
     _ pow(-inf, y) = -0 for y an odd integer < 0.
     _ pow(-inf, y) = +0 for y < 0 and not an odd integer.
     _ pow(-inf, y) = -inf for y an odd integer > 0.
     _ pow(-inf, y) = +inf for y > 0 and not an odd integer.
     _ pow(+inf, y) = +0 for y < 0.
     _ pow(+inf, y) = +inf for y > 0. */
int
mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode)
{
  int inexact;
  int cmp_x_1;
  int y_is_integer;
  MPFR_SAVE_EXPO_DECL (expo);

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

  if (MPFR_ARE_SINGULAR (x, y))
    {
      /* pow(x, 0) returns 1 for any x, even a NaN. */
      if (MPFR_UNLIKELY (MPFR_IS_ZERO (y)))
        return mpfr_set_ui (z, 1, rnd_mode);
      else if (MPFR_IS_NAN (x))
        {
          MPFR_SET_NAN (z);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_NAN (y))
        {
          /* pow(+1, NaN) returns 1. */
          if (mpfr_cmp_ui (x, 1) == 0)
            return mpfr_set_ui (z, 1, rnd_mode);
          MPFR_SET_NAN (z);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF (y))
        {
          if (MPFR_IS_INF (x))
            {
              if (MPFR_IS_POS (y))
                MPFR_SET_INF (z);
              else
                MPFR_SET_ZERO (z);
              MPFR_SET_POS (z);
              MPFR_RET (0);
            }
          else
            {
              int cmp;
              cmp = mpfr_cmpabs (x, __gmpfr_one) * MPFR_INT_SIGN (y);
              MPFR_SET_POS (z);
              if (cmp > 0)
                {
                  /* Return +inf. */
                  MPFR_SET_INF (z);
                  MPFR_RET (0);
                }
              else if (cmp < 0)
                {
                  /* Return +0. */
                  MPFR_SET_ZERO (z);
                  MPFR_RET (0);
                }
              else
                {
                  /* Return 1. */
                  return mpfr_set_ui (z, 1, rnd_mode);
                }
            }
        }
      else if (MPFR_IS_INF (x))
        {
          int negative;
          /* Determine the sign now, in case y and z are the same object */
          negative = MPFR_IS_NEG (x) && is_odd (y);
          if (MPFR_IS_POS (y))
            MPFR_SET_INF (z);
          else
            MPFR_SET_ZERO (z);
          if (negative)
            MPFR_SET_NEG (z);
          else
            MPFR_SET_POS (z);
          MPFR_RET (0);
        }
      else
        {
          int negative;
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          /* Determine the sign now, in case y and z are the same object */
          negative = MPFR_IS_NEG(x) && is_odd (y);
          if (MPFR_IS_NEG (y))
            {
              MPFR_ASSERTD (! MPFR_IS_INF (y));
              MPFR_SET_INF (z);
              mpfr_set_divby0 ();
            }
          else
            MPFR_SET_ZERO (z);
          if (negative)
            MPFR_SET_NEG (z);
          else
            MPFR_SET_POS (z);
          MPFR_RET (0);
        }
    }

  /* x^y for x < 0 and y not an integer is not defined */
  y_is_integer = mpfr_integer_p (y);
  if (MPFR_IS_NEG (x) && ! y_is_integer)
    {
      MPFR_SET_NAN (z);
      MPFR_RET_NAN;
    }

  /* now the result cannot be NaN:
     (1) either x > 0
     (2) or x < 0 and y is an integer */

  cmp_x_1 = mpfr_cmpabs (x, __gmpfr_one);
  if (cmp_x_1 == 0)
    return mpfr_set_si (z, MPFR_IS_NEG (x) && is_odd (y) ? -1 : 1, rnd_mode);

  /* now we have:
     (1) either x > 0
     (2) or x < 0 and y is an integer
     and in addition |x| <> 1.
  */

  /* detect overflow: an overflow is possible if
     (a) |x| > 1 and y > 0
     (b) |x| < 1 and y < 0.
     FIXME: this assumes 1 is always representable.

     FIXME2: maybe we can test overflow and underflow simultaneously.
     The idea is the following: first compute an approximation to
     y * log2|x|, using rounding to nearest. If |x| is not too near from 1,
     this approximation should be accurate enough, and in most cases enable
     one to prove that there is no underflow nor overflow.
     Otherwise, it should enable one to check only underflow or overflow,
     instead of both cases as in the present case.
  */
  if (cmp_x_1 * MPFR_SIGN (y) > 0)
    {
      mpfr_t t;
      int negative, overflow;

      MPFR_SAVE_EXPO_MARK (expo);
      mpfr_init2 (t, 53);
      /* we want a lower bound on y*log2|x|:
         (i) if x > 0, it suffices to round log2(x) toward zero, and
             to round y*o(log2(x)) toward zero too;
         (ii) if x < 0, we first compute t = o(-x), with rounding toward 1,
              and then follow as in case (1). */
      if (MPFR_SIGN (x) > 0)
        mpfr_log2 (t, x, MPFR_RNDZ);
      else
        {
          mpfr_neg (t, x, (cmp_x_1 > 0) ? MPFR_RNDZ : MPFR_RNDU);
          mpfr_log2 (t, t, MPFR_RNDZ);
        }
      mpfr_mul (t, t, y, MPFR_RNDZ);
      overflow = mpfr_cmp_si (t, __gmpfr_emax) > 0;
      mpfr_clear (t);
      MPFR_SAVE_EXPO_FREE (expo);
      if (overflow)
        {
          MPFR_LOG_MSG (("early overflow detection\n", 0));
          negative = MPFR_SIGN(x) < 0 && is_odd (y);
          return mpfr_overflow (z, rnd_mode, negative ? -1 : 1);
        }
    }

  /* Basic underflow checking. One has:
   *   - if y > 0, |x^y| < 2^(EXP(x) * y);
   *   - if y < 0, |x^y| <= 2^((EXP(x) - 1) * y);
   * so that one can compute a value ebound such that |x^y| < 2^ebound.
   * If we have ebound <= emin - 2 (emin - 1 in directed rounding modes),
   * then there is an underflow and we can decide the return value.
   */
  if (MPFR_IS_NEG (y) ? (MPFR_GET_EXP (x) > 1) : (MPFR_GET_EXP (x) < 0))
    {
      mpfr_t tmp;
      mpfr_eexp_t ebound;
      int inex2;

      /* We must restore the flags. */
      MPFR_SAVE_EXPO_MARK (expo);
      mpfr_init2 (tmp, sizeof (mpfr_exp_t) * CHAR_BIT);
      inex2 = mpfr_set_exp_t (tmp, MPFR_GET_EXP (x), MPFR_RNDN);
      MPFR_ASSERTN (inex2 == 0);
      if (MPFR_IS_NEG (y))
        {
          inex2 = mpfr_sub_ui (tmp, tmp, 1, MPFR_RNDN);
          MPFR_ASSERTN (inex2 == 0);
        }
      mpfr_mul (tmp, tmp, y, MPFR_RNDU);
      if (MPFR_IS_NEG (y))
        mpfr_nextabove (tmp);
      /* tmp doesn't necessarily fit in ebound, but that doesn't matter
         since we get the minimum value in such a case. */
      ebound = mpfr_get_exp_t (tmp, MPFR_RNDU);
      mpfr_clear (tmp);
      MPFR_SAVE_EXPO_FREE (expo);
      if (MPFR_UNLIKELY (ebound <=
                         __gmpfr_emin - (rnd_mode == MPFR_RNDN ? 2 : 1)))
        {
          /* warning: mpfr_underflow rounds away from 0 for MPFR_RNDN */
          MPFR_LOG_MSG (("early underflow detection\n", 0));
          return mpfr_underflow (z,
                                 rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode,
                                 MPFR_SIGN (x) < 0 && is_odd (y) ? -1 : 1);
        }
    }

  /* If y is an integer, we can use mpfr_pow_z (based on multiplications),
     but if y is very large (I'm not sure about the best threshold -- VL),
     we shouldn't use it, as it can be very slow and take a lot of memory
     (and even crash or make other programs crash, as several hundred of
     MBs may be necessary). Note that in such a case, either x = +/-2^b
     (this case is handled below) or x^y cannot be represented exactly in
     any precision supported by MPFR (the general case uses this property).
  */
  if (y_is_integer && (MPFR_GET_EXP (y) <= 256))
    {
      mpz_t zi;

      MPFR_LOG_MSG (("special code for y not too large integer\n", 0));
      mpz_init (zi);
      mpfr_get_z (zi, y, MPFR_RNDN);
      inexact = mpfr_pow_z (z, x, zi, rnd_mode);
      mpz_clear (zi);
      return inexact;
    }

  /* Special case (+/-2^b)^Y which could be exact. If x is negative, then
     necessarily y is a large integer. */
  {
    mpfr_exp_t b = MPFR_GET_EXP (x) - 1;

    MPFR_ASSERTN (b >= LONG_MIN && b <= LONG_MAX);  /* FIXME... */
    if (mpfr_cmp_si_2exp (x, MPFR_SIGN(x), b) == 0)
      {
        mpfr_t tmp;
        int sgnx = MPFR_SIGN (x);

        MPFR_LOG_MSG (("special case (+/-2^b)^Y\n", 0));
        /* now x = +/-2^b, so x^y = (+/-1)^y*2^(b*y) is exact whenever b*y is
           an integer */
        MPFR_SAVE_EXPO_MARK (expo);
        mpfr_init2 (tmp, MPFR_PREC (y) + sizeof (long) * CHAR_BIT);
        inexact = mpfr_mul_si (tmp, y, b, MPFR_RNDN); /* exact */
        MPFR_ASSERTN (inexact == 0);
        /* Note: as the exponent range has been extended, an overflow is not
           possible (due to basic overflow and underflow checking above, as
           the result is ~ 2^tmp), and an underflow is not possible either
           because b is an integer (thus either 0 or >= 1). */
        MPFR_CLEAR_FLAGS ();
        inexact = mpfr_exp2 (z, tmp, rnd_mode);
        mpfr_clear (tmp);
        if (sgnx < 0 && is_odd (y))
          {
            mpfr_neg (z, z, rnd_mode);
            inexact = -inexact;
          }
        /* Without the following, the overflows3 test in tpow.c fails. */
        MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
        MPFR_SAVE_EXPO_FREE (expo);
        return mpfr_check_range (z, inexact, rnd_mode);
      }
  }

  MPFR_SAVE_EXPO_MARK (expo);

  /* Case where |y * log(x)| is very small. Warning: x can be negative, in
     that case y is a large integer. */
  {
    mpfr_t t;
    mpfr_exp_t err;

    /* We need an upper bound on the exponent of y * log(x). */
    mpfr_init2 (t, 16);
    if (MPFR_IS_POS(x))
      mpfr_log (t, x, cmp_x_1 < 0 ? MPFR_RNDD : MPFR_RNDU); /* away from 0 */
    else
      {
        /* if x < -1, round to +Inf, else round to zero */
        mpfr_neg (t, x, (mpfr_cmp_si (x, -1) < 0) ? MPFR_RNDU : MPFR_RNDD);
        mpfr_log (t, t, (mpfr_cmp_ui (t, 1) < 0) ? MPFR_RNDD : MPFR_RNDU);
      }
    MPFR_ASSERTN (MPFR_IS_PURE_FP (t));
    err = MPFR_GET_EXP (y) + MPFR_GET_EXP (t);
    mpfr_clear (t);
    MPFR_CLEAR_FLAGS ();
    MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (z, __gmpfr_one, - err, 0,
                                      (MPFR_SIGN (y) > 0) ^ (cmp_x_1 < 0),
                                      rnd_mode, expo, {});
  }

  /* General case */
  inexact = mpfr_pow_general (z, x, y, rnd_mode, y_is_integer, &expo);

  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (z, inexact, rnd_mode);
}
コード例 #18
0
ファイル: pow.c プロジェクト: Distrotech/mpfr
/* 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;
}
コード例 #19
0
ファイル: log2.c プロジェクト: 119/aircam-openwrt
int
mpfr_log2 (mpfr_ptr r, mpfr_srcptr a, mpfr_rnd_t rnd_mode)
{
  int inexact;
  MPFR_SAVE_EXPO_DECL (expo);

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a)))
    {
      /* If a is NaN, the result is NaN */
      if (MPFR_IS_NAN (a))
        {
          MPFR_SET_NAN (r);
          MPFR_RET_NAN;
        }
      /* check for infinity before zero */
      else if (MPFR_IS_INF (a))
        {
          if (MPFR_IS_NEG (a))
            /* log(-Inf) = NaN */
            {
              MPFR_SET_NAN (r);
              MPFR_RET_NAN;
            }
          else /* log(+Inf) = +Inf */
            {
              MPFR_SET_INF (r);
              MPFR_SET_POS (r);
              MPFR_RET (0);
            }
        }
      else /* a is zero */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (a));
          MPFR_SET_INF (r);
          MPFR_SET_NEG (r);
          MPFR_RET (0); /* log2(0) is an exact -infinity */
        }
    }

  /* If a is negative, the result is NaN */
  if (MPFR_UNLIKELY (MPFR_IS_NEG (a)))
    {
      MPFR_SET_NAN (r);
      MPFR_RET_NAN;
    }

  /* If a is 1, the result is 0 */
  if (MPFR_UNLIKELY (mpfr_cmp_ui (a, 1) == 0))
    {
      MPFR_SET_ZERO (r);
      MPFR_SET_POS (r);
      MPFR_RET (0); /* only "normal" case where the result is exact */
    }

  /* If a is 2^N, log2(a) is exact*/
  if (MPFR_UNLIKELY (mpfr_cmp_ui_2exp (a, 1, MPFR_GET_EXP (a) - 1) == 0))
    return mpfr_set_si(r, MPFR_GET_EXP (a) - 1, rnd_mode);

  MPFR_SAVE_EXPO_MARK (expo);

  /* General case */
  {
    /* Declaration of the intermediary variable */
    mpfr_t t, tt;
    /* Declaration of the size variable */
    mpfr_prec_t Ny = MPFR_PREC(r);              /* target precision */
    mpfr_prec_t Nt;                             /* working precision */
    mpfr_exp_t err;                             /* error */
    MPFR_ZIV_DECL (loop);

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

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

    /* First computation of log2 */
    MPFR_ZIV_INIT (loop, Nt);
    for (;;)
      {
        /* compute log2 */
        mpfr_const_log2(t,MPFR_RNDD); /* log(2) */
        mpfr_log(tt,a,MPFR_RNDN);     /* log(a) */
        mpfr_div(t,tt,t,MPFR_RNDN); /* log(a)/log(2) */

        /* estimation of the error */
        err = Nt-3;
        if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
          break;

        /* actualisation of the precision */
        MPFR_ZIV_NEXT (loop, Nt);
        mpfr_set_prec (t, Nt);
        mpfr_set_prec (tt, Nt);
      }
    MPFR_ZIV_FREE (loop);

    inexact = mpfr_set (r, t, rnd_mode);

    mpfr_clear (t);
    mpfr_clear (tt);
  }

  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (r, inexact, rnd_mode);
}
コード例 #20
0
int main()
{
    slong iter;
    flint_rand_t state;

    flint_printf("d_log_upper_bound....");
    fflush(stdout);

    flint_randinit(state);

    for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++)
    {
        mpfr_t t;
        double x, y, z;

        mpfr_init2(t, 53);

        x = d_randtest2(state);
        x = ldexp(x, 100 - n_randint(state, 200));

        switch (n_randint(state, 10))
        {
            case 0:
                x = 1.0 + x;
                break;
            case 1:
                x = 1.0 - x;
                break;
            case 2:
                x = D_INF;
                break;
            case 3:
                x = 0.0;
                break;
            case 4:
                x = D_NAN;
                break;
            default:
                break;
        }

        y = mag_d_log_upper_bound(x);

        mpfr_set_d(t, x, MPFR_RNDD);
        mpfr_log(t, t, MPFR_RNDU);
        z = mpfr_get_d(t, MPFR_RNDD);

        if (y < z || fabs(y-z) > 0.000001 * fabs(z))
        {
            flint_printf("FAIL\n");
            flint_printf("x = %.20g\n", x);
            flint_printf("y = %.20g\n", y);
            flint_printf("z = %.20g\n", z);
            flint_abort();
        }

        mpfr_clear(t);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
コード例 #21
0
ファイル: t-log.c プロジェクト: argriffing/arb
int main()
{
    slong iter;
    flint_rand_t state;

    flint_printf("log....");
    fflush(stdout);

    flint_randinit(state);

    /* compare with mpfr */
    for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++)
    {
        arb_t a, b;
        fmpq_t q;
        mpfr_t t;
        slong prec = 2 + n_randint(state, 200);

        arb_init(a);
        arb_init(b);
        fmpq_init(q);
        mpfr_init2(t, prec + 100);

        do {
            arb_randtest(a, state, 1 + n_randint(state, 200), 10);
        } while (arb_contains_nonpositive(a));

        arb_randtest(b, state, 1 + n_randint(state, 200), 10);
        arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200));

        fmpq_get_mpfr(t, q, MPFR_RNDN);

        /* todo: estimate cancellation precisely */
        if (mpfr_cmp_d(t, 1 - 1e-10) > 0 && mpfr_cmp_d(t, 1 + 1e-10) < 0)
        {
            mpfr_set_prec(t, prec + 1000);
            fmpq_get_mpfr(t, q, MPFR_RNDN);
        }

        mpfr_log(t, t, MPFR_RNDN);

        arb_log(b, a, prec);

        if (!arb_contains_mpfr(b, t))
        {
            flint_printf("FAIL: containment\n\n");
            flint_printf("a = "); arb_print(a); flint_printf("\n\n");
            flint_printf("b = "); arb_print(b); flint_printf("\n\n");
            abort();
        }

        arb_log(a, a, prec);

        if (!arb_equal(a, b))
        {
            flint_printf("FAIL: aliasing\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        fmpq_clear(q);
        mpfr_clear(t);
    }

    /* compare with mpfr (higher precision) */
    for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
    {
        arb_t a, b;
        fmpq_t q;
        mpfr_t t;
        slong prec = 2 + n_randint(state, 6000);

        arb_init(a);
        arb_init(b);
        fmpq_init(q);
        mpfr_init2(t, prec + 100);

        do {
            arb_randtest(a, state, 1 + n_randint(state, 6000), 10);
        } while (arb_contains_nonpositive(a));

        arb_randtest(b, state, 1 + n_randint(state, 6000), 10);
        arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200));

        fmpq_get_mpfr(t, q, MPFR_RNDN);

        /* todo: estimate cancellation precisely */
        if (mpfr_cmp_d(t, 1 - 1e-10) > 0 && mpfr_cmp_d(t, 1 + 1e-10) < 0)
        {
            mpfr_set_prec(t, prec + 10000);
            fmpq_get_mpfr(t, q, MPFR_RNDN);
        }

        mpfr_log(t, t, MPFR_RNDN);

        arb_log(b, a, prec);

        if (!arb_contains_mpfr(b, t))
        {
            flint_printf("FAIL: containment\n\n");
            flint_printf("a = "); arb_print(a); flint_printf("\n\n");
            flint_printf("b = "); arb_print(b); flint_printf("\n\n");
            abort();
        }

        arb_log(a, a, prec);

        if (!arb_equal(a, b))
        {
            flint_printf("FAIL: aliasing\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        fmpq_clear(q);
        mpfr_clear(t);
    }

    /* test large numbers */
    for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++)
    {
        arb_t a, b, ab, lab, la, lb, lalb;
        slong prec = 2 + n_randint(state, 6000);

        arb_init(a);
        arb_init(b);
        arb_init(ab);
        arb_init(lab);
        arb_init(la);
        arb_init(lb);
        arb_init(lalb);

        arb_randtest(a, state, 1 + n_randint(state, 400), 400);
        arb_randtest(b, state, 1 + n_randint(state, 400), 400);

        arb_log(la, a, prec);
        arb_log(lb, b, prec);
        arb_mul(ab, a, b, prec);
        arb_log(lab, ab, prec);
        arb_add(lalb, la, lb, prec);

        if (!arb_overlaps(lab, lalb))
        {
            flint_printf("FAIL: containment\n\n");
            flint_printf("a = "); arb_print(a); flint_printf("\n\n");
            flint_printf("b = "); arb_print(b); flint_printf("\n\n");
            flint_printf("la = "); arb_print(la); flint_printf("\n\n");
            flint_printf("lb = "); arb_print(lb); flint_printf("\n\n");
            flint_printf("ab = "); arb_print(ab); flint_printf("\n\n");
            flint_printf("lab = "); arb_print(lab); flint_printf("\n\n");
            flint_printf("lalb = "); arb_print(lalb); flint_printf("\n\n");
            abort();
        }

        arb_log(a, a, prec);
        if (!arb_overlaps(a, la))
        {
            flint_printf("FAIL: aliasing\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        arb_clear(ab);
        arb_clear(lab);
        arb_clear(la);
        arb_clear(lb);
        arb_clear(lalb);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
コード例 #22
0
int
main (int argc, char *argv[])
{
  int n, prec, st, st2, N, i;
  mpfr_t x, y, z;
  
  if (argc != 2 && argc != 3)
    {
      fprintf(stderr, "Usage: timing digits \n");
      exit(1);
    }

  printf ("Using MPFR-%s with GMP-%s\n", mpfr_version, gmp_version);
  n = atoi(argv[1]);
  prec = (int) ( n * log(10.0) / log(2.0) + 1.0 );
  printf("[precision is %u bits]\n", prec);
 
  mpfr_init2(x, prec); mpfr_init2(y, prec); mpfr_init2(z, prec); 

  mpfr_set_d(x, 3.0, GMP_RNDN); mpfr_sqrt(x, x, GMP_RNDN); mpfr_sub_ui (x, x, 1, GMP_RNDN);
  mpfr_set_d(y, 5.0, GMP_RNDN); mpfr_sqrt(y, y, GMP_RNDN);

  mpfr_log (z, x, GMP_RNDN);

  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_mul(z, x, y, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000); 	  
  printf("x*y        took %f ms (%d eval in %d ms)\n", 
	 (double)(st2-st)/(N-1),N-1,st2-st);

  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_mul(z, x, x, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000); 	  
  printf("x*x        took %f ms (%d eval in %d ms)\n", 
	 (double)(st2-st)/(N-1),N-1,st2-st);

  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_div(z, x, y, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000); 	  
  printf("x/y        took %f ms (%d eval in %d ms)\n", 
	 (double)(st2-st)/(N-1),N-1,st2-st);
  
  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_sqrt(z, x, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000); 	  
  printf("sqrt(x)    took %f ms (%d eval in %d ms)\n", 
	 (double)(st2-st)/(N-1),N-1,st2-st);
  
  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_exp(z, x, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000); 	  
  printf("exp(x)     took %f ms (%d eval in %d ms)\n", 
	 (double)(st2-st)/(N-1),N-1,st2-st);
  
  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_log(z, x, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000); 	  
  printf("log(x)     took %f ms (%d eval in %d ms)\n", 
	 (double)(st2-st)/(N-1),N-1,st2-st);
  
  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_sin(z, x, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000); 	  
  printf("sin(x)     took %f ms (%d eval in %d ms)\n", 
	 (double)(st2-st)/(N-1),N-1,st2-st);
  
  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_cos(z, x, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000);
  printf("cos(x)     took %f ms (%d eval in %d ms)\n",
         (double)(st2-st)/(N-1),N-1,st2-st);

  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_acos(z, x, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000);
  printf("arccos(x)  took %f ms (%d eval in %d ms)\n",
         (double)(st2-st)/(N-1),N-1,st2-st);
  
  N=1;  st = cputime();
  do {
    for (i=0;i<N;i++) mpfr_atan(z, x, GMP_RNDN);
    N=2*N;
    st2=cputime();
  } while (st2-st<1000);
  printf("arctan(x)  took %f ms (%d eval in %d ms)\n",
         (double)(st2-st)/(N-1),N-1,st2-st);

  mpfr_clear(x); mpfr_clear(y); mpfr_clear(z);
  return 0;
}
コード例 #23
0
/******************************************************************************
One forward-backward pass through a minimum-duration HMM model with a
single Gaussian in each of the states. T: totalFeatures
*******************************************************************************/
double ESHMM::mdHMMLogForwardBackward(ESHMM *mdHMM, VECTOR_OF_F_VECTORS *features, double **post, int T, mat &gamma, rowvec &gamma1,
			     mat &sumxi){
  printf("forward backward algorithm calculation in progress...\n");
  int i = 0, j = 0 , k = 0;
  /* total no of states is much larger, instead of number of pdfs we have to extend 
   states by Min_DUR, therefore total states = Q * MD */
  int Q = mdHMM->hmmStates;
  int Qmd = Q * MIN_DUR;
  mat logalpha(T, Qmd); // forward probability matrix
  mat logbeta(T, Qmd); // backward probability matrix
  mat logg(T, Qmd);  // loggamma 
  mat m(Q, 1);
  mat logA(Qmd, Qmd);  /// transition matrix is already in logarithm
  mat new_logp(T, Qmd); // after replication for each substates
  mat logp_k(Q, T);  // we have single cluster only, probability of each feature corresponding to each cluster
  
  printf("Q: %d  Qmd: %d\n", Q, Qmd);
  for(i = 0; i < Qmd; i++){
    for(j = 0; j < Qmd; j++){
      logA(i, j) = mdHMM->trans[i]->array[j];
    }
  }
  
  // minimum duration viterbi hence modify B(posterior) prob matrix
  
  for(i = 0; i < Q; i++)
    for(j = 0; j < T; j++){
      logp_k(i, j) = post[i][j];
    }
  
  for(i = 0; i < Q; i++){
    m(i, 0) = 1;
    for(j = 0; j < T; j++)
      logp_k(i, j) = 0.0; // since  we have only one cluster so cluster probability and 
    // total probability is same. Hence subtracting cluster probability from total probability would make it zero.
  }
  
  // modifying logp matrix according to minimum duration
  for(i = 0; i < Q; i++){
    for(j = 0; j < T; j++){
      for(k = i*MIN_DUR; k < (i+1)*MIN_DUR; k++){
	new_logp(j, k) = post[i][j];
      }
    }
  }
  /* forward initialization */
  // for summing log probabilties, first sum probs and then take logarithm
  printf("forward initialization...\n\n");
  for(i = 0; i < Qmd; i++){
    logalpha(0, i) = mdHMM->prior->array[i] + new_logp(0, i) ;
  }
  ///print logalpha after initialization
  for(i = 0; i < Qmd; i++)
    printf("%lf ", logalpha(0, i));
  
  /* forward induction */
  printf("forward induction in progress...\n");
  int t = 0;  
  
  mpfr_t summation3;
  mpfr_init(summation3);
  mpfr_t var11, var21;
  mpfr_init(var11);
  mpfr_init(var21);
  mpfr_set_d(var11, 0.0, MPFR_RNDN);
  mpfr_set_d(var21, 0.0, MPFR_RNDN);
  mpfr_set_d(summation3, 0.0, MPFR_RNDN);
  
  for(t = 1; t < T; t++){
    //printf("%d ", t);
    for(j = 0; j < Qmd; j++){
      vec v1(Qmd), v2(Qmd);      vec v3(Qmd);  
      //first find logalpha vector
      for(i = 0; i < Qmd; i++)
	v1(i) = logalpha(t-1, i);
      // if(t < 20)
      // 	v1.print("v1:\n");
      
      // extract transition probability vector
      for(i = 0; i < Qmd; i++)
	v2(i) = logA(i, j);
      // if(t < 20)
      // 	v2.print("v2:\n");
      // Now sum both the vectors into one
      for(i = 0; i < Qmd; i++)
	v3(i) = v1(i) + v2(i);
            
      double *temp = (double *)calloc(Qmd, sizeof(double ));
      for(i = 0; i < Qmd; i++)
	temp[i] = v3(i);
      // if(t < 20)
      // 	v3.print("v3:\n");
      //printf("printed\n");
      // now sum over whole column vector      
      mpfr_set_d(summation3, 0.0, MPFR_RNDN);
      // take the exponentiation and summation in one loop 
      
      // getting double from mpfr variable
      /// double mpfr_get_d(mpfr_t op, mpfr_rnd_t rnd);      
      //mpfr_set_d(var1, 0.0, MPFR_RNDD);
      //mpfr_set_d(var2, 0.0, MPFR_RNDD);
      // now take the exponentiation
      for(i = 0; i < Qmd; i++){
	double elem = temp[i];
	mpfr_set_d(var21, elem, MPFR_RNDD);
	//mpfr_printf("var2: %lf\n", var21);
	mpfr_exp(var11, var21, MPFR_RNDD); ///take exp(v2) and store in v1 
	// take sum of all elements in total  
	mpfr_add(summation3, summation3, var11, MPFR_RNDD); // add summation and v1
      }
      
      // now take the logarithm of sum 
      mpfr_log(summation3, summation3, MPFR_RNDD);
      // now convert this sum to double
      double sum2 = mpfr_get_d(summation3, MPFR_RNDD);
      // now assign this double to logalpha
      
      // now add logp(t, j)      
      sum2 += new_logp(t, j);
      // if(t < 20)
      // 	printf("sum: %lf\n", sum2);
      logalpha(t, j) = sum2;
      /// clear mpfr variables      
    }
    if(t < 20){
      printf("logalpha:\n");
      for(j = 0; j < Qmd; j++)
	printf("%lf ", logalpha(t, j));
      printf("\n");
    }
  }  // close the forward induction loop   
  mpfr_clear(var11);
  mpfr_clear(var21);
  mpfr_clear(summation3);
  
  /* forward termination */
  double ll = 0; // total log likelihood of all observation given this HMM
  for(i = 0; i < Qmd; i++){
    ll += logalpha(T-1, i);
  }
  ///===================================================================
  // for(i = 0; i < 100; i++){
  //   for(j = 0; j < Qmd; j++)
  //     printf("%lf ", logalpha(i, j));
  //   printf("\n");
  // }
  printf("\nprinting last column of logalpha...\n");
  for(i = 1; i < 6; i++){
    for(j = 0; j < Qmd; j++)
      printf("%lf ", logalpha(T-i, j));
    printf("\n");
  }
  printf("total loglikelihood: %lf\n", ll);
  ///===================================================================  
  double sum = 0;
  /* calculate logalpha last row sum */  
  for(i = 0; i < Qmd; i++)
    sum += logalpha(T-1, i);
  ll = sum;
  printf("LL: %lf........\n", ll);
  
  /* backward initilization */
  /// intialize mpfr variables  
  mpfr_t summation;
  mpfr_init(summation);
  mpfr_t var1, var2;
  mpfr_init(var1);
  mpfr_init(var2);
  mpfr_set_d(summation, 0.0, MPFR_RNDN);
  mpfr_set_d(var1, 0.0, MPFR_RNDN);
  mpfr_set_d(var2, 0.0, MPFR_RNDN);
  
  printf("backward initialization...\n");
  mpfr_set_d(summation, 0.0, MPFR_RNDN);
  double *temp = (double *)calloc(Qmd, sizeof(double ));
  
  for(i = 0; i < Qmd; i++)
    temp[i] = logalpha(T-1, i);
  
  for(i = 0; i < Qmd; i++){
    //double elem = logalpha(T-1, i);
    double elem = temp[i-1];
    mpfr_set_d(var2, elem, MPFR_RNDN);
    mpfr_exp(var1, var2, MPFR_RNDN);
    mpfr_add(summation, summation, var1, MPFR_RNDN);
  }
  // take logarithm
  mpfr_log(summation, summation, MPFR_RNDN);
  double sum2 = mpfr_get_d(summation, MPFR_RNDN);
  for(i = 0; i < Qmd; i++){    
    logg(T-1, i) = logalpha(T-1, i) - sum2 ;
  }

  // gamma matrix
  for(j = 0; j < Q; j++){
    gamma(j, T-1) = exp(logp_k(j, T-1) + logg(T-1, j));
  }
  mat lognewxi(Qmd, Qmd); // declare lognewxi matrix 
  /* backward induction */
  printf("backward induction in progress...\n");
  for(t = T-2; t >= 0 ; t--){
    for(j = 0; j < Qmd; j++){
      vec v1(Qmd);
      vec v2(Qmd);
      vec v3(Qmd);
      sum = 0;
      for(i = 0; i < Qmd; i++)
	v1(i) = logA(j, i);
      for(i = 0; i < Qmd; i++)
	v2(i) = logbeta(t+1, i);
      for(i = 0; i < Qmd; i++)
	v3(i) = new_logp(t+1, i);
      // add all three vectors
      for(i = 0; i < Qmd; i++)
	v1(i) += v2(i) + v3(i);
      mpfr_set_d(summation, 0.0, MPFR_RNDN);
      for(i = 0; i < Qmd; i++){
	double elem = v1(i);
	mpfr_set_d(var2, elem, MPFR_RNDN);
	mpfr_exp(var1, var2, MPFR_RNDN);
	mpfr_add(summation, summation, var1, MPFR_RNDN);
      }      
      mpfr_log(summation, summation, MPFR_RNDN);
      sum2 = mpfr_get_d(summation, MPFR_RNDN);
      logbeta(t, j) = sum2;
    }

    // computation of log(gamma) is now possible called logg here
    for(i = 0; i < Qmd; i++){
      logg(t, i) = logalpha(t, i) + logbeta(t, i);
    }
    mpfr_set_d(summation, 0.0, MPFR_RNDN);
    for(i = 0; i < Qmd; i++){
      double elem = logg(t, i);
      mpfr_set_d(var2, elem, MPFR_RNDN);
      mpfr_exp(var1, var2, MPFR_RNDN);
      mpfr_add(summation, summation, var1, MPFR_RNDN);
    }
    mpfr_log(summation, summation, MPFR_RNDN);
    sum2 = mpfr_get_d(summation, MPFR_RNDN);
    for(i = 0; i < Qmd; i++)
      logg(t, i) = logg(t, i) - sum2;
    
    // finally the gamma_k is computed (called gamma here )
    mpfr_set_d(summation, 0.0, MPFR_RNDN);
    for(j = 0; j < Q; j++){
      // for(i = j*MIN_DUR; i < (j+1) * MIN_DUR; i++){
      // 	sum += exp(logg(t, i));
      // }
      gamma(j, t) = exp( logp_k(j, t) + logg(t, j) );
    }    
    /* for the EM algorithm we need the sum
       over xi all over t */
    // replicate logalpha(t, :)' matrix along columns
    mat m1(Qmd, Qmd);
    for(i = 0; i < Qmd; i++){
      for(j = 0; j < Qmd; j++){
	m1(i, j) = logalpha(t, i);
      }
    }
    // replicate logbeta matrix
    vec v1(Qmd);
    for(i = 0; i < Qmd; i++)
      v1(i) = logbeta(t+1, i);
    vec v2(Qmd);
    for(i = 0; i < Qmd; i++)
      v2(i) = new_logp(t+1, i);
    vec v3(Qmd);
    for(i = 0; i < Qmd; i++)
      v3(i) = v1(i) + v2(i);
    // replicate v3 row vector along all rows of matrix m2
    mat m2(Qmd, Qmd);
    for(i = 0; i < Qmd; i++){
      for(j = 0; j < Qmd; j++){
	m2(i, j) = v3(i);
      }
    }
    
    // add both matrices m1 and m2 
    mat m3(Qmd, Qmd);
    m3 = m1 + m2;  // can do direct addition   
    ///mat lognewxi(Qmd, Qmd); // declare lognewxi matrix 
    lognewxi.zeros();
    lognewxi = m3 + logA;
    // add new sum to older sumxi
    /// first subtract total sum from lognewxi
    mpfr_set_d(summation, 0.0, MPFR_RNDN);
    for(i = 0; i < Qmd; i++){
      for(j = 0; j < Qmd; j++){
	double elem = lognewxi(i, j);
	mpfr_set_d(var2, elem, MPFR_RNDN);
	mpfr_exp(var1, var2, MPFR_RNDN);
	mpfr_add(summation, summation, var1, MPFR_RNDN);	
	//sum += exp(lognewxi(i, j));
      }
    }
    // now take the logarithm of sum
    mpfr_log(summation, summation, MPFR_RNDN);
    sum2 = mpfr_get_d(summation, MPFR_RNDN);
    // subtract sum from lognewxi
    for(i = 0; i < Qmd; i++){
      for(j = 0; j < Qmd; j++){
	lognewxi(i, j) = lognewxi(i, j) - sum2;
      }
    }
    mat newxi(Qmd, Qmd);
    newxi = lognewxi;
    // add sumxi and newlogsumxi
    /// take exponential of each element
    for(i = 0; i < Qmd; i++){
      for(j = 0; j < Qmd; j++){
	newxi(i, j) = exp(newxi(i, j));
      }
    }
    sumxi = sumxi + newxi;
  } // close the backward induction loop 
  
  /* handle annoying numerics */
  /// calculate sum of lognewxi along each row (lognewxi is already modified in our case)
  
  for(i = 0; i < Qmd; i++){
    mpfr_set_d(summation, 0.0, MPFR_RNDN);
    for(j = 0; j < Qmd; j++){
      //sum += lognewxi(i, j);
      double elem = lognewxi(i, j);
      mpfr_set_d(var2, elem, MPFR_RNDN);
      mpfr_exp(var1, var2, MPFR_RNDN);
      mpfr_add(summation, summation, var1, MPFR_RNDN);
    }
    sum2 = mpfr_get_d(summation, MPFR_RNDN);
    gamma1(i) = sum2;
  }
  // normalize gamma1 which is prior and normalize sumxi which is transition matrix
  sum = 0;
  for(i = 0; i < Qmd; i++)
    sum += gamma1(i);
  for(i = 0; i < Qmd; i++)
    gamma1(i) /= sum;  
  // transition probability matrix will be normalized in train_hmm function
  
  /// clear mpfr variables
  mpfr_clear(summation);
  mpfr_clear(var1);
  mpfr_clear(var2);
  printf("forward-backward algorithm calculation is done...\n");
  /* finished forward-backward algorithm */    
  return ll;
}
コード例 #24
0
ファイル: t-log_tab.c プロジェクト: fredrik-johansson/arb
int main()
{
    slong i;

    mpfr_t tabx, logx, y1, y2;
    mpz_t tt;

    flint_printf("log_tab....");
    fflush(stdout);

    {
        slong prec, bits, num;

        prec = ARB_LOG_TAB1_LIMBS * FLINT_BITS;
        bits = ARB_LOG_TAB11_BITS;
        num = 1 << ARB_LOG_TAB11_BITS;

        mpfr_init2(tabx, prec);
        mpfr_init2(logx, prec);
        mpfr_init2(y1, prec);
        mpfr_init2(y2, prec);

        for (i = 0; i < num; i++)
        {
            tt->_mp_d = (mp_ptr) arb_log_tab11[i];
            tt->_mp_size = prec / FLINT_BITS;
            tt->_mp_alloc = tt->_mp_size;

            while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0)
                tt->_mp_size--;

            mpfr_set_z(tabx, tt, MPFR_RNDD);
            mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD);

            mpfr_set_ui(logx, i, MPFR_RNDD);
            mpfr_div_2ui(logx, logx, bits, MPFR_RNDD);
            mpfr_add_ui(logx, logx, 1, MPFR_RNDD);
            mpfr_log(logx, logx, MPFR_RNDD);

            mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD);
            mpfr_floor(y1, y1);
            mpfr_div_2ui(y1, y1, prec, MPFR_RNDD);

            mpfr_mul_2ui(y2, logx, prec, MPFR_RNDD);
            mpfr_floor(y2, y2);
            mpfr_div_2ui(y2, y2, prec, MPFR_RNDD);

            if (!mpfr_equal_p(y1, y2))
            {
                flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec);
                mpfr_printf("y1 = %.1500Rg\n", y1);
                mpfr_printf("y2 = %.1500Rg\n", y2);
                flint_abort();
            }
        }

        mpfr_clear(tabx);
        mpfr_clear(logx);
        mpfr_clear(y1);
        mpfr_clear(y2);
    }

    {
        slong prec, bits, num;

        prec = ARB_LOG_TAB1_LIMBS * FLINT_BITS;
        bits = ARB_LOG_TAB11_BITS + ARB_LOG_TAB12_BITS;
        num = 1 << ARB_LOG_TAB12_BITS;

        mpfr_init2(tabx, prec);
        mpfr_init2(logx, prec);
        mpfr_init2(y1, prec);
        mpfr_init2(y2, prec);

        for (i = 0; i < num; i++)
        {
            tt->_mp_d = (mp_ptr) arb_log_tab12[i];
            tt->_mp_size = prec / FLINT_BITS;
            tt->_mp_alloc = tt->_mp_size;

            while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0)
                tt->_mp_size--;

            mpfr_set_z(tabx, tt, MPFR_RNDD);
            mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD);

            mpfr_set_ui(logx, i, MPFR_RNDD);
            mpfr_div_2ui(logx, logx, bits, MPFR_RNDD);
            mpfr_add_ui(logx, logx, 1, MPFR_RNDD);
            mpfr_log(logx, logx, MPFR_RNDD);

            mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD);
            mpfr_floor(y1, y1);
            mpfr_div_2ui(y1, y1, prec, MPFR_RNDD);

            mpfr_mul_2ui(y2, logx, prec, MPFR_RNDD);
            mpfr_floor(y2, y2);
            mpfr_div_2ui(y2, y2, prec, MPFR_RNDD);

            if (!mpfr_equal_p(y1, y2))
            {
                flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec);
                mpfr_printf("y1 = %.1500Rg\n", y1);
                mpfr_printf("y2 = %.1500Rg\n", y2);
                flint_abort();
            }
        }

        mpfr_clear(tabx);
        mpfr_clear(logx);
        mpfr_clear(y1);
        mpfr_clear(y2);
    }

    {
        slong prec, bits, num;

        prec = ARB_LOG_TAB2_LIMBS * FLINT_BITS;
        bits = ARB_LOG_TAB21_BITS;
        num = 1 << ARB_LOG_TAB21_BITS;

        mpfr_init2(tabx, prec);
        mpfr_init2(logx, prec);
        mpfr_init2(y1, prec);
        mpfr_init2(y2, prec);

        for (i = 0; i < num; i++)
        {
            tt->_mp_d = (mp_ptr) arb_log_tab21[i];
            tt->_mp_size = prec / FLINT_BITS;
            tt->_mp_alloc = tt->_mp_size;

            while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0)
                tt->_mp_size--;

            mpfr_set_z(tabx, tt, MPFR_RNDD);
            mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD);

            mpfr_set_ui(logx, i, MPFR_RNDD);
            mpfr_div_2ui(logx, logx, bits, MPFR_RNDD);
            mpfr_add_ui(logx, logx, 1, MPFR_RNDD);
            mpfr_log(logx, logx, MPFR_RNDD);

            mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD);
            mpfr_floor(y1, y1);
            mpfr_div_2ui(y1, y1, prec, MPFR_RNDD);

            mpfr_mul_2ui(y2, logx, prec, MPFR_RNDD);
            mpfr_floor(y2, y2);
            mpfr_div_2ui(y2, y2, prec, MPFR_RNDD);

            if (!mpfr_equal_p(y1, y2))
            {
                flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec);
                mpfr_printf("y1 = %.1500Rg\n", y1);
                mpfr_printf("y2 = %.1500Rg\n", y2);
                flint_abort();
            }
        }

        mpfr_clear(tabx);
        mpfr_clear(logx);
        mpfr_clear(y1);
        mpfr_clear(y2);
    }

    {
        slong prec, bits, num;

        prec = ARB_LOG_TAB2_LIMBS * FLINT_BITS;
        bits = ARB_LOG_TAB21_BITS + ARB_LOG_TAB22_BITS;
        num = 1 << ARB_LOG_TAB22_BITS;

        mpfr_init2(tabx, prec);
        mpfr_init2(logx, prec);
        mpfr_init2(y1, prec);
        mpfr_init2(y2, prec);

        for (i = 0; i < num; i++)
        {
            tt->_mp_d = (mp_ptr) arb_log_tab22[i];
            tt->_mp_size = prec / FLINT_BITS;
            tt->_mp_alloc = tt->_mp_size;

            while (tt->_mp_size > 0 && tt->_mp_d[tt->_mp_size-1] == 0)
                tt->_mp_size--;

            mpfr_set_z(tabx, tt, MPFR_RNDD);
            mpfr_div_2ui(tabx, tabx, prec, MPFR_RNDD);

            mpfr_set_ui(logx, i, MPFR_RNDD);
            mpfr_div_2ui(logx, logx, bits, MPFR_RNDD);
            mpfr_add_ui(logx, logx, 1, MPFR_RNDD);
            mpfr_log(logx, logx, MPFR_RNDD);

            mpfr_mul_2ui(y1, tabx, prec, MPFR_RNDD);
            mpfr_floor(y1, y1);
            mpfr_div_2ui(y1, y1, prec, MPFR_RNDD);

            mpfr_mul_2ui(y2, logx, prec, MPFR_RNDD);
            mpfr_floor(y2, y2);
            mpfr_div_2ui(y2, y2, prec, MPFR_RNDD);

            if (!mpfr_equal_p(y1, y2))
            {
                flint_printf("FAIL: i = %wd, bits = %wd, prec = %wd\n", i, bits, prec);
                mpfr_printf("y1 = %.1500Rg\n", y1);
                mpfr_printf("y2 = %.1500Rg\n", y2);
                flint_abort();
            }
        }

        mpfr_clear(tabx);
        mpfr_clear(logx);
        mpfr_clear(y1);
        mpfr_clear(y2);
    }

    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
コード例 #25
0
ファイル: integral_decomp.c プロジェクト: tohtsky/cboot
mpfr_t* double_pole_case_c(long pole_order_max, mpfr_t base, mpfr_t pole_position, mpfr_t incomplete_gamma_factor, mpfr_prec_t prec){ 

	mpfr_t* result=malloc(sizeof(mpfr_t)*(pole_order_max+1)); 

	mpfr_t temp1;
	mpfr_init2(temp1,prec);

	mpfr_t double_pole_integral;
	mpfr_init2(double_pole_integral,prec); 

	mpfr_t temp2;
	mpfr_init2(temp2,prec); 

	mpfr_t minus_pole_position;
	mpfr_init2(minus_pole_position,prec); 
	mpfr_neg(minus_pole_position,pole_position,MPFR_RNDN);

//	mpfr_t factorial;
//	mpfr_init2(factorial,prec); 
//	mpfr_set_ui(factorial,1,MPFR_RNDN);

	mpfr_t minus_log_base;
	mpfr_init2(minus_log_base,prec); 
	mpfr_log(minus_log_base,base,prec); 
	mpfr_neg(minus_log_base,minus_log_base,MPFR_RNDN);
	mpfr_ui_div(minus_log_base,1,minus_log_base,MPFR_RNDN);

	mpfr_t log_base_power;
	mpfr_init2(log_base_power,prec); 
	mpfr_set(log_base_power,minus_log_base,MPFR_RNDN);

	//mpfr_set_ui(temp1,0,MPFR_RNDN);
	
	//mpfr_mul(double_pole_integral,temp1,incomplete_gamma_factor,MPFR_RNDN); 
	mpfr_log(temp1,base,MPFR_RNDN); 
	mpfr_mul(double_pole_integral,incomplete_gamma_factor,temp1,MPFR_RNDN);
	mpfr_ui_div(temp1,1,minus_pole_position,MPFR_RNDN);
	mpfr_add(double_pole_integral,double_pole_integral,temp1,MPFR_RNDN); 
	//mpfr_printf("before loop: double_pole_integral = %.32RNf\n",double_pole_integral);


	for(int i=0;i<=pole_order_max;i++){
		mpfr_init2(result[i],prec);
		mpfr_set(result[i],double_pole_integral,MPFR_RNDN); 
		if(i<pole_order_max){
			mpfr_mul(double_pole_integral,double_pole_integral,pole_position,MPFR_RNDN); 
		} 
	}

#ifdef debug_mode
	for(int i=0;i<=pole_order_max;i++){
		mpfr_printf("result[%d] = %.16RNf\n",i,result[i],MPFR_RNDN);
	} 
#endif

	mpfr_t * factorial_times_power_lnb;
	mpfr_t * single_pole_coeffs;
	/*
	 * x**1/(x+a)**2 case
	 * */
	
	if(pole_order_max >= 1){ 
		single_pole_coeffs=malloc(sizeof(mpfr_t)*(pole_order_max));
		/*  x^(j+1)=( 
		 *  single_pole_coeffs[0] x^(j-1) + 
		 *  single_pole_coeffs[1] x^(j-2) + ...  +
		 *  single_pole_coeffs[j-1] x^0
		 *  )*(x-a)^2  +
		 *
		 *  single_pole_coeffs[j](x-a) * ((x-a) + a)
		 *
		 *  + a^(j+1)
		 *
		 *  => single_pole_coeffs[j+1]
		 *
		 *  single_pole_coeffs[j+1] = single_pole_coeffs[j]*a + a^j+1
		 * single_pole_coeffs[0] =  
		 * */
		if(pole_order_max>=2){
			factorial_times_power_lnb=malloc(sizeof(mpfr_t)*(pole_order_max-1));
			mpfr_init2(factorial_times_power_lnb[0],prec);
			mpfr_set(factorial_times_power_lnb[0],minus_log_base,MPFR_RNDN);
		}

		mpfr_set(temp1,pole_position,MPFR_RNDN);		
		/* below temp1 is used as pole_position^j*/

		mpfr_init2(single_pole_coeffs[0],prec);
		mpfr_set_ui(single_pole_coeffs[0], 1 ,MPFR_RNDN);
		mpfr_add(result[1],result[1],incomplete_gamma_factor,MPFR_RNDN);
		
		for(int j=1;j<=pole_order_max-1;j++){
			mpfr_init2(single_pole_coeffs[j],prec);
			mpfr_mul(single_pole_coeffs[j],single_pole_coeffs[j-1],pole_position,MPFR_RNDN);
			mpfr_add(single_pole_coeffs[j],single_pole_coeffs[j],temp1,MPFR_RNDN);

			mpfr_mul(temp2,single_pole_coeffs[j],incomplete_gamma_factor,MPFR_RNDN);
			mpfr_add(result[j+1],result[j+1],temp2,MPFR_RNDN);
			if(j<=pole_order_max-2){
				mpfr_init2(factorial_times_power_lnb[j],prec);
				mpfr_mul(temp1,temp1,pole_position,MPFR_RNDN);

				mpfr_mul(factorial_times_power_lnb[j],factorial_times_power_lnb[j-1],minus_log_base,MPFR_RNDN); 
				mpfr_mul_ui(factorial_times_power_lnb[j],factorial_times_power_lnb[j],j,MPFR_RNDN);
			}
		}
	}
#ifdef debug_mode
	for(int j=0;j<=pole_order_max-1;j++){
		mpfr_printf("single_pole_coeffs[%d] = %.16RNf\n",j,single_pole_coeffs[j]);
	}
#endif
#ifdef debug_mode
	for(int j=0;j<=pole_order_max-2;j++){
		mpfr_printf("factorial_times_power_lnb[%d] = %.16RNf\n",j,factorial_times_power_lnb[j]);
	}
#endif
	for(int j=0;j<=pole_order_max-2;j++){
		for(int k=0;k<=j;k++){
			mpfr_mul(temp2,factorial_times_power_lnb[k],single_pole_coeffs[j-k],MPFR_RNDN);
			mpfr_add(result[j+2],result[j+2],temp2,MPFR_RNDN);
		}
	}

	for(int i=0;i<=pole_order_max-1;i++){
		mpfr_clear(single_pole_coeffs[i]);
	}
	for(int i=0;i<=pole_order_max-2;i++){
		mpfr_clear(factorial_times_power_lnb[i]);
	}
	if(pole_order_max > 0){
		free(single_pole_coeffs);
	}
	if(pole_order_max > 1){
		free(factorial_times_power_lnb);
	}
	mpfr_clear(temp1);
	mpfr_clear(double_pole_integral);
	mpfr_clear(temp2);
	mpfr_clear(minus_pole_position);
	//mpfr_clear(factorial);
	mpfr_clear(minus_log_base);
	mpfr_clear(log_base_power);
	return result;
} 
コード例 #26
0
ファイル: digamma.c プロジェクト: epowers/mpfr
/* Put in s an approximation of digamma(x).
   Assumes x >= 2.
   Assumes s does not overlap with x.
   Returns an integer e such that the error is bounded by 2^e ulps
   of the result s.
*/
static mpfr_exp_t
mpfr_digamma_approx (mpfr_ptr s, mpfr_srcptr x)
{
  mpfr_prec_t p = MPFR_PREC (s);
  mpfr_t t, u, invxx;
  mpfr_exp_t e, exps, f, expu;
  mpz_t *INITIALIZED(B);  /* variable B declared as initialized */
  unsigned long n0, n; /* number of allocated B[] */

  MPFR_ASSERTN(MPFR_IS_POS(x) && (MPFR_EXP(x) >= 2));

  mpfr_init2 (t, p);
  mpfr_init2 (u, p);
  mpfr_init2 (invxx, p);

  mpfr_log (s, x, MPFR_RNDN);         /* error <= 1/2 ulp */
  mpfr_ui_div (t, 1, x, MPFR_RNDN);   /* error <= 1/2 ulp */
  mpfr_div_2exp (t, t, 1, MPFR_RNDN); /* exact */
  mpfr_sub (s, s, t, MPFR_RNDN);
  /* error <= 1/2 + 1/2*2^(EXP(olds)-EXP(s)) + 1/2*2^(EXP(t)-EXP(s)).
     For x >= 2, log(x) >= 2*(1/(2x)), thus olds >= 2t, and olds - t >= olds/2,
     thus 0 <= EXP(olds)-EXP(s) <= 1, and EXP(t)-EXP(s) <= 0, thus
     error <= 1/2 + 1/2*2 + 1/2 <= 2 ulps. */
  e = 2; /* initial error */
  mpfr_mul (invxx, x, x, MPFR_RNDZ);     /* invxx = x^2 * (1 + theta)
                                            for |theta| <= 2^(-p) */
  mpfr_ui_div (invxx, 1, invxx, MPFR_RNDU); /* invxx = 1/x^2 * (1 + theta)^2 */

  /* in the following we note err=xxx when the ratio between the approximation
     and the exact result can be written (1 + theta)^xxx for |theta| <= 2^(-p),
     following Higham's method */
  B = mpfr_bernoulli_internal ((mpz_t *) 0, 0);
  mpfr_set_ui (t, 1, MPFR_RNDN); /* err = 0 */
  for (n = 1;; n++)
    {
      /* compute next Bernoulli number */
      B = mpfr_bernoulli_internal (B, n);
      /* The main term is Bernoulli[2n]/(2n)/x^(2n) = B[n]/(2n+1)!(2n)/x^(2n)
         = B[n]*t[n]/(2n) where t[n]/t[n-1] = 1/(2n)/(2n+1)/x^2. */
      mpfr_mul (t, t, invxx, MPFR_RNDU);        /* err = err + 3 */
      mpfr_div_ui (t, t, 2 * n, MPFR_RNDU);     /* err = err + 1 */
      mpfr_div_ui (t, t, 2 * n + 1, MPFR_RNDU); /* err = err + 1 */
      /* we thus have err = 5n here */
      mpfr_div_ui (u, t, 2 * n, MPFR_RNDU);     /* err = 5n+1 */
      mpfr_mul_z (u, u, B[n], MPFR_RNDU);       /* err = 5n+2, and the
                                                   absolute error is bounded
                                                   by 10n+4 ulp(u) [Rule 11] */
      /* if the terms 'u' are decreasing by a factor two at least,
         then the error coming from those is bounded by
         sum((10n+4)/2^n, n=1..infinity) = 24 */
      exps = mpfr_get_exp (s);
      expu = mpfr_get_exp (u);
      if (expu < exps - (mpfr_exp_t) p)
        break;
      mpfr_sub (s, s, u, MPFR_RNDN); /* error <= 24 + n/2 */
      if (mpfr_get_exp (s) < exps)
        e <<= exps - mpfr_get_exp (s);
      e ++; /* error in mpfr_sub */
      f = 10 * n + 4;
      while (expu < exps)
        {
          f = (1 + f) / 2;
          expu ++;
        }
      e += f; /* total rouding error coming from 'u' term */
    }

  n0 = ++n;
  while (n--)
    mpz_clear (B[n]);
  (*__gmp_free_func) (B, n0 * sizeof (mpz_t));

  mpfr_clear (t);
  mpfr_clear (u);
  mpfr_clear (invxx);

  f = 0;
  while (e > 1)
    {
      f++;
      e = (e + 1) / 2;
      /* Invariant: 2^f * e does not decrease */
    }
  return f;
}
コード例 #27
0
ファイル: atanh.c プロジェクト: SESA/EbbRT-mpfr
int
mpfr_atanh (mpfr_ptr y, mpfr_srcptr xt , mpfr_rnd_t rnd_mode)
{
  int inexact;
  mpfr_t x, t, te;
  mpfr_prec_t Nx, Ny, Nt;
  mpfr_exp_t err;
  MPFR_ZIV_DECL (loop);
  MPFR_SAVE_EXPO_DECL (expo);

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

  /* Special cases */
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (xt)))
    {
      /* atanh(NaN) = NaN, and atanh(+/-Inf) = NaN since tanh gives a result
         between -1 and 1 */
      if (MPFR_IS_NAN (xt) || MPFR_IS_INF (xt))
        {
          MPFR_SET_NAN (y);
          MPFR_RET_NAN;
        }
      else /* necessarily xt is 0 */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (xt));
          MPFR_SET_ZERO (y);   /* atanh(0) = 0 */
          MPFR_SET_SAME_SIGN (y,xt);
          MPFR_RET (0);
        }
    }

  /* atanh (x) = NaN as soon as |x| > 1, and arctanh(+/-1) = +/-Inf */
  if (MPFR_UNLIKELY (MPFR_GET_EXP (xt) > 0))
    {
      if (MPFR_GET_EXP (xt) == 1 && mpfr_powerof2_raw (xt))
        {
          MPFR_SET_INF (y);
          MPFR_SET_SAME_SIGN (y, xt);
          mpfr_set_divby0 ();
          MPFR_RET (0);
        }
      MPFR_SET_NAN (y);
      MPFR_RET_NAN;
    }

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

  MPFR_SAVE_EXPO_MARK (expo);

  /* Compute initial precision */
  Nx = MPFR_PREC (xt);
  MPFR_TMP_INIT_ABS (x, xt);
  Ny = MPFR_PREC (y);
  Nt = MAX (Nx, Ny);
  /* the optimal number of bits : see algorithms.ps */
  Nt = Nt + MPFR_INT_CEIL_LOG2 (Nt) + 4;

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

  /* First computation of cosh */
  MPFR_ZIV_INIT (loop, Nt);
  for (;;)
    {
      /* compute atanh */
      mpfr_ui_sub (te, 1, x, MPFR_RNDU);   /* (1-xt)*/
      mpfr_add_ui (t,  x, 1, MPFR_RNDD);   /* (xt+1)*/
      mpfr_div (t, t, te, MPFR_RNDN);      /* (1+xt)/(1-xt)*/
      mpfr_log (t, t, MPFR_RNDN);          /* ln((1+xt)/(1-xt))*/
      mpfr_div_2ui (t, t, 1, MPFR_RNDN);   /* (1/2)*ln((1+xt)/(1-xt))*/

      /* error estimate: see algorithms.tex */
      /* FIXME: this does not correspond to the value in algorithms.tex!!! */
      /* err=Nt-__gmpfr_ceil_log2(1+5*pow(2,1-MPFR_EXP(t)));*/
      err = Nt - (MAX (4 - MPFR_GET_EXP (t), 0) + 1);

      if (MPFR_LIKELY (MPFR_IS_ZERO (t)
                       || MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
        break;

      /* reactualisation of the precision */
      MPFR_ZIV_NEXT (loop, Nt);
      mpfr_set_prec (t, Nt);
      mpfr_set_prec (te, Nt);
    }
  MPFR_ZIV_FREE (loop);

  inexact = mpfr_set4 (y, t, rnd_mode, MPFR_SIGN (xt));

  mpfr_clear(t);
  mpfr_clear(te);

  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (y, inexact, rnd_mode);
}
コード例 #28
0
int
mpfr_atanh (mpfr_ptr y, mpfr_srcptr xt , mp_rnd_t rnd_mode) 
{
  int inexact = 0;
  mpfr_t x;
  mp_prec_t Nx = MPFR_PREC(xt);   /* Precision of input variable */

  /* Special cases */
  if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(xt) ))
    {
      /* atanh(NaN) = NaN, and atanh(+/-Inf) = NaN since tanh gives a result
         between -1 and 1 */
      if (MPFR_IS_NAN(xt) || MPFR_IS_INF(xt))
	{  
	  MPFR_SET_NAN(y);
	  MPFR_RET_NAN;
	}
      else /* necessarily xt is 0 */
	{
          MPFR_ASSERTD(MPFR_IS_ZERO(xt));
	  MPFR_SET_ZERO(y);   /* atanh(0) = 0 */
	  MPFR_SET_SAME_SIGN(y,xt);
	  MPFR_RET(0);
	}
    }
  /* Useless due to final mpfr_set
     MPFR_CLEAR_FLAGS(y);*/

  /* atanh(x) = NaN as soon as |x| > 1, and arctanh(+/-1) = +/-Inf */
  if (MPFR_EXP(xt) > 0)
    {
      if (MPFR_EXP(xt) == 1 && mpfr_powerof2_raw (xt))
        {
          MPFR_SET_INF(y);
          MPFR_SET_SAME_SIGN(y, xt);
          MPFR_RET(0);
        }
      MPFR_SET_NAN(y);
      MPFR_RET_NAN;
    }

  mpfr_init2 (x, Nx);
  mpfr_abs (x, xt, GMP_RNDN); 

  /* General case */
  {
    /* Declaration of the intermediary variable */
    mpfr_t t, te,ti;       
    
    /* 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+4+__gmpfr_ceil_log2(Nt);

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

    /* First computation of cosh */
    do
      {
        /* reactualisation of the precision */
        mpfr_set_prec(t,Nt);             
        mpfr_set_prec(te,Nt);             
        mpfr_set_prec(ti,Nt);             

        /* compute atanh */
        mpfr_ui_sub(te,1,x,GMP_RNDU);   /* (1-xt)*/
        mpfr_add_ui(ti,x,1,GMP_RNDD);   /* (xt+1)*/
        mpfr_div(te,ti,te,GMP_RNDN);    /* (1+xt)/(1-xt)*/
        mpfr_log(te,te,GMP_RNDN);       /* ln((1+xt)/(1-xt))*/
        mpfr_div_2ui(t,te,1,GMP_RNDN);  /* (1/2)*ln((1+xt)/(1-xt))*/

        /* error estimate see- algorithms.ps*/
        /* err=Nt-__gmpfr_ceil_log2(1+5*pow(2,1-MPFR_EXP(t)));*/
        err = Nt - (MAX (4 - MPFR_GET_EXP (t), 0) + 1);

        /* actualisation of the precision */
        Nt += 10;
      }
    while ((err < 0) || (!mpfr_can_round (t, err, GMP_RNDN, GMP_RNDZ,
                                          Ny + (rnd_mode == GMP_RNDN))
                         || MPFR_IS_ZERO(t)));

    if (MPFR_IS_NEG(xt))
      MPFR_CHANGE_SIGN(t);

    inexact = mpfr_set (y, t, rnd_mode);

    mpfr_clear(t);
    mpfr_clear(ti);
    mpfr_clear(te);
  }
  mpfr_clear(x);
  return inexact;
}
コード例 #29
0
ファイル: gamma.c プロジェクト: Canar/mpfr
/* We use the reflection formula
  Gamma(1+t) Gamma(1-t) = - Pi t / sin(Pi (1 + t))
  in order to treat the case x <= 1,
  i.e. with x = 1-t, then Gamma(x) = -Pi*(1-x)/sin(Pi*(2-x))/GAMMA(2-x)
*/
int
mpfr_gamma (mpfr_ptr gamma, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  mpfr_t xp, GammaTrial, tmp, tmp2;
  mpz_t fact;
  mpfr_prec_t realprec;
  int compared, is_integer;
  int inex = 0;  /* 0 means: result gamma not set yet */
  MPFR_GROUP_DECL (group);
  MPFR_SAVE_EXPO_DECL (expo);
  MPFR_ZIV_DECL (loop);

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

  /* Trivial cases */
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN (x))
        {
          MPFR_SET_NAN (gamma);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF (x))
        {
          if (MPFR_IS_NEG (x))
            {
              MPFR_SET_NAN (gamma);
              MPFR_RET_NAN;
            }
          else
            {
              MPFR_SET_INF (gamma);
              MPFR_SET_POS (gamma);
              MPFR_RET (0);  /* exact */
            }
        }
      else /* x is zero */
        {
          MPFR_ASSERTD(MPFR_IS_ZERO(x));
          MPFR_SET_INF(gamma);
          MPFR_SET_SAME_SIGN(gamma, x);
          MPFR_SET_DIVBY0 ();
          MPFR_RET (0);  /* exact */
        }
    }

  /* Check for tiny arguments, where gamma(x) ~ 1/x - euler + ....
     We know from "Bound on Runs of Zeros and Ones for Algebraic Functions",
     Proceedings of Arith15, T. Lang and J.-M. Muller, 2001, that the maximal
     number of consecutive zeroes or ones after the round bit is n-1 for an
     input of n bits. But we need a more precise lower bound. Assume x has
     n bits, and 1/x is near a floating-point number y of n+1 bits. We can
     write x = X*2^e, y = Y/2^f with X, Y integers of n and n+1 bits.
     Thus X*Y^2^(e-f) is near from 1, i.e., X*Y is near from 2^(f-e).
     Two cases can happen:
     (i) either X*Y is exactly 2^(f-e), but this can happen only if X and Y
         are themselves powers of two, i.e., x is a power of two;
     (ii) or X*Y is at distance at least one from 2^(f-e), thus
          |xy-1| >= 2^(e-f), or |y-1/x| >= 2^(e-f)/x = 2^(-f)/X >= 2^(-f-n).
          Since ufp(y) = 2^(n-f) [ufp = unit in first place], this means
          that the distance |y-1/x| >= 2^(-2n) ufp(y).
          Now assuming |gamma(x)-1/x| <= 1, which is true for x <= 1,
          if 2^(-2n) ufp(y) >= 2, the error is at most 2^(-2n-1) ufp(y),
          and round(1/x) with precision >= 2n+2 gives the correct result.
          If x < 2^E, then y > 2^(-E), thus ufp(y) > 2^(-E-1).
          A sufficient condition is thus EXP(x) + 2 <= -2 MAX(PREC(x),PREC(Y)).
  */
  if (MPFR_GET_EXP (x) + 2
      <= -2 * (mpfr_exp_t) MAX(MPFR_PREC(x), MPFR_PREC(gamma)))
    {
      int sign = MPFR_SIGN (x); /* retrieve sign before possible override */
      int special;
      MPFR_BLOCK_DECL (flags);

      MPFR_SAVE_EXPO_MARK (expo);

      /* for overflow cases, see below; this needs to be done
         before x possibly gets overridden. */
      special =
        MPFR_GET_EXP (x) == 1 - MPFR_EMAX_MAX &&
        MPFR_IS_POS_SIGN (sign) &&
        MPFR_IS_LIKE_RNDD (rnd_mode, sign) &&
        mpfr_powerof2_raw (x);

      MPFR_BLOCK (flags, inex = mpfr_ui_div (gamma, 1, x, rnd_mode));
      if (inex == 0) /* x is a power of two */
        {
          /* return RND(1/x - euler) = RND(+/- 2^k - eps) with eps > 0 */
          if (rnd_mode == MPFR_RNDN || MPFR_IS_LIKE_RNDU (rnd_mode, sign))
            inex = 1;
          else
            {
              mpfr_nextbelow (gamma);
              inex = -1;
            }
        }
      else if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags)))
        {
          /* Overflow in the division 1/x. This is a real overflow, except
             in RNDZ or RNDD when 1/x = 2^emax, i.e. x = 2^(-emax): due to
             the "- euler", the rounded value in unbounded exponent range
             is 0.111...11 * 2^emax (not an overflow). */
          if (!special)
            MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, flags);
        }
      MPFR_SAVE_EXPO_FREE (expo);
      /* Note: an overflow is possible with an infinite result;
         in this case, the overflow flag will automatically be
         restored by mpfr_check_range. */
      return mpfr_check_range (gamma, inex, rnd_mode);
    }

  is_integer = mpfr_integer_p (x);
  /* gamma(x) for x a negative integer gives NaN */
  if (is_integer && MPFR_IS_NEG(x))
    {
      MPFR_SET_NAN (gamma);
      MPFR_RET_NAN;
    }

  compared = mpfr_cmp_ui (x, 1);
  if (compared == 0)
    return mpfr_set_ui (gamma, 1, rnd_mode);

  /* if x is an integer that fits into an unsigned long, use mpfr_fac_ui
     if argument is not too large.
     If precision is p, fac_ui costs O(u*p), whereas gamma costs O(p*M(p)),
     so for u <= M(p), fac_ui should be faster.
     We approximate here M(p) by p*log(p)^2, which is not a bad guess.
     Warning: since the generic code does not handle exact cases,
     we want all cases where gamma(x) is exact to be treated here.
  */
  if (is_integer && mpfr_fits_ulong_p (x, MPFR_RNDN))
    {
      unsigned long int u;
      mpfr_prec_t p = MPFR_PREC(gamma);
      u = mpfr_get_ui (x, MPFR_RNDN);
      if (u < 44787929UL && bits_fac (u - 1) <= p + (rnd_mode == MPFR_RNDN))
        /* bits_fac: lower bound on the number of bits of m,
           where gamma(x) = (u-1)! = m*2^e with m odd. */
        return mpfr_fac_ui (gamma, u - 1, rnd_mode);
      /* if bits_fac(...) > p (resp. p+1 for rounding to nearest),
         then gamma(x) cannot be exact in precision p (resp. p+1).
         FIXME: remove the test u < 44787929UL after changing bits_fac
         to return a mpz_t or mpfr_t. */
    }

  MPFR_SAVE_EXPO_MARK (expo);

  /* check for overflow: according to (6.1.37) in Abramowitz & Stegun,
     gamma(x) >= exp(-x) * x^(x-1/2) * sqrt(2*Pi)
              >= 2 * (x/e)^x / x for x >= 1 */
  if (compared > 0)
    {
      mpfr_t yp;
      mpfr_exp_t expxp;
      MPFR_BLOCK_DECL (flags);

      /* quick test for the default exponent range */
      if (mpfr_get_emax () >= 1073741823UL && MPFR_GET_EXP(x) <= 25)
        {
          MPFR_SAVE_EXPO_FREE (expo);
          return mpfr_gamma_aux (gamma, x, rnd_mode);
        }

      /* 1/e rounded down to 53 bits */
#define EXPM1_STR "0.010111100010110101011000110110001011001110111100111"
      mpfr_init2 (xp, 53);
      mpfr_init2 (yp, 53);
      mpfr_set_str_binary (xp, EXPM1_STR);
      mpfr_mul (xp, x, xp, MPFR_RNDZ);
      mpfr_sub_ui (yp, x, 2, MPFR_RNDZ);
      mpfr_pow (xp, xp, yp, MPFR_RNDZ); /* (x/e)^(x-2) */
      mpfr_set_str_binary (yp, EXPM1_STR);
      mpfr_mul (xp, xp, yp, MPFR_RNDZ); /* x^(x-2) / e^(x-1) */
      mpfr_mul (xp, xp, yp, MPFR_RNDZ); /* x^(x-2) / e^x */
      mpfr_mul (xp, xp, x, MPFR_RNDZ); /* lower bound on x^(x-1) / e^x */
      MPFR_BLOCK (flags, mpfr_mul_2ui (xp, xp, 1, MPFR_RNDZ));
      expxp = MPFR_GET_EXP (xp);
      mpfr_clear (xp);
      mpfr_clear (yp);
      MPFR_SAVE_EXPO_FREE (expo);
      return MPFR_OVERFLOW (flags) || expxp > __gmpfr_emax ?
        mpfr_overflow (gamma, rnd_mode, 1) :
        mpfr_gamma_aux (gamma, x, rnd_mode);
    }

  /* now compared < 0 */

  /* check for underflow: for x < 1,
     gamma(x) = Pi*(x-1)/sin(Pi*(2-x))/gamma(2-x).
     Since gamma(2-x) >= 2 * ((2-x)/e)^(2-x) / (2-x), we have
     |gamma(x)| <= Pi*(1-x)*(2-x)/2/((2-x)/e)^(2-x) / |sin(Pi*(2-x))|
                <= 12 * ((2-x)/e)^x / |sin(Pi*(2-x))|.
     To avoid an underflow in ((2-x)/e)^x, we compute the logarithm.
  */
  if (MPFR_IS_NEG(x))
    {
      int underflow = 0, sgn, ck;
      mpfr_prec_t w;

      mpfr_init2 (xp, 53);
      mpfr_init2 (tmp, 53);
      mpfr_init2 (tmp2, 53);
      /* we want an upper bound for x * [log(2-x)-1].
         since x < 0, we need a lower bound on log(2-x) */
      mpfr_ui_sub (xp, 2, x, MPFR_RNDD);
      mpfr_log (xp, xp, MPFR_RNDD);
      mpfr_sub_ui (xp, xp, 1, MPFR_RNDD);
      mpfr_mul (xp, xp, x, MPFR_RNDU);

      /* we need an upper bound on 1/|sin(Pi*(2-x))|,
         thus a lower bound on |sin(Pi*(2-x))|.
         If 2-x is exact, then the error of Pi*(2-x) is (1+u)^2 with u = 2^(-p)
         thus the error on sin(Pi*(2-x)) is less than 1/2ulp + 3Pi(2-x)u,
         assuming u <= 1, thus <= u + 3Pi(2-x)u */

      w = mpfr_gamma_2_minus_x_exact (x); /* 2-x is exact for prec >= w */
      w += 17; /* to get tmp2 small enough */
      mpfr_set_prec (tmp, w);
      mpfr_set_prec (tmp2, w);
      MPFR_DBGRES (ck = mpfr_ui_sub (tmp, 2, x, MPFR_RNDN));
      MPFR_ASSERTD (ck == 0); /* tmp = 2-x exactly */
      mpfr_const_pi (tmp2, MPFR_RNDN);
      mpfr_mul (tmp2, tmp2, tmp, MPFR_RNDN); /* Pi*(2-x) */
      mpfr_sin (tmp, tmp2, MPFR_RNDN); /* sin(Pi*(2-x)) */
      sgn = mpfr_sgn (tmp);
      mpfr_abs (tmp, tmp, MPFR_RNDN);
      mpfr_mul_ui (tmp2, tmp2, 3, MPFR_RNDU); /* 3Pi(2-x) */
      mpfr_add_ui (tmp2, tmp2, 1, MPFR_RNDU); /* 3Pi(2-x)+1 */
      mpfr_div_2ui (tmp2, tmp2, mpfr_get_prec (tmp), MPFR_RNDU);
      /* if tmp2<|tmp|, we get a lower bound */
      if (mpfr_cmp (tmp2, tmp) < 0)
        {
          mpfr_sub (tmp, tmp, tmp2, MPFR_RNDZ); /* low bnd on |sin(Pi*(2-x))| */
          mpfr_ui_div (tmp, 12, tmp, MPFR_RNDU); /* upper bound */
          mpfr_log2 (tmp, tmp, MPFR_RNDU);
          mpfr_add (xp, tmp, xp, MPFR_RNDU);
          /* The assert below checks that expo.saved_emin - 2 always
             fits in a long. FIXME if we want to allow mpfr_exp_t to
             be a long long, for instance. */
          MPFR_ASSERTN (MPFR_EMIN_MIN - 2 >= LONG_MIN);
          underflow = mpfr_cmp_si (xp, expo.saved_emin - 2) <= 0;
        }

      mpfr_clear (xp);
      mpfr_clear (tmp);
      mpfr_clear (tmp2);
      if (underflow) /* the sign is the opposite of that of sin(Pi*(2-x)) */
        {
          MPFR_SAVE_EXPO_FREE (expo);
          return mpfr_underflow (gamma, (rnd_mode == MPFR_RNDN) ? MPFR_RNDZ : rnd_mode, -sgn);
        }
    }

  realprec = MPFR_PREC (gamma);
  /* we want both 1-x and 2-x to be exact */
  {
    mpfr_prec_t w;
    w = mpfr_gamma_1_minus_x_exact (x);
    if (realprec < w)
      realprec = w;
    w = mpfr_gamma_2_minus_x_exact (x);
    if (realprec < w)
      realprec = w;
  }
  realprec = realprec + MPFR_INT_CEIL_LOG2 (realprec) + 20;
  MPFR_ASSERTD(realprec >= 5);

  MPFR_GROUP_INIT_4 (group, realprec + MPFR_INT_CEIL_LOG2 (realprec) + 20,
                     xp, tmp, tmp2, GammaTrial);
  mpz_init (fact);
  MPFR_ZIV_INIT (loop, realprec);
  for (;;)
    {
      mpfr_exp_t err_g;
      int ck;
      MPFR_GROUP_REPREC_4 (group, realprec, xp, tmp, tmp2, GammaTrial);

      /* reflection formula: gamma(x) = Pi*(x-1)/sin(Pi*(2-x))/gamma(2-x) */

      ck = mpfr_ui_sub (xp, 2, x, MPFR_RNDN); /* 2-x, exact */
      MPFR_ASSERTD(ck == 0);  (void) ck; /* use ck to avoid a warning */
      mpfr_gamma (tmp, xp, MPFR_RNDN);   /* gamma(2-x), error (1+u) */
      mpfr_const_pi (tmp2, MPFR_RNDN);   /* Pi, error (1+u) */
      mpfr_mul (GammaTrial, tmp2, xp, MPFR_RNDN); /* Pi*(2-x), error (1+u)^2 */
      err_g = MPFR_GET_EXP(GammaTrial);
      mpfr_sin (GammaTrial, GammaTrial, MPFR_RNDN); /* sin(Pi*(2-x)) */
      /* If tmp is +Inf, we compute exp(lngamma(x)). */
      if (mpfr_inf_p (tmp))
        {
          inex = mpfr_explgamma (gamma, x, &expo, tmp, tmp2, rnd_mode);
          if (inex)
            goto end;
          else
            goto ziv_next;
        }
      err_g = err_g + 1 - MPFR_GET_EXP(GammaTrial);
      /* let g0 the true value of Pi*(2-x), g the computed value.
         We have g = g0 + h with |h| <= |(1+u^2)-1|*g.
         Thus sin(g) = sin(g0) + h' with |h'| <= |(1+u^2)-1|*g.
         The relative error is thus bounded by |(1+u^2)-1|*g/sin(g)
         <= |(1+u^2)-1|*2^err_g. <= 2.25*u*2^err_g for |u|<=1/4.
         With the rounding error, this gives (0.5 + 2.25*2^err_g)*u. */
      ck = mpfr_sub_ui (xp, x, 1, MPFR_RNDN); /* x-1, exact */
      MPFR_ASSERTD(ck == 0);  (void) ck; /* use ck to avoid a warning */
      mpfr_mul (xp, tmp2, xp, MPFR_RNDN); /* Pi*(x-1), error (1+u)^2 */
      mpfr_mul (GammaTrial, GammaTrial, tmp, MPFR_RNDN);
      /* [1 + (0.5 + 2.25*2^err_g)*u]*(1+u)^2 = 1 + (2.5 + 2.25*2^err_g)*u
         + (0.5 + 2.25*2^err_g)*u*(2u+u^2) + u^2.
         For err_g <= realprec-2, we have (0.5 + 2.25*2^err_g)*u <=
         0.5*u + 2.25/4 <= 0.6875 and u^2 <= u/4, thus
         (0.5 + 2.25*2^err_g)*u*(2u+u^2) + u^2 <= 0.6875*(2u+u/4) + u/4
         <= 1.8*u, thus the rel. error is bounded by (4.5 + 2.25*2^err_g)*u. */
      mpfr_div (GammaTrial, xp, GammaTrial, MPFR_RNDN);
      /* the error is of the form (1+u)^3/[1 + (4.5 + 2.25*2^err_g)*u].
         For realprec >= 5 and err_g <= realprec-2, [(4.5 + 2.25*2^err_g)*u]^2
         <= 0.71, and for |y|<=0.71, 1/(1-y) can be written 1+a*y with a<=4.
         (1+u)^3 * (1+4*(4.5 + 2.25*2^err_g)*u)
         = 1 + (21 + 9*2^err_g)*u + (57+27*2^err_g)*u^2 + (55+27*2^err_g)*u^3
             + (18+9*2^err_g)*u^4
         <= 1 + (21 + 9*2^err_g)*u + (57+27*2^err_g)*u^2 + (56+28*2^err_g)*u^3
         <= 1 + (21 + 9*2^err_g)*u + (59+28*2^err_g)*u^2
         <= 1 + (23 + 10*2^err_g)*u.
         The final error is thus bounded by (23 + 10*2^err_g) ulps,
         which is <= 2^6 for err_g<=2, and <= 2^(err_g+4) for err_g >= 2. */
      err_g = (err_g <= 2) ? 6 : err_g + 4;

      if (MPFR_LIKELY (MPFR_CAN_ROUND (GammaTrial, realprec - err_g,
                                       MPFR_PREC(gamma), rnd_mode)))
        break;

    ziv_next:
      MPFR_ZIV_NEXT (loop, realprec);
    }

 end:
  MPFR_ZIV_FREE (loop);

  if (inex == 0)
    inex = mpfr_set (gamma, GammaTrial, rnd_mode);
  MPFR_GROUP_CLEAR (group);
  mpz_clear (fact);

  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (gamma, inex, rnd_mode);
}
コード例 #30
0
ファイル: log10.c プロジェクト: BrianGladman/MPC
static void
mpfr_const_log10 (mpfr_ptr log10)
{
   mpfr_set_ui (log10, 10, MPFR_RNDN); /* exact since prec >= 4 */
   mpfr_log (log10, log10, MPFR_RNDN); /* error <= 1/2 ulp */
}