Ejemplo n.º 1
0
mpfr_t* compute_rho_to_z_matrix(unsigned long Lambda_arg, long prec){
	/* To avoid writing lambda + 1 so many times...*/
	unsigned long Lambda=Lambda_arg+1;
	mpfr_t* temps=malloc(sizeof(mpfr_t)*(Lambda));
	mpfr_init2(temps[0],prec);
	mpfr_set_ui(temps[0],8,MPFR_RNDN);
	mpfr_sqrt(temps[0],temps[0],MPFR_RNDN);
	mpfr_neg(temps[0],temps[0],MPFR_RNDN);
	for(unsigned long j=1;j<Lambda;j++){
		mpfr_init2(temps[j],prec);
		mpfr_mul_si(temps[j],temps[j-1],2*j-3,MPFR_RNDN);
		mpfr_div_ui(temps[j],temps[j],j,MPFR_RNDN); 
	}
	mpfr_sub_ui(temps[1],temps[1],2,MPFR_RNDN);
	mpfr_add_ui(temps[0],temps[0],3,MPFR_RNDN);
	mpfr_t temp;
	mpfr_init2(temp,prec);
	mpfr_t temp2;
	mpfr_init2(temp2,prec);

	mpfr_t* result=malloc(sizeof(mpfr_t)*(Lambda)*(Lambda));
	mpfr_init2(result[0],prec);
	mpfr_set_ui(result[0],1,MPFR_RNDN);
	for(unsigned long j=1; j<(Lambda*Lambda); j++){
		mpfr_init2(result[j],prec);
		mpfr_set_zero(result[j],1);
	}
	for(unsigned long j=1;j<Lambda;j++){
		mpfr_set_ui(temp,1,MPFR_RNDN);
		for(unsigned long k=0;k<=j;k++){
			mpfr_mul(temp2,temps[j-k],temp,MPFR_RNDN);
			mpfr_add(result[j+Lambda],result[j+Lambda],temp2,MPFR_RNDN);
			mpfr_mul_si(temp,temp,-2,MPFR_RNDN); 
		} 
	}
	for(unsigned long i=2;i<Lambda;i++){
		for(unsigned long j=1;j<Lambda;j++){
			for(unsigned long k=i-1;k<Lambda-j;k++){
				mpfr_mul(temp,result[Lambda*(i-1)+k],result[j+Lambda],MPFR_RNDN);
				mpfr_add(result[Lambda*i+k+j],result[Lambda*i+k+j],temp,MPFR_RNDN);
			}

		} 
	} 

	/* transposition */
	for(unsigned long i=0;i<Lambda;i++){
		for(unsigned long j=0;j<i;j++){
		mpfr_swap(result[i+Lambda*j],result[j+Lambda*i]);
		}
	}
	for(unsigned long j=0;j<Lambda;j++){
		mpfr_clear(temps[j]);
	}
	free(temps);
	mpfr_clear(temp);
	mpfr_clear(temp2);
	return result; 
}
Ejemplo n.º 2
0
depth_t frac_generalized_celtic_mpfr(
                                depth_t depth,
                                mpfr_t bail,
                                mpfr_t wim,     mpfr_t wre,
                                mpfr_t c_im,    mpfr_t c_re,
                                mpfr_t wim2,    mpfr_t wre2, mpfr_t t1)
{
    depth_t wz;
    for (wz = 1; wz <= depth; wz++)
    {
        /* wim = 2.0 * wre * wim + c_im; */
        mpfr_mul(   t1,     wre,    wim,    GMP_RNDN);
        mpfr_mul_si(t1,     t1,     2,      GMP_RNDN);
        mpfr_add(   wim,    t1,     c_im,   GMP_RNDN);
        /* wre = wre2 - wim2 + c_re; */
        mpfr_sub(   t1,     wre2,   wim2,   GMP_RNDN);
        mpfr_abs(   t1,     t1,             GMP_RNDN);
        mpfr_add(   wre,    t1,     c_re,   GMP_RNDN);
        /* wim2 = wim * wim; */
        mpfr_mul(   wim2,   wim,    wim,    GMP_RNDN);
        /* wre2 = wre * wre; */
        mpfr_mul(   wre2,   wre,    wre,    GMP_RNDN);
        /* if ((wim2 + wre2) > frs_bail) */
        mpfr_add(   t1,     wim2,   wre2,   GMP_RNDN);
        if (mpfr_greater_p(t1, bail))
            return wz;
    }
    return 0;
}
Ejemplo n.º 3
0
void mpfr_taylor_nat_log(mpfr_t R, mpfr_t x, mpz_t n)
{
	assert(mpz_cmp_ui(n, 0) > 0);
	assert(mpfr_cmp_ui(x, 0) > 0);

	mpfr_t a, t, tt;
	mpfr_exp_t b;
	mpz_t k;
	unsigned int f = 1000, F = 1000;

	mpfr_init(a);
	mpfr_frexp(&b, a, x, MPFR_RNDN);
	mpfr_ui_sub(a, 1, a, MPFR_RNDN);
	
	mpfr_init_set(t, a, MPFR_RNDN);
	mpfr_init(tt);
	mpfr_set(R, a, MPFR_RNDN);

	for(mpz_init_set_ui(k, 2); mpz_cmp(k, n) < 0; mpz_add_ui(k, k, 1))
	{
		mpfr_mul(t, t, a, MPFR_RNDN);
		mpfr_div_z(tt, t, k, MPFR_RNDN);
		mpfr_add(R, R, tt, MPFR_RNDN);
	}

	mpfr_mul_si(a, MPFR_NAT_LOG_2, b, MPFR_RNDN);
	mpfr_sub(R, a, R, MPFR_RNDN);
}
Ejemplo n.º 4
0
double
virtual_timing_ai2 (struct speed_params *s)
{
  double t;
  unsigned i;
  mpfr_t w, x;
  mp_size_t size;
  mpfr_t temp1, temp2;

  SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN);
  SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX);

  size = (s->size-1)/GMP_NUMB_BITS+1;
  s->xp[size-1] |= MPFR_LIMB_HIGHBIT;
  MPFR_TMP_INIT1 (s->xp, x, s->size);
  MPFR_SET_EXP (x, (mpfr_exp_t) s->r);
  if (s->align_xp == 2) MPFR_SET_NEG (x);

  mpfr_init2 (w, s->size);
  speed_starttime ();
  i = s->reps;

  mpfr_init2 (temp1, MPFR_SMALL_PRECISION);
  mpfr_init2 (temp2, MPFR_SMALL_PRECISION);

  mpfr_set (temp1, x, MPFR_SMALL_PRECISION);
  mpfr_set_si (temp2, MPFR_AI_THRESHOLD2, MPFR_RNDN);
  mpfr_mul_ui (temp2, temp2, (unsigned int)MPFR_PREC (w), MPFR_RNDN);

  if (MPFR_IS_NEG (x))
      mpfr_mul_si (temp1, temp1, MPFR_AI_THRESHOLD1, MPFR_RNDN);
  else
      mpfr_mul_si (temp1, temp1, MPFR_AI_THRESHOLD3, MPFR_RNDN);

  mpfr_add (temp1, temp1, temp2, MPFR_RNDN);

  if (mpfr_cmp_si (temp1, MPFR_AI_SCALE) > 0)
    t = 1.;
  else
    t = 1000.;

  mpfr_clear (temp1);
  mpfr_clear (temp2);

  return t;
}
Ejemplo n.º 5
0
mpfr_t* simple_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 temp2;
	mpfr_init2(temp2,prec); 
	
	mpfr_t temp3;
	mpfr_init2(temp3,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(temp2,pole_position,incomplete_gamma_factor,MPFR_RNDN); 

	mpfr_init2(result[0],prec);
	mpfr_set(result[0],incomplete_gamma_factor,MPFR_RNDN);
	for(long j=1;j<=pole_order_max;j++){
		mpfr_init2(result[j],prec);
		mpfr_mul(temp1,temp1,pole_position,MPFR_RNDN);	
		mpfr_mul(temp3,factorial,log_base_power,MPFR_RNDN);
		mpfr_add(temp1,temp3,temp1,MPFR_RNDN);
		mpfr_add(result[j],temp1,temp2,MPFR_RNDN);

		if(j<pole_order_max){ 
			mpfr_mul(temp2,temp2,pole_position,MPFR_RNDN);
			mpfr_mul(log_base_power,log_base_power,minus_log_base,MPFR_RNDN);
			mpfr_mul_si(factorial,factorial,j,MPFR_RNDN);
		}
	}

	mpfr_clear(temp1);
	mpfr_clear(temp2);
	mpfr_clear(temp3);
	mpfr_clear(minus_pole_position);
	mpfr_clear(factorial);
	mpfr_clear(minus_log_base);
	mpfr_clear(log_base_power);
	return result;
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
/// @brief tan keyword implementation
///
void program::rpn_tan(void) {
    MIN_ARGUMENTS(1);

    if (_stack->get_type(0) == cmd_number) {
        floating_t* left = &((number*)_stack->get_obj(0))->_value;
        CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
    } else if (_stack->get_type(0) == cmd_complex) {
        // tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x)
        stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);

        floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
        floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
        floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();

        floating_t* re = ((complex*)_stack->get_obj(0))->re();
        floating_t* im = ((complex*)_stack->get_obj(0))->im();

        // x->2x
        CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd));
        // y->2y
        CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, floating_t::s_mpfr_rnd));

        // sin(2x)+sinh(2y)
        CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
        CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));

        // cosh(2y)+cos(2x)
        CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
        CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
        CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, floating_t::s_mpfr_rnd));

        // sin(2x)+sinh(2y) / (cosh(2y)+cos(2x))
        CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
        CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));

        _calc_stack.pop_back(2);
    } else
        ERR_CONTEXT(ret_bad_operand_type);
}
Ejemplo n.º 8
0
/// @brief r->d keyword implementation
///
void program::rpn_r2d(void) {
    MIN_ARGUMENTS(1);
    ARG_MUST_BE_OF_TYPE(0, cmd_number);

    // add pi on stack
    rpn_pi();

    floating_t* pi = &((number*)_stack->pop_back())->_value;
    floating_t* left = &((number*)_stack->get_obj(0))->_value;

    CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
    CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
}
Ejemplo n.º 9
0
int
main (int argc, char *argv[])
{
  mpfr_t x, z;
  int y;
  int i;

  tests_start_mpfr ();
  mpfr_inits2 (53, x, z, (mpfr_ptr) 0);
  for(i = 0 ; i < numberof (tab) ; i++)
    {
      mpfr_set_str (x, tab[i].op1, 16, MPFR_RNDN);
      y = tab[i].op2;
      mpfr_add_si (z, x, y, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_add, 16, MPFR_RNDN))
        ERROR1("add_si", i, z, tab[i].res_add);
      mpfr_sub_si (z, x, y, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_sub, 16, MPFR_RNDN))
        ERROR1("sub_si", i, z, tab[i].res_sub);
      mpfr_si_sub (z, y, x, MPFR_RNDZ);
      mpfr_neg (z, z, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_sub, 16, MPFR_RNDN))
        ERROR1("si_sub", i, z, tab[i].res_sub);
      mpfr_mul_si (z, x, y, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_mul, 16, MPFR_RNDN))
        ERROR1("mul_si", i, z, tab[i].res_mul);
      mpfr_div_si (z, x, y, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_div, 16, MPFR_RNDN))
        ERROR1("div_si", i, z, tab[i].res_div);
    }
  mpfr_set_str1 (x, "1");
  mpfr_si_div (z, 1024, x, MPFR_RNDN);
  if (mpfr_cmp_str1 (z, "1024"))
    ERROR1("si_div", i, z, "1024");
  mpfr_si_div (z, -1024, x, MPFR_RNDN);
  if (mpfr_cmp_str1 (z, "-1024"))
    ERROR1("si_div", i, z, "-1024");

  mpfr_clears (x, z, (mpfr_ptr) 0);

  check_invert ();

  test_generic_add_si (2, 200, 17);
  test_generic_sub_si (2, 200, 17);
  test_generic_mul_si (2, 200, 17);
  test_generic_div_si (2, 200, 17);

  tests_end_mpfr ();
  return 0;
}
Ejemplo n.º 10
0
Archivo: t10.cpp Proyecto: oakad/ucpf
int main(int argc, char **argv)
{
	mpfr_t x2, x10;
	mpfr_t l2, l10;
	mpfr_t inv_log2_10;
	mpfr_inits2(256, x2, x10, l2, l10, inv_log2_10, nullptr);
	mpfr_set_ui(x2, 2, MPFR_RNDN);
	mpfr_set_ui(x10, 10, MPFR_RNDN);
	mpfr_log(l2, x2, MPFR_RNDN);
	mpfr_log(l10, x10, MPFR_RNDN);
	mpfr_div(inv_log2_10, l2, l10, MPFR_RNDN);

	constexpr double d_inv_log2_10 = 0.30102999566398114;

	constexpr int32_t i_inv_log2_10 = 646456993;

	for (long c = -(1 << 14); c < (1 << 14); ++c) {
		mpfr_mul_si(x10, inv_log2_10, c, MPFR_RNDN);
		auto pow_10(mpfr_get_si(x10, MPFR_RNDU));

		auto d_pow_10(std::lround(std::ceil(
			c * d_inv_log2_10 - 1e-10
		)));

		int64_t acc(c);
		acc *= i_inv_log2_10;
		auto i_pow_10(acc ? (acc >> 31) + 1 : 0);

		if (pow_10 != d_pow_10) {
			printf(
				"xx pow_2 %ld, pow_10 %ld, diff %ld\n",
				c, pow_10, pow_10 - d_pow_10
			);
		}
		if (pow_10 != i_pow_10) {
			printf(
				"yy pow_2 %ld, pow_10 %ld, diff %ld\n",
				c, pow_10, pow_10 - i_pow_10
			);
		}
	}
	return 0;
}
Ejemplo n.º 11
0
void fft_init(size_t N, mpfr_prec_t prec)
{
	if (prec) precision = prec;
	if (N) LEN = N;
	twid_fact = (Sequence) calloc(LEN, sizeof(mpc_t));
	mpfr_init_set_d(ZERO, 0.0, MPFR_RNDA);
	mpfr_init2(tmp, precision);
	mpfr_const_pi(tmp, MPFR_RNDA);
	mpfr_mul_si(tmp, tmp, -2, MPFR_RNDA);
	mpfr_div_ui(tmp, tmp, N, MPFR_RNDA);
	mpc_init2(min2pii, precision);
	mpc_set_fr_fr(min2pii, ZERO, tmp, RND);
	mpc_init2(temp, precision);
	new_seq = (Sequence) calloc(N, sizeof(mpc_t));
	size_t n = N / 2;
	while (n--)
	{
		mpc_init2(twid_fact + n, precision);
		mpc_mul_ui(twid_fact + n, min2pii, n, RND);
		mpc_exp(twid_fact + n, twid_fact + n, RND);
	}
}
Ejemplo n.º 12
0
int fractal_mpfr_calculate_line(image_info* img, int line)
{
    int ret = 1;
    int ix = 0;
    int mx = 0;
    int chk_px = ((rthdata*)img->rth_ptr)->check_stop_px;
    int img_width = img->real_width;
    int* raw_data = &img->raw_data[line * img_width];

    depth_t depth = img->depth;

    mpfr_t  x,      y;
    mpfr_t  x2,     y2;
    mpfr_t  c_re,   c_im;

/*  working variables:      */
    mpfr_t  wre,    wim;
    mpfr_t  wre2,   wim2;

    mpfr_t  frs_bail;
    mpfr_t  width,  img_rw,    img_xmin;
    mpfr_t  t1;

    mpfr_init2(x,       img->precision);
    mpfr_init2(y,       img->precision);
    mpfr_init2(x2,      img->precision);
    mpfr_init2(y2,      img->precision);
    mpfr_init2(c_re,    img->precision);
    mpfr_init2(c_im,    img->precision);
    mpfr_init2(wre,     img->precision);
    mpfr_init2(wim,     img->precision);
    mpfr_init2(wre2,    img->precision);
    mpfr_init2(wim2,    img->precision);
    mpfr_init2(frs_bail,img->precision);
    mpfr_init2(width,   img->precision);
    mpfr_init2(img_rw,  img->precision);
    mpfr_init2(img_xmin,img->precision);
    mpfr_init2(t1,      img->precision);

    mpfr_set_si(frs_bail,   4,          GMP_RNDN);
    mpfr_set_si(img_rw,     img_width,  GMP_RNDN);
    mpfr_set(   img_xmin,   img->xmin,  GMP_RNDN);
    mpfr_set(   width,      img->width, GMP_RNDN);

/*  y = img->ymax - ((img->xmax - img->xmin) 
                / (long double)img->real_width)
                * (long double)img->lines_done; */
    mpfr_div(       t1,     width,      img_rw,     GMP_RNDN);

    mpfr_mul_si(    t1,     t1,         line,       GMP_RNDN);
    mpfr_sub(       y,      img->ymax,  t1,         GMP_RNDN);
    mpfr_mul(       y2,     y,          y,          GMP_RNDN);

    while (ix < img_width)
    {
        mx += chk_px;
        if (mx > img_width)
            mx = img_width;
        for (; ix < mx; ++ix, ++raw_data)
        {
/*          x = ((long double)ix / (long double)img->real_width)
                * (img->xmax - img->xmin) + img->xmin;              */

            mpfr_si_div(t1,  ix,    img_rw,     GMP_RNDN);

            mpfr_mul(x,      t1,    width,      GMP_RNDN);
            mpfr_add(x,      x,     img_xmin,   GMP_RNDN);

            mpfr_mul(   x2,     x,      x,      GMP_RNDN);
            mpfr_set(   wre,    x,              GMP_RNDN);
            mpfr_set(   wim,    y,              GMP_RNDN);
            mpfr_set(   wre2,   x2,             GMP_RNDN);
            mpfr_set(   wim2,   y2,             GMP_RNDN);

            switch (img->family)
            {
            case FAMILY_MANDEL:
                mpfr_set(c_re,  x,  GMP_RNDN);
                mpfr_set(c_im,  y,  GMP_RNDN);
                break;
            case FAMILY_JULIA:
                mpfr_set(c_re,  img->u.julia.c_re,  GMP_RNDN);
                mpfr_set(c_im,  img->u.julia.c_im,  GMP_RNDN);
                break;
            }
            switch(img->fractal)
            {
            case BURNING_SHIP:
                *raw_data = frac_burning_ship_mpfr(
                                                depth, frs_bail,
                                                    wim, wre,
                                                    c_im, c_re,
                                                    wim2, wre2, t1);
                break;
            case GENERALIZED_CELTIC:
                *raw_data = frac_generalized_celtic_mpfr(
                                                depth, frs_bail,
                                                    wim, wre,
                                                    c_im, c_re,
                                                    wim2, wre2, t1);
                break;
            case VARIANT:
                *raw_data = frac_variant_mpfr(
                                                depth, frs_bail,
                                                    wim, wre,
                                                    c_im, c_re,
                                                    wim2, wre2, t1);
                break;
            case MANDELBROT:
            default:
                *raw_data = frac_mandel_mpfr(depth, frs_bail,
                                                    wim, wre,
                                                    c_im, c_re,
                                                    wim2, wre2, t1);
            }
        }
        if (rth_render_should_stop((rthdata*)img->rth_ptr))
        {
            ret = 0;
            break;
        }
    }
    mpfr_clear(x);
    mpfr_clear(y);
    mpfr_clear(x2);
    mpfr_clear(y2);
    mpfr_clear(c_re);
    mpfr_clear(c_im);
    mpfr_clear(wre);
    mpfr_clear(wim);
    mpfr_clear(wre2);
    mpfr_clear(wim2);
    mpfr_clear(frs_bail);
    mpfr_clear(width);
    mpfr_clear(img_rw);
    mpfr_clear(t1);
    return ret;
}
Ejemplo n.º 13
0
static PyObject *
GMPy_Real_Mul(PyObject *x, PyObject *y, CTXT_Object *context)
{
    MPFR_Object *result = NULL;

    CHECK_CONTEXT(context);

    if (!(result = GMPy_MPFR_New(0, context))) {
        /* LCOV_EXCL_START */
        return NULL;
        /* LCOV_EXCL_STOP */
    }

    if (MPFR_Check(x) && MPFR_Check(y)) {
        mpfr_clear_flags();
        result->rc = mpfr_mul(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
        goto done;
    }

    if (MPFR_Check(x)) {
        if (PyIntOrLong_Check(y)) {
            int error;
            long temp = GMPy_Integer_AsLongAndError(y, &error);

            if (!error) {
                mpfr_clear_flags();
                result->rc = mpfr_mul_si(result->f, MPFR(x), temp, GET_MPFR_ROUND(context));
                goto done;
            }
            else {
                mpz_t tempz;
                mpz_inoc(tempz);
                mpz_set_PyIntOrLong(tempz, y);
                mpfr_clear_flags();
                result->rc = mpfr_mul_z(result->f, MPFR(x), tempz, GET_MPFR_ROUND(context));
                mpz_cloc(tempz);
                goto done;
            }
        }

        if (CHECK_MPZANY(y)) {
            mpfr_clear_flags();
            result->rc = mpfr_mul_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context));
            goto done;
        }

        if (IS_RATIONAL(y)) {
            MPQ_Object *tempy = NULL;

            if (!(tempy = GMPy_MPQ_From_Number(y, context))) {
                /* LCOV_EXCL_START */
                Py_DECREF((PyObject*)result);
                return NULL;
                /* LCOV_EXCL_STOP */
            }

            mpfr_clear_flags();
            result->rc = mpfr_mul_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context));
            Py_DECREF((PyObject*)tempy);
            goto done;
        }

        if (PyFloat_Check(y)) {
            mpfr_clear_flags();
            result->rc = mpfr_mul_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context));
            goto done;
        }
    }

    if (MPFR_Check(y)) {
        if (PyIntOrLong_Check(x)) {
            int error;
            long temp = GMPy_Integer_AsLongAndError(x, &error);

            if (!error) {
                mpfr_clear_flags();
                result->rc = mpfr_mul_si(result->f, MPFR(y), temp, GET_MPFR_ROUND(context));
                goto done;
            }
            else {
                mpz_t tempz;
                mpz_inoc(tempz);
                mpz_set_PyIntOrLong(tempz, x);
                mpfr_clear_flags();
                result->rc = mpfr_mul_z(result->f, MPFR(y), tempz, GET_MPFR_ROUND(context));
                mpz_cloc(tempz);
                goto done;
            }
        }

        if (CHECK_MPZANY(x)) {
            mpfr_clear_flags();
            result->rc = mpfr_mul_z(result->f, MPFR(y), MPZ(x), GET_MPFR_ROUND(context));
            goto done;
        }

        if (IS_RATIONAL(x)) {
            MPQ_Object *tempx = NULL;

            if (!(tempx = GMPy_MPQ_From_Number(x, context))) {
                /* LCOV_EXCL_START */
                Py_DECREF((PyObject*)result);
                return NULL;
                /* LCOV_EXCL_STOP */
            }

            mpfr_clear_flags();
            result->rc = mpfr_mul_q(result->f, MPFR(y), tempx->q, GET_MPFR_ROUND(context));
            Py_DECREF((PyObject*)tempx);
            goto done;
        }

        if (PyFloat_Check(x)) {
            mpfr_clear_flags();
            result->rc = mpfr_mul_d(result->f, MPFR(y), PyFloat_AS_DOUBLE(x), GET_MPFR_ROUND(context));
            goto done;
        }
    }

    if (IS_REAL(x) && IS_REAL(y)) {
        MPFR_Object *tempx = NULL, *tempy = NULL;

        if (!(tempx = GMPy_MPFR_From_Real(x, 1, context)) ||
            !(tempy = GMPy_MPFR_From_Real(y, 1, context))) {
            /* LCOV_EXCL_START */
            Py_XDECREF((PyObject*)tempx);
            Py_XDECREF((PyObject*)tempy);
            Py_DECREF((PyObject*)result);
            return NULL;
            /* LCOV_EXCL_STOP */
        }

        mpfr_clear_flags();
        result->rc = mpfr_mul(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
        Py_DECREF((PyObject*)tempx);
        Py_DECREF((PyObject*)tempy);
        goto done;
    }

    /* LCOV_EXCL_START */
    Py_DECREF((PyObject*)result);
    SYSTEM_ERROR("Internal error in GMPy_Real_Mul().");
    return NULL;
    /* LCOV_EXCL_STOP */

  done:
    _GMPy_MPFR_Cleanup(&result, context);
    return (PyObject*)result;
}
Ejemplo n.º 14
0
static int
binary (void)
{
    mpfr_t x;
    mpfr_t z;
    mpfr_inits2 (64, x, z, (mpfr_ptr) 0);

    /* special */
    mpfr_set_inf (x, 1);
    check_sprintf (pinf_str, "%Rb", x);

    mpfr_set_inf (x, -1);
    check_sprintf (minf_str, "%Rb", x);

    mpfr_set_nan (x);
    check_sprintf (nan_str, "%Rb", x);

    /* regular numbers */
    mpfr_set_str (x, "1110010101.1001101", 2, MPFR_RNDN);
    mpfr_set_ui (z, 0, MPFR_RNDN);

    /* simplest case: right justified */
    check_sprintf ("    1.1100101011001101p+9", "%25Rb", x);
    check_sprintf ("                     0p+0", "%25Rb", z);
    /* sign or space, pad with leading zeros */
    check_sprintf (" 0001.1100101011001101p+9", "% 025Rb", x);
    check_sprintf (" 000000000000000000000p+0", "% 025Rb", z);
    /* sign + or -, left justified */
    check_sprintf ("+1.1100101011001101p+9   ", "%+-25Rb", x);
    check_sprintf ("+0p+0                    ", "%+-25Rb", z);
    /* sign or space */
    check_sprintf (" 1.110p+9",  "% .3RNb", x);
    check_sprintf (" 1.1101p+9", "% .4RNb", x);
    check_sprintf (" 0.0000p+0", "% .4RNb", z);
    /* sign + or -, decimal point, pad with leading zeros */
    check_sprintf ("+00001.1p+9", "%0+#11.1RZb", x);
    check_sprintf ("+0001.0p+10", "%0+#11.1RNb", x);
    check_sprintf ("+000000.p+0", "%0+#11.0RNb", z);
    /* pad with leading zero */
    check_sprintf ("00001.1100101011001101p+9", "%025RDb", x);
    /* sign or space, decimal point (unused), left justified */
    check_sprintf (" 1.1p+9    ", "%- #11.1RDb", x);
    check_sprintf (" 1.p+9     ", "%- #11.0RDb", x);
    check_sprintf (" 1.p+10    ", "%- #11.0RUb", x);
    check_sprintf (" 1.p+9     ", "%- #11.0RZb", x);
    check_sprintf (" 1.p+10    ", "%- #11.0RYb", x);
    check_sprintf (" 1.p+10    ", "%- #11.0RNb", x);

    mpfr_mul_si (x, x, -1, MPFR_RNDD);
    mpfr_mul_si (z, z, -1, MPFR_RNDD);

    /* sign + or - */
    check_sprintf ("   -1.1p+9", "%+10.1RUb", x);
    check_sprintf ("   -0.0p+0", "%+10.1RUb", z);

    /* precision 0 */
    check_sprintf ("-1p+10", "%.0RNb", x);
    check_sprintf ("-1p+10", "%.0RDb", x);
    check_sprintf ("-1p+9",  "%.0RUb", x);
    check_sprintf ("-1p+9",  "%.0RZb", x);
    check_sprintf ("-1p+10", "%.0RYb", x);
    /* round to next base power */
    check_sprintf ("-1.0p+10", "%.1RNb", x);
    check_sprintf ("-1.0p+10", "%.1RDb", x);
    check_sprintf ("-1.0p+10", "%.1RYb", x);
    /* do not round to next base power */
    check_sprintf ("-1.1p+9", "%.1RUb", x);
    check_sprintf ("-1.1p+9", "%.1RZb", x);
    /* rounding bit is zero */
    check_sprintf ("-1.11p+9", "%.2RNb", x);
    /* tie case in round to nearest mode */
    check_sprintf ("-1.1100101011001101p+9", "%.16RNb", x);
    /* trailing zeros in fractional part */
    check_sprintf ("-1.110010101100110100000000000000p+9", "%.30RNb", x);

    mpfr_clears (x, z, (mpfr_ptr) 0);
    return 0;
}
Ejemplo n.º 15
0
static int
hexadecimal (void)
{
    mpfr_t x, z;
    mpfr_inits2 (64, x, z, (mpfr_ptr) 0);

    /* special */
    mpfr_set_inf (x, 1);
    check_sprintf (pinf_str, "%Ra", x);
    check_sprintf (pinf_str, "%RUa", x);
    check_sprintf (pinf_str, "%RDa", x);
    check_sprintf (pinf_uc_str, "%RA", x);
    check_sprintf (pinf_uc_str, "%RYA", x);
    check_sprintf (pinf_uc_str, "%RZA", x);
    check_sprintf (pinf_uc_str, "%RNA", x);

    mpfr_set_inf (x, -1);
    check_sprintf (minf_str, "%Ra", x);
    check_sprintf (minf_str, "%RYa", x);
    check_sprintf (minf_str, "%RZa", x);
    check_sprintf (minf_str, "%RNa", x);
    check_sprintf (minf_uc_str, "%RA", x);
    check_sprintf (minf_uc_str, "%RUA", x);
    check_sprintf (minf_uc_str, "%RDA", x);

    mpfr_set_nan (x);
    check_sprintf (nan_str, "%Ra", x);
    check_sprintf (nan_uc_str, "%RA", x);

    /* regular numbers */
    mpfr_set_str (x, "FEDCBA9.87654321", 16, MPFR_RNDN);
    mpfr_set_ui (z, 0, MPFR_RNDZ);

    /* simplest case right justified */
    check_sprintf ("   0xf.edcba987654321p+24", "%25Ra", x);
    check_sprintf ("   0xf.edcba987654321p+24", "%25RUa", x);
    check_sprintf ("   0xf.edcba987654321p+24", "%25RDa", x);
    check_sprintf ("   0xf.edcba987654321p+24", "%25RYa", x);
    check_sprintf ("   0xf.edcba987654321p+24", "%25RZa", x);
    check_sprintf ("   0xf.edcba987654321p+24", "%25RNa", x);
    check_sprintf ("                  0x1p+28", "%25.0Ra", x);
    check_sprintf ("                   0x0p+0", "%25.0Ra", z);
    /* sign or space, pad with leading zeros */
    check_sprintf (" 0X00F.EDCBA987654321P+24", "% 025RA", x);
    check_sprintf (" 0X000000000000000001P+28", "% 025.0RA", x);
    check_sprintf (" 0X0000000000000000000P+0", "% 025.0RA", z);
    /* sign + or -, left justified */
    check_sprintf ("+0xf.edcba987654321p+24  ", "%+-25Ra", x);
    check_sprintf ("+0x1p+28                 ", "%+-25.0Ra", x);
    check_sprintf ("+0x0p+0                  ", "%+-25.0Ra", z);
    /* decimal point, left justified, precision and rounding parameter */
    check_vsprintf ("0XF.FP+24 ", "%#-10.*R*A", 1, MPFR_RNDN, x);
    check_vsprintf ("0X1.P+28  ", "%#-10.*R*A", 0, MPFR_RNDN, x);
    check_vsprintf ("0X0.P+0   ", "%#-10.*R*A", 0, MPFR_RNDN, z);
    /* sign or space */
    check_sprintf (" 0xf.eddp+24", "% .3RNa", x);
    check_sprintf (" 0x1p+28",     "% .0RNa", x);
    /* sign + or -, decimal point, pad with leading zeros */
    check_sprintf ("+0X0F.EP+24", "%0+#11.1RZA", x);
    check_sprintf ("+0X00F.P+24", "%0+#11.0RZA", x);
    check_sprintf ("+0X000.0P+0", "%0+#11.1RZA", z);
    /* pad with leading zero */
    check_sprintf ("0x0000f.edcba987654321p+24", "%026RDa", x);
    check_sprintf ("0x0000000000000000000fp+24", "%026.0RDa", x);
    /* sign or space, decimal point, left justified */
    check_sprintf (" 0XF.EP+24 " , "%- #11.1RDA", x);
    check_sprintf (" 0XF.P+24  " , "%- #11.0RDA", x);

    mpfr_mul_si (x, x, -1, MPFR_RNDD);
    mpfr_mul_si (z, z, -1, MPFR_RNDD);

    /* sign + or - */
    check_sprintf ("-0xf.ep+24", "%+10.1RUa", x);
    check_sprintf ("  -0xfp+24", "%+10.0RUa", x);
    check_sprintf ("   -0x0p+0", "%+10.0RUa", z);

    /* rounding bit is zero */
    mpfr_set_str (x, "0xF.7", 16, MPFR_RNDN);
    check_sprintf ("0XFP+0", "%.0RNA", x);
    /* tie case in round to nearest mode */
    mpfr_set_str (x, "0x0.8800000000000000p+3", 16, MPFR_RNDN);
    check_sprintf ("0x9.p-1", "%#.0RNa", x);
    mpfr_set_str (x, "-0x0.9800000000000000p+3", 16, MPFR_RNDN);
    check_sprintf ("-0xap-1", "%.0RNa", x);
    /* trailing zeros in fractional part */
    check_sprintf ("-0X4.C0000000000000000000P+0", "%.20RNA", x);
    /* rounding bit is one and the first non zero bit is far away */
    mpfr_set_prec (x, 1024);
    mpfr_set_ui_2exp (x, 29, -1, MPFR_RNDN);
    mpfr_nextabove (x);
    check_sprintf ("0XFP+0", "%.0RNA", x);

    /* with more than one limb */
    mpfr_set_prec (x, 300);
    mpfr_set_str (x, "0xf.ffffffffffffffffffffffffffffffffffffffffffffffffffff"
                  "fffffffffffffffff", 16, MPFR_RNDN);
    check_sprintf ("0x1p+4 [300]", "%.0RNa [300]", x);
    check_sprintf ("0xfp+0 [300]", "%.0RZa [300]", x);
    check_sprintf ("0x1p+4 [300]", "%.0RYa [300]", x);
    check_sprintf ("0xfp+0 [300]", "%.0RDa [300]", x);
    check_sprintf ("0x1p+4 [300]", "%.0RUa [300]", x);
    check_sprintf ("0x1.0000000000000000000000000000000000000000p+4",
                   "%.40RNa", x);
    check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffffffp+0",
                   "%.40RZa", x);
    check_sprintf ("0x1.0000000000000000000000000000000000000000p+4",
                   "%.40RYa", x);
    check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffffffp+0",
                   "%.40RDa", x);
    check_sprintf ("0x1.0000000000000000000000000000000000000000p+4",
                   "%.40RUa", x);

    mpfr_set_str (x, "0xf.7fffffffffffffffffffffffffffffffffffffffffffffffffff"
                  "ffffffffffffffffff", 16, MPFR_RNDN);
    check_sprintf ("0XFP+0", "%.0RNA", x);
    check_sprintf ("0XFP+0", "%.0RZA", x);
    check_sprintf ("0X1P+4", "%.0RYA", x);
    check_sprintf ("0XFP+0", "%.0RDA", x);
    check_sprintf ("0X1P+4", "%.0RUA", x);
    check_sprintf ("0XF.8P+0", "%.1RNA", x);
    check_sprintf ("0XF.7P+0", "%.1RZA", x);
    check_sprintf ("0XF.8P+0", "%.1RYA", x);
    check_sprintf ("0XF.7P+0", "%.1RDA", x);
    check_sprintf ("0XF.8P+0", "%.1RUA", x);

    /* do not round up to the next power of the base */
    mpfr_set_str (x, "0xf.fffffffffffffffffffffffffffffffffffffeffffffffffffff"
                  "ffffffffffffffffff", 16, MPFR_RNDN);
    check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0",
                   "%.40RNa", x);
    check_sprintf ("0xf.fffffffffffffffffffffffffffffffffffffeffp+0",
                   "%.40RZa", x);
    check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0",
                   "%.40RYa", x);
    check_sprintf ("0xf.fffffffffffffffffffffffffffffffffffffeffp+0",
                   "%.40RDa", x);
    check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0",
                   "%.40RUa", x);

    mpfr_clears (x, z, (mpfr_ptr) 0);
    return 0;
}
Ejemplo n.º 16
0
static int
decimal (void)
{
    mpfr_prec_t p = 128;
    mpfr_t x;
    mpfr_t z;
    mpfr_init (z);
    mpfr_init2 (x, p);

    /* specifier 'P' for precision */
    check_vsprintf ("128", "%Pu", p);
    check_vsprintf ("00128", "%.5Pu", p);

    /* special numbers */
    mpfr_set_inf (x, 1);
    check_sprintf (pinf_str, "%Re", x);
    check_sprintf (pinf_str, "%RUe", x);
    check_sprintf (pinf_uc_str, "%RE", x);
    check_sprintf (pinf_uc_str, "%RDE", x);
    check_sprintf (pinf_str, "%Rf", x);
    check_sprintf (pinf_str, "%RYf", x);
    check_sprintf (pinf_uc_str, "%RF", x);
    check_sprintf (pinf_uc_str, "%RZF", x);
    check_sprintf (pinf_str, "%Rg", x);
    check_sprintf (pinf_str, "%RNg", x);
    check_sprintf (pinf_uc_str, "%RG", x);
    check_sprintf (pinf_uc_str, "%RUG", x);
    check_sprintf ("       inf", "%010Re", x);
    check_sprintf ("       inf", "%010RDe", x);

    mpfr_set_inf (x, -1);
    check_sprintf (minf_str, "%Re", x);
    check_sprintf (minf_str, "%RYe", x);
    check_sprintf (minf_uc_str, "%RE", x);
    check_sprintf (minf_uc_str, "%RZE", x);
    check_sprintf (minf_str, "%Rf", x);
    check_sprintf (minf_str, "%RNf", x);
    check_sprintf (minf_uc_str, "%RF", x);
    check_sprintf (minf_uc_str, "%RUF", x);
    check_sprintf (minf_str, "%Rg", x);
    check_sprintf (minf_str, "%RDg", x);
    check_sprintf (minf_uc_str, "%RG", x);
    check_sprintf (minf_uc_str, "%RYG", x);
    check_sprintf ("      -inf", "%010Re", x);
    check_sprintf ("      -inf", "%010RZe", x);

    mpfr_set_nan (x);
    check_sprintf (nan_str, "%Re", x);
    check_sprintf (nan_str, "%RNe", x);
    check_sprintf (nan_uc_str, "%RE", x);
    check_sprintf (nan_uc_str, "%RUE", x);
    check_sprintf (nan_str, "%Rf", x);
    check_sprintf (nan_str, "%RDf", x);
    check_sprintf (nan_uc_str, "%RF", x);
    check_sprintf (nan_uc_str, "%RYF", x);
    check_sprintf (nan_str, "%Rg", x);
    check_sprintf (nan_str, "%RZg", x);
    check_sprintf (nan_uc_str, "%RG", x);
    check_sprintf (nan_uc_str, "%RNG", x);
    check_sprintf ("       nan", "%010Re", x);

    /* positive numbers */
    mpfr_set_str (x, "18993474.61279296875", 10, MPFR_RNDN);
    mpfr_set_ui (z, 0, MPFR_RNDD);

    /* simplest case right justified */
    check_sprintf ("      1.899347461279296875e+07", "%30Re", x);
    check_sprintf ("                         2e+07", "%30.0Re", x);
    check_sprintf ("               18993474.612793", "%30Rf", x);
    check_sprintf ("              18993474.6127930", "%30.7Rf", x);
    check_sprintf ("                   1.89935e+07", "%30Rg", x);
    check_sprintf ("                         2e+07", "%30.0Rg", x);
    check_sprintf ("          18993474.61279296875", "%30.19Rg", x);
    check_sprintf ("                         0e+00", "%30.0Re", z);
    check_sprintf ("                             0", "%30.0Rf", z);
    check_sprintf ("                        0.0000", "%30.4Rf", z);
    check_sprintf ("                             0", "%30.0Rg", z);
    check_sprintf ("                             0", "%30.4Rg", z);
    /* sign or space, pad with leading zeros */
    check_sprintf (" 000001.899347461279296875E+07", "% 030RE", x);
    check_sprintf (" 0000000000000000001.89935E+07", "% 030RG", x);
    check_sprintf (" 0000000000000000000000002E+07", "% 030.0RE", x);
    check_sprintf (" 0000000000000000000000000E+00", "% 030.0RE", z);
    check_sprintf (" 00000000000000000000000000000", "% 030.0RF", z);
    /* sign + or -, left justified */
    check_sprintf ("+1.899347461279296875e+07     ", "%+-30Re", x);
    check_sprintf ("+2e+07                        ", "%+-30.0Re", x);
    check_sprintf ("+0e+00                        ", "%+-30.0Re", z);
    check_sprintf ("+0                            ", "%+-30.0Rf", z);
    /* decimal point, left justified, precision and rounding parameter */
    check_vsprintf ("1.9E+07   ", "%#-10.*R*E", 1, MPFR_RNDN, x);
    check_vsprintf ("2.E+07    ", "%#*.*R*E", -10, 0, MPFR_RNDN, x);
    check_vsprintf ("2.E+07    ", "%#-10.*R*G", 0, MPFR_RNDN, x);
    check_vsprintf ("0.E+00    ", "%#-10.*R*E", 0, MPFR_RNDN, z);
    check_vsprintf ("0.        ", "%#-10.*R*F", 0, MPFR_RNDN, z);
    check_vsprintf ("0.        ", "%#-10.*R*G", 0, MPFR_RNDN, z);
    /* sign or space */
    check_sprintf (" 1.899e+07", "% .3RNe", x);
    check_sprintf (" 2e+07",     "% .0RNe", x);
    /* sign + or -, decimal point, pad with leading zeros */
    check_sprintf ("+0001.8E+07", "%0+#11.1RZE", x);
    check_sprintf ("+00001.E+07", "%0+#11.0RZE", x);
    check_sprintf ("+0000.0E+00", "%0+#11.1RZE", z);
    check_sprintf ("+00000000.0", "%0+#11.1RZF", z);
    /* pad with leading zero */
    check_sprintf ("0000001.899347461279296875e+07", "%030RDe", x);
    check_sprintf ("00000000000000000000000001e+07", "%030.0RDe", x);
    /* sign or space, decimal point, left justified */
    check_sprintf (" 1.8E+07   ", "%- #11.1RDE", x);
    check_sprintf (" 1.E+07    ", "%- #11.0RDE", x);

    /* negative numbers */
    mpfr_mul_si (x, x, -1, MPFR_RNDD);
    mpfr_mul_si (z, z, -1, MPFR_RNDD);

    /* sign + or - */
    check_sprintf ("  -1.8e+07", "%+10.1RUe", x);
    check_sprintf ("    -1e+07", "%+10.0RUe", x);
    check_sprintf ("    -0e+00", "%+10.0RUe", z);
    check_sprintf ("        -0", "%+10.0RUf", z);


    /* neighborhood of 1 */
    mpfr_set_str (x, "0.99993896484375", 10, MPFR_RNDN);
    check_sprintf ("9.9993896484375E-01 ", "%-20RE", x);
    check_sprintf ("9.9993896484375E-01 ", "%-20.RE", x);
    check_sprintf ("1E+00               ", "%-20.0RE", x);
    check_sprintf ("1.0E+00             ", "%-20.1RE", x);
    check_sprintf ("1.00E+00            ", "%-20.2RE", x);
    check_sprintf ("9.999E-01           ", "%-20.3RE", x);
    check_sprintf ("9.9994E-01          ", "%-20.4RE", x);
    check_sprintf ("0.999939            ", "%-20RF", x);
    check_sprintf ("0.999939            ", "%-20.RF", x);
    check_sprintf ("1                   ", "%-20.0RF", x);
    check_sprintf ("1.0                 ", "%-20.1RF", x);
    check_sprintf ("1.00                ", "%-20.2RF", x);
    check_sprintf ("1.000               ", "%-20.3RF", x);
    check_sprintf ("0.9999              ", "%-20.4RF", x);
    check_sprintf ("0.999939            ", "%-#20RF", x);
    check_sprintf ("0.999939            ", "%-#20.RF", x);
    check_sprintf ("1.                  ", "%-#20.0RF", x);
    check_sprintf ("1.0                 ", "%-#20.1RF", x);
    check_sprintf ("1.00                ", "%-#20.2RF", x);
    check_sprintf ("1.000               ", "%-#20.3RF", x);
    check_sprintf ("0.9999              ", "%-#20.4RF", x);
    check_sprintf ("1                   ", "%-20.0RG", x);
    check_sprintf ("1                   ", "%-20.1RG", x);
    check_sprintf ("1                   ", "%-20.2RG", x);
    check_sprintf ("1                   ", "%-20.3RG", x);
    check_sprintf ("0.9999              ", "%-20.4RG", x);
    check_sprintf ("0.999939            ", "%-#20RG", x);
    check_sprintf ("0.999939            ", "%-#20.RG", x);
    check_sprintf ("1.                  ", "%-#20.0RG", x);
    check_sprintf ("1.                  ", "%-#20.1RG", x);
    check_sprintf ("1.0                 ", "%-#20.2RG", x);
    check_sprintf ("1.00                ", "%-#20.3RG", x);
    check_sprintf ("0.9999              ", "%-#20.4RG", x);

    /* multiple of 10 */
    mpfr_set_str (x, "1e17", 10, MPFR_RNDN);
    check_sprintf ("1e+17", "%Re", x);
    check_sprintf ("1.000e+17", "%.3Re", x);
    check_sprintf ("100000000000000000", "%.0Rf", x);
    check_sprintf ("100000000000000000.0", "%.1Rf", x);
    check_sprintf ("100000000000000000.000000", "%'Rf", x);
    check_sprintf ("100000000000000000.0", "%'.1Rf", x);

    mpfr_ui_div (x, 1, x, MPFR_RNDN); /* x=1e-17 */
    check_sprintf ("1e-17", "%Re", x);
    check_sprintf ("0.000000", "%Rf", x);
    check_sprintf ("1e-17", "%Rg", x);
    check_sprintf ("0.0", "%.1RDf", x);
    check_sprintf ("0.0", "%.1RZf", x);
    check_sprintf ("0.1", "%.1RUf", x);
    check_sprintf ("0.1", "%.1RYf", x);
    check_sprintf ("0", "%.0RDf", x);
    check_sprintf ("0", "%.0RZf", x);
    check_sprintf ("1", "%.0RUf", x);
    check_sprintf ("1", "%.0RYf", x);

    /* multiple of 10 with 'g' style */
    mpfr_set_str (x, "10", 10, MPFR_RNDN);
    check_sprintf ("10", "%Rg", x);
    check_sprintf ("1e+01", "%.0Rg", x);
    check_sprintf ("1e+01", "%.1Rg", x);
    check_sprintf ("10", "%.2Rg", x);

    mpfr_ui_div (x, 1, x, MPFR_RNDN);
    check_sprintf ("0.1", "%Rg", x);
    check_sprintf ("0.1", "%.0Rg", x);
    check_sprintf ("0.1", "%.1Rg", x);

    mpfr_set_str (x, "1000", 10, MPFR_RNDN);
    check_sprintf ("1000", "%Rg", x);
    check_sprintf ("1e+03", "%.0Rg", x);
    check_sprintf ("1e+03", "%.3Rg", x);
    check_sprintf ("1000", "%.4Rg", x);

    mpfr_ui_div (x, 1, x, MPFR_RNDN);
    check_sprintf ("0.001", "%Rg", x);
    check_sprintf ("0.001", "%.0Rg", x);
    check_sprintf ("0.001", "%.1Rg", x);

    mpfr_set_str (x, "100000", 10, MPFR_RNDN);
    check_sprintf ("100000", "%Rg", x);
    check_sprintf ("1e+05", "%.0Rg", x);
    check_sprintf ("1e+05", "%.5Rg", x);
    check_sprintf ("100000", "%.6Rg", x);

    mpfr_ui_div (x, 1, x, MPFR_RNDN);
    check_sprintf ("1e-05", "%Rg", x);
    check_sprintf ("1e-05", "%.0Rg", x);
    check_sprintf ("1e-05", "%.1Rg", x);

    /* check rounding mode */
    mpfr_set_str (x, "0.0076", 10, MPFR_RNDN);
    check_sprintf ("0.007", "%.3RDF", x);
    check_sprintf ("0.007", "%.3RZF", x);
    check_sprintf ("0.008", "%.3RF", x);
    check_sprintf ("0.008", "%.3RUF", x);
    check_sprintf ("0.008", "%.3RYF", x);
    check_vsprintf ("0.008", "%.3R*F", MPFR_RNDA, x);

    /* check limit between %f-style and %g-style */
    mpfr_set_str (x, "0.0000999", 10, MPFR_RNDN);
    check_sprintf ("0.0001",   "%.0Rg", x);
    check_sprintf ("9e-05",    "%.0RDg", x);
    check_sprintf ("0.0001",   "%.1Rg", x);
    check_sprintf ("0.0001",   "%.2Rg", x);
    check_sprintf ("9.99e-05", "%.3Rg", x);

    /* trailing zeros */
    mpfr_set_si_2exp (x, -1, -15, MPFR_RNDN); /* x=-2^-15 */
    check_sprintf ("-3.0517578125e-05", "%.30Rg", x);
    check_sprintf ("-3.051757812500000000000000000000e-05", "%.30Re", x);
    check_sprintf ("-3.05175781250000000000000000000e-05", "%#.30Rg", x);
    check_sprintf ("-0.000030517578125000000000000000", "%.30Rf", x);

    /* bug 20081023 */
    check_sprintf ("-3.0517578125e-05", "%.30Rg", x);
    mpfr_set_str (x, "1.9999", 10, MPFR_RNDN);
    check_sprintf ("1.999900  ", "%-#10.7RG", x);
    check_sprintf ("1.9999    ", "%-10.7RG", x);
    mpfr_set_ui (x, 1, MPFR_RNDN);
    check_sprintf ("1.00000000000000000000000000000", "%#.30Rg", x);
    check_sprintf ("1", "%.30Rg", x);
    mpfr_set_ui (x, 0, MPFR_RNDN);
    check_sprintf ("0.000000000000000000000000000000", "%#.30Rg", x);
    check_sprintf ("0", "%.30Rg", x);

    /* following tests with precision 53 bits */
    mpfr_set_prec (x, 53);

    /* Exponent zero has a plus sign */
    mpfr_set_str (x, "-9.95645044213728791504536275169812142849e-01", 10,
                  MPFR_RNDN);
    check_sprintf ("-1.0e+00", "%- #0.1Re", x);

    /* Decimal point and no figure after it with '#' flag and 'G' style */
    mpfr_set_str (x, "-9.90597761233942053494e-01", 10, MPFR_RNDN);
    check_sprintf ("-1.", "%- #0.1RG", x);

    /* precision zero */
    mpfr_set_d (x, 9.5, MPFR_RNDN);
    check_sprintf ("9",    "%.0RDf", x);
    check_sprintf ("10",    "%.0RUf", x);

    mpfr_set_d (x, 19.5, MPFR_RNDN);
    check_sprintf ("19",    "%.0RDf", x);
    check_sprintf ("20",    "%.0RUf", x);

    mpfr_set_d (x, 99.5, MPFR_RNDN);
    check_sprintf ("99",    "%.0RDf", x);
    check_sprintf ("100",   "%.0RUf", x);

    mpfr_set_d (x, -9.5, MPFR_RNDN);
    check_sprintf ("-10",    "%.0RDf", x);
    check_sprintf ("-10",    "%.0RYf", x);
    check_sprintf ("-10",    "%.0Rf", x);
    check_sprintf ("-1e+01", "%.0Re", x);
    check_sprintf ("-1e+01", "%.0Rg", x);
    mpfr_set_ui_2exp (x, 1, -1, MPFR_RNDN);
    check_sprintf ("0",      "%.0Rf", x);
    check_sprintf ("5e-01",  "%.0Re", x);
    check_sprintf ("0.5",    "%.0Rg", x);
    mpfr_set_ui_2exp (x, 3, -1, MPFR_RNDN);
    check_sprintf ("2",      "%.0Rf", x);
    mpfr_set_ui_2exp (x, 5, -1, MPFR_RNDN);
    check_sprintf ("2",      "%.0Rf", x);
    mpfr_set_ui (x, 0x1f, MPFR_RNDN);
    check_sprintf ("0x1p+5", "%.0Ra", x);
    mpfr_set_ui (x, 3, MPFR_RNDN);
    check_sprintf ("1p+2",   "%.0Rb", x);

    /* round to next ten power with %f but not with %g */
    mpfr_set_str (x, "-6.64464380544039223686e-02", 10, MPFR_RNDN);
    check_sprintf ("-0.1",  "%.1Rf", x);
    check_sprintf ("-0.0",  "%.1RZf", x);
    check_sprintf ("-0.07", "%.1Rg", x);
    check_sprintf ("-0.06", "%.1RZg", x);

    /* round to next ten power and do not remove trailing zeros */
    mpfr_set_str (x, "9.98429393291486722006e-02", 10, MPFR_RNDN);
    check_sprintf ("0.1",   "%#.1Rg", x);
    check_sprintf ("0.10",  "%#.2Rg", x);
    check_sprintf ("0.099", "%#.2RZg", x);

    /* Halfway cases */
    mpfr_set_str (x, "1.5", 10, MPFR_RNDN);
    check_sprintf ("2e+00", "%.0Re", x);
    mpfr_set_str (x, "2.5", 10, MPFR_RNDN);
    check_sprintf ("2e+00", "%.0Re", x);
    mpfr_set_str (x, "9.5", 10, MPFR_RNDN);
    check_sprintf ("1e+01", "%.0Re", x);
    mpfr_set_str (x, "1.25", 10, MPFR_RNDN);
    check_sprintf ("1.2e+00", "%.1Re", x);
    mpfr_set_str (x, "1.75", 10, MPFR_RNDN);
    check_sprintf ("1.8e+00", "%.1Re", x);
    mpfr_set_str (x, "-0.5", 10, MPFR_RNDN);
    check_sprintf ("-0", "%.0Rf", x);
    mpfr_set_str (x, "1.25", 10, MPFR_RNDN);
    check_sprintf ("1.2", "%.1Rf", x);
    mpfr_set_str (x, "1.75", 10, MPFR_RNDN);
    check_sprintf ("1.8", "%.1Rf", x);
    mpfr_set_str (x, "1.5", 10, MPFR_RNDN);
    check_sprintf ("2", "%.1Rg", x);
    mpfr_set_str (x, "2.5", 10, MPFR_RNDN);
    check_sprintf ("2", "%.1Rg", x);
    mpfr_set_str (x, "9.25", 10, MPFR_RNDN);
    check_sprintf ("9.2", "%.2Rg", x);
    mpfr_set_str (x, "9.75", 10, MPFR_RNDN);
    check_sprintf ("9.8", "%.2Rg", x);

    /* assertion failure in r6320 */
    mpfr_set_str (x, "-9.996", 10, MPFR_RNDN);
    check_sprintf ("-10.0", "%.1Rf", x);

    /* regression in MPFR 3.1.0 (bug introduced in r7761, fixed in r7931) */
    check_sprintf ("-10", "%.2Rg", x);

    mpfr_clears (x, z, (mpfr_ptr) 0);
    return 0;
}
Ejemplo n.º 17
0
/* Implements asymptotic expansion for jn or yn (formulae 9.2.5 and 9.2.6
   from Abramowitz & Stegun).
   Assumes |z| > p log(2)/2, where p is the target precision
   (z can be negative only for jn).
   Return 0 if the expansion does not converge enough (the value 0 as inexact
   flag should not happen for normal input).
*/
static int
FUNCTION (mpfr_ptr res, long n, mpfr_srcptr z, mpfr_rnd_t r)
{
  mpfr_t s, c, P, Q, t, iz, err_t, err_s, err_u;
  mpfr_prec_t w;
  long k;
  int inex, stop, diverge = 0;
  mpfr_exp_t err2, err;
  MPFR_ZIV_DECL (loop);

  mpfr_init (c);

  w = MPFR_PREC(res) + MPFR_INT_CEIL_LOG2(MPFR_PREC(res)) + 4;

  MPFR_ZIV_INIT (loop, w);
  for (;;)
    {
      mpfr_set_prec (c, w);
      mpfr_init2 (s, w);
      mpfr_init2 (P, w);
      mpfr_init2 (Q, w);
      mpfr_init2 (t, w);
      mpfr_init2 (iz, w);
      mpfr_init2 (err_t, 31);
      mpfr_init2 (err_s, 31);
      mpfr_init2 (err_u, 31);

      /* Approximate sin(z) and cos(z). In the following, err <= k means that
         the approximate value y and the true value x are related by
         y = x * (1 + u)^k with |u| <= 2^(-w), following Higham's method. */
      mpfr_sin_cos (s, c, z, MPFR_RNDN);
      if (MPFR_IS_NEG(z))
        mpfr_neg (s, s, MPFR_RNDN); /* compute jn/yn(|z|), fix sign later */
      /* The absolute error on s/c is bounded by 1/2 ulp(1/2) <= 2^(-w-1). */
      mpfr_add (t, s, c, MPFR_RNDN);
      mpfr_sub (c, s, c, MPFR_RNDN);
      mpfr_swap (s, t);
      /* now s approximates sin(z)+cos(z), and c approximates sin(z)-cos(z),
         with total absolute error bounded by 2^(1-w). */

      /* precompute 1/(8|z|) */
      mpfr_si_div (iz, MPFR_IS_POS(z) ? 1 : -1, z, MPFR_RNDN);   /* err <= 1 */
      mpfr_div_2ui (iz, iz, 3, MPFR_RNDN);

      /* compute P and Q */
      mpfr_set_ui (P, 1, MPFR_RNDN);
      mpfr_set_ui (Q, 0, MPFR_RNDN);
      mpfr_set_ui (t, 1, MPFR_RNDN); /* current term */
      mpfr_set_ui (err_t, 0, MPFR_RNDN); /* error on t */
      mpfr_set_ui (err_s, 0, MPFR_RNDN); /* error on P and Q (sum of errors) */
      for (k = 1, stop = 0; stop < 4; k++)
        {
          /* compute next term: t(k)/t(k-1) = (2n+2k-1)(2n-2k+1)/(8kz) */
          mpfr_mul_si (t, t, 2 * (n + k) - 1, MPFR_RNDN); /* err <= err_k + 1 */
          mpfr_mul_si (t, t, 2 * (n - k) + 1, MPFR_RNDN); /* err <= err_k + 2 */
          mpfr_div_ui (t, t, k, MPFR_RNDN);               /* err <= err_k + 3 */
          mpfr_mul (t, t, iz, MPFR_RNDN);                 /* err <= err_k + 5 */
          /* the relative error on t is bounded by (1+u)^(5k)-1, which is
             bounded by 6ku for 6ku <= 0.02: first |5 log(1+u)| <= |5.5u|
             for |u| <= 0.15, then |exp(5.5u)-1| <= 6u for |u| <= 0.02. */
          mpfr_mul_ui (err_t, t, 6 * k, MPFR_IS_POS(t) ? MPFR_RNDU : MPFR_RNDD);
          mpfr_abs (err_t, err_t, MPFR_RNDN); /* exact */
          /* the absolute error on t is bounded by err_t * 2^(-w) */
          mpfr_abs (err_u, t, MPFR_RNDU);
          mpfr_mul_2ui (err_u, err_u, w, MPFR_RNDU); /* t * 2^w */
          mpfr_add (err_u, err_u, err_t, MPFR_RNDU); /* max|t| * 2^w */
          if (stop >= 2)
            {
              /* take into account the neglected terms: t * 2^w */
              mpfr_div_2ui (err_s, err_s, w, MPFR_RNDU);
              if (MPFR_IS_POS(t))
                mpfr_add (err_s, err_s, t, MPFR_RNDU);
              else
                mpfr_sub (err_s, err_s, t, MPFR_RNDU);
              mpfr_mul_2ui (err_s, err_s, w, MPFR_RNDU);
              stop ++;
            }
          /* if k is odd, add to Q, otherwise to P */
          else if (k & 1)
            {
              /* if k = 1 mod 4, add, otherwise subtract */
              if ((k & 2) == 0)
                mpfr_add (Q, Q, t, MPFR_RNDN);
              else
                mpfr_sub (Q, Q, t, MPFR_RNDN);
              /* check if the next term is smaller than ulp(Q): if EXP(err_u)
                 <= EXP(Q), since the current term is bounded by
                 err_u * 2^(-w), it is bounded by ulp(Q) */
              if (MPFR_EXP(err_u) <= MPFR_EXP(Q))
                stop ++;
              else
                stop = 0;
            }
          else
            {
              /* if k = 0 mod 4, add, otherwise subtract */
              if ((k & 2) == 0)
                mpfr_add (P, P, t, MPFR_RNDN);
              else
                mpfr_sub (P, P, t, MPFR_RNDN);
              /* check if the next term is smaller than ulp(P) */
              if (MPFR_EXP(err_u) <= MPFR_EXP(P))
                stop ++;
              else
                stop = 0;
            }
          mpfr_add (err_s, err_s, err_t, MPFR_RNDU);
          /* the sum of the rounding errors on P and Q is bounded by
             err_s * 2^(-w) */

          /* stop when start to diverge */
          if (stop < 2 &&
              ((MPFR_IS_POS(z) && mpfr_cmp_ui (z, (k + 1) / 2) < 0) ||
               (MPFR_IS_NEG(z) && mpfr_cmp_si (z, - ((k + 1) / 2)) > 0)))
            {
              /* if we have to stop the series because it diverges, then
                 increasing the precision will most probably fail, since
                 we will stop to the same point, and thus compute a very
                 similar approximation */
              diverge = 1;
              stop = 2; /* force stop */
            }
        }
      /* the sum of the total errors on P and Q is bounded by err_s * 2^(-w) */

      /* Now combine: the sum of the rounding errors on P and Q is bounded by
         err_s * 2^(-w), and the absolute error on s/c is bounded by 2^(1-w) */
      if ((n & 1) == 0) /* n even: P * (sin + cos) + Q (cos - sin) for jn
                                   Q * (sin + cos) + P (sin - cos) for yn */
        {
#ifdef MPFR_JN
          mpfr_mul (c, c, Q, MPFR_RNDN); /* Q * (sin - cos) */
          mpfr_mul (s, s, P, MPFR_RNDN); /* P * (sin + cos) */
#else
          mpfr_mul (c, c, P, MPFR_RNDN); /* P * (sin - cos) */
          mpfr_mul (s, s, Q, MPFR_RNDN); /* Q * (sin + cos) */
#endif
          err = MPFR_EXP(c);
          if (MPFR_EXP(s) > err)
            err = MPFR_EXP(s);
#ifdef MPFR_JN
          mpfr_sub (s, s, c, MPFR_RNDN);
#else
          mpfr_add (s, s, c, MPFR_RNDN);
#endif
        }
      else /* n odd: P * (sin - cos) + Q (cos + sin) for jn,
                     Q * (sin - cos) - P (cos + sin) for yn */
        {
#ifdef MPFR_JN
          mpfr_mul (c, c, P, MPFR_RNDN); /* P * (sin - cos) */
          mpfr_mul (s, s, Q, MPFR_RNDN); /* Q * (sin + cos) */
#else
          mpfr_mul (c, c, Q, MPFR_RNDN); /* Q * (sin - cos) */
          mpfr_mul (s, s, P, MPFR_RNDN); /* P * (sin + cos) */
#endif
          err = MPFR_EXP(c);
          if (MPFR_EXP(s) > err)
            err = MPFR_EXP(s);
#ifdef MPFR_JN
          mpfr_add (s, s, c, MPFR_RNDN);
#else
          mpfr_sub (s, c, s, MPFR_RNDN);
#endif
        }
      if ((n & 2) != 0)
        mpfr_neg (s, s, MPFR_RNDN);
      if (MPFR_EXP(s) > err)
        err = MPFR_EXP(s);
      /* the absolute error on s is bounded by P*err(s/c) + Q*err(s/c)
         + err(P)*(s/c) + err(Q)*(s/c) + 3 * 2^(err - w - 1)
         <= (|P|+|Q|) * 2^(1-w) + err_s * 2^(1-w) + 2^err * 2^(1-w),
         since |c|, |old_s| <= 2. */
      err2 = (MPFR_EXP(P) >= MPFR_EXP(Q)) ? MPFR_EXP(P) + 2 : MPFR_EXP(Q) + 2;
      /* (|P| + |Q|) * 2^(1 - w) <= 2^(err2 - w) */
      err = MPFR_EXP(err_s) >= err ? MPFR_EXP(err_s) + 2 : err + 2;
      /* err_s * 2^(1-w) + 2^old_err * 2^(1-w) <= 2^err * 2^(-w) */
      err2 = (err >= err2) ? err + 1 : err2 + 1;
      /* now the absolute error on s is bounded by 2^(err2 - w) */

      /* multiply by sqrt(1/(Pi*z)) */
      mpfr_const_pi (c, MPFR_RNDN);     /* Pi, err <= 1 */
      mpfr_mul (c, c, z, MPFR_RNDN);    /* err <= 2 */
      mpfr_si_div (c, MPFR_IS_POS(z) ? 1 : -1, c, MPFR_RNDN); /* err <= 3 */
      mpfr_sqrt (c, c, MPFR_RNDN);      /* err<=5/2, thus the absolute error is
                                          bounded by 3*u*|c| for |u| <= 0.25 */
      mpfr_mul (err_t, c, s, MPFR_SIGN(c)==MPFR_SIGN(s) ? MPFR_RNDU : MPFR_RNDD);
      mpfr_abs (err_t, err_t, MPFR_RNDU);
      mpfr_mul_ui (err_t, err_t, 3, MPFR_RNDU);
      /* 3*2^(-w)*|old_c|*|s| [see below] is bounded by err_t * 2^(-w) */
      err2 += MPFR_EXP(c);
      /* |old_c| * 2^(err2 - w) [see below] is bounded by 2^(err2-w) */
      mpfr_mul (c, c, s, MPFR_RNDN);    /* the absolute error on c is bounded by
                                          1/2 ulp(c) + 3*2^(-w)*|old_c|*|s|
                                          + |old_c| * 2^(err2 - w) */
      /* compute err_t * 2^(-w) + 1/2 ulp(c) = (err_t + 2^EXP(c)) * 2^(-w) */
      err = (MPFR_EXP(err_t) > MPFR_EXP(c)) ? MPFR_EXP(err_t) + 1 : MPFR_EXP(c) + 1;
      /* err_t * 2^(-w) + 1/2 ulp(c) <= 2^(err - w) */
      /* now err_t * 2^(-w) bounds 1/2 ulp(c) + 3*2^(-w)*|old_c|*|s| */
      err = (err >= err2) ? err + 1 : err2 + 1;
      /* the absolute error on c is bounded by 2^(err - w) */

      mpfr_clear (s);
      mpfr_clear (P);
      mpfr_clear (Q);
      mpfr_clear (t);
      mpfr_clear (iz);
      mpfr_clear (err_t);
      mpfr_clear (err_s);
      mpfr_clear (err_u);

      err -= MPFR_EXP(c);
      if (MPFR_LIKELY (MPFR_CAN_ROUND (c, w - err, MPFR_PREC(res), r)))
        break;
      if (diverge != 0)
        {
          mpfr_set (c, z, r); /* will force inex=0 below, which means the
                               asymptotic expansion failed */
          break;
        }
      MPFR_ZIV_NEXT (loop, w);
    }
  MPFR_ZIV_FREE (loop);

  inex = (MPFR_IS_POS(z) || ((n & 1) == 0)) ? mpfr_set (res, c, r)
    : mpfr_neg (res, c, r);
  mpfr_clear (c);

  return inex;
}
Ejemplo n.º 18
0
/* 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);
}
Ejemplo n.º 19
0
int main() {

	int op;
	bool res=0; 
	long int per=100;
	int no, *ptr,*temp,n1,i;
	double n,k,j,pcomp,cnt=0;
	double x;
//	******************************************Calculate original probability ****************************************
	mpfr_t p,t; 
	mpfr_init2(p,100); // declare probability with a pecision of 100 so that smaller probabilities dont get truncated to zero
	mpfr_set_d (p, 1.0, MPFR_RNDD); //initialise p with 1.0
	mpfr_init2(t,100);
	mpfr_set_d (t, 1.0, MPFR_RNDD);
	printf("Enter the number of people :\n"); //Number of people to form a group of
	scanf("%lf",&k);
	printf("Choose :\nLeap Year(1)\nNormal Year(2)\n"); // Choose if its a normal year or a leap year
	scanf("%d",&op);
	if(op==1)
		n=366;
	else if(op==2)
		n=365;		
	for(i=1;i<=k;i++) //this loop calculates the probability that two people dont have birthdays on the same day
	{
		x=(n-i+1)/n;
		mpfr_mul_d(p, p,x, MPFR_RNDD);
	}
	mpfr_sub(p,t,p,MPFR_RNDD); // 1-probability that no two people have birthdays on the same day
	mpfr_mul_si(p,p,per,MPFR_RNDD); //Percentage
	printf ("Expected Probability in Percentage : ");
	mpfr_printf ("%.64Rf ", p);
    putchar ('\n');
    mpfr_clear(p);
    mpfr_clear(t);
    
//  ****************************************Verification of this paradox**********************************************
    
    printf("Enter the number of trials you want to take :\n"); //number of trials to take to confirm the resultant probaility
    scanf("%d",&no);	
    ptr=(int *)malloc(k*sizeof(int)); //Assign memory space for an array of k people for each test case
    temp=ptr;
    for(j=0;j<no;j++)
    {
    	ptr=temp;
   		res=0;
    	for(i=0,n1=(int)n;i<k;i++,ptr++)
    		*ptr=(rand()%n1)+1; //randomly select nth day from 365/366 days for assigning birthdays
    	ptr=temp;
    	qsort(ptr,k,sizeof(int),compare_int); //sort the array using quick sort
    	ptr=temp;
    	for(i=0;i<k;i++,ptr++)
   	 	{
    		if(*ptr==*(ptr+1)) //comparing if two people have birthdays on the same day
				{
					res=1;  
					break;
				}  		
		}		
		if(res==1)
			cnt++; //increase the count of tests which turned out to be positive from total number of trials
	}
	pcomp = (cnt/no) *100; //percentage of success cases 
	printf("Actual Probability in Percentage : %lf  \n",pcomp);	
	return 0;
}
Ejemplo n.º 20
0
/* Returns >= zero iff successful */
static int find_triple_64(int i, int min_leeway, int perfect_leeway, mpfr_fn
                          sin_fn, mpfr_fn cos_fn)
{
        /*
           Using mpfr is not entirely overkill for this; [Lut95]
           includes PASCAL fragments that use almost entirely integer
           arithmetic... but the error term in that only handles
           up to 13 extra bits of zeroes or so. We proudly boast
           at least 16 bits of extra zeroes in all cases.
         */
        mpfr_t xi;
        mpfr_t xip1;
        mpfr_t cos;
        mpfr_t sin;
        double xip1_d;
        double t;
        uint64_t sin_u;
        uint64_t cos_u;
        int e1;
        int e2;
        uint64_t xip1_u;
        double xi_initial;
        uint64_t xi_initial_u;
        double xi_current;
        uint64_t xi_current_u;
        long int r = 0;
        long int best_r = 0;
        int sgn = 1;
        int ml = min_leeway;
        int best_l = 0;
        uint64_t best_xi_u;
        uint64_t best_sin_u;
        uint64_t best_cos_u;
        time_t start;
        time_t end;

        start = time(0);
        mpfr_init2(xi, 100);
        mpfr_init2(xip1, 100);
        mpfr_init2(cos, 100);
        mpfr_init2(sin, 100);

        /* start out at xi = πi/(4N) */
        mpfr_const_pi(xi, MPFR_RNDN);
        mpfr_mul_si(xip1, xi, (long int) (i + 1), MPFR_RNDN);
        mpfr_mul_si(xi, xi, (long int) i, MPFR_RNDN);
        mpfr_div_si(xi, xi, (long int) 4 * N, MPFR_RNDN);
        mpfr_div_si(xip1, xip1, (long int) 4 * N, MPFR_RNDN);
        xip1_d = mpfr_get_d(xip1, MPFR_RNDN);
        xip1_u = FLT64_TO_UINT64(xip1_d);
        xi_initial = mpfr_get_d(xi, MPFR_RNDN);
        xi_initial_u = FLT64_TO_UINT64(xi_initial);

        while (1) {
                xi_current_u = xi_initial_u + (sgn * r);
                xi_current = UINT64_TO_FLT64(xi_current_u);
                mpfr_set_d(xi, xi_current, MPFR_RNDN);

                /* Test if cos(xi) has enough zeroes */
                cos_fn(cos, xi, MPFR_RNDN);
                t = mpfr_get_d(cos, MPFR_RNDN);
                cos_u = FLT64_TO_UINT64(t);
                e1 = EXP_OF_FLT64(t);
                mpfr_sub_d(cos, cos, t, MPFR_RNDN);
                t = mpfr_get_d(cos, MPFR_RNDN);
                e2 = EXP_OF_FLT64(t);

                if (e2 == -1024) {

                        /* Damn; this is too close to a subnormal. i = 0 or N? */
                        return -1;
                }

                if (e1 - e2 < (52 + min_leeway)) {
                        goto inc;
                }

                ml = xmax(min_leeway, e1 - e2 - 52);

                /* Test if sin(xi) has enough zeroes */
                sin_fn(sin, xi, MPFR_RNDN);
                t = mpfr_get_d(sin, MPFR_RNDN);
                sin_u = FLT64_TO_UINT64(t);
                e1 = EXP_OF_FLT64(t);
                mpfr_sub_d(sin, sin, t, MPFR_RNDN);
                t = mpfr_get_d(sin, MPFR_RNDN);
                e2 = EXP_OF_FLT64(t);

                if (e2 == -1024) {

                        /* Damn; this is too close to a subnormal. i = 0 or N? */
                        return -1;
                }

                if (e1 - e2 < (52 + min_leeway)) {
                        goto inc;
                }

                ml = xmin(ml, e1 - e2 - 52);

                /* Hurrah, this is valid */
                if (ml > best_l) {
                        best_l = ml;
                        best_xi_u = xi_current_u;
                        best_cos_u = cos_u;
                        best_sin_u = sin_u;
                        best_r = sgn * r;

                        /* If this is super-good, don't bother finding more */
                        if (best_l >= perfect_leeway) {
                                break;
                        }
                }

inc:

                /* Increment */
                sgn *= -1;

                if (sgn < 0) {
                        r++;
                } else if (r > (1 << 29) ||
                           xi_current_u > xip1_u) {
                        /*
                           This is taking too long, give up looking
                           for perfection and take the best we've
                           got. A sweep of 1 << 28 finishes in ~60
                           hrs on my personal machine as I write
                           this.
                         */
                        break;
                }
        }

        end = time(0);

        if (best_l > min_leeway) {
                printf(
                        "(%#018lx, %#018lx, %#018lx), /* i = %03d, l = %02d, r = %010ld, t = %ld */ \n",
                        best_xi_u, best_cos_u, best_sin_u, i, best_l, best_r,
                        end -
                        start);

                return 0;
        } else {
                return -1;
        }
}
Ejemplo n.º 21
0
int
mpfr_log (mpfr_ptr r, mpfr_srcptr a, mpfr_rnd_t rnd_mode)
{
  int inexact;
  mpfr_prec_t p, q;
  mpfr_t tmp1, tmp2;
  MPFR_SAVE_EXPO_DECL (expo);
  MPFR_ZIV_DECL (loop);
  MPFR_GROUP_DECL(group);

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

  /* Special cases */
  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_set_divby0 ();
          MPFR_RET (0); /* log(0) is an exact -infinity */
        }
    }
  /* If a is negative, the result is NaN */
  else if (MPFR_UNLIKELY (MPFR_IS_NEG (a)))
    {
      MPFR_SET_NAN (r);
      MPFR_RET_NAN;
    }
  /* If a is 1, the result is 0 */
  else if (MPFR_UNLIKELY (MPFR_GET_EXP (a) == 1 && 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 */
    }

  q = MPFR_PREC (r);

  /* use initial precision about q+lg(q)+5 */
  p = q + 5 + 2 * MPFR_INT_CEIL_LOG2 (q);
  /* % ~(mpfr_prec_t)GMP_NUMB_BITS  ;
     m=q; while (m) { p++; m >>= 1; }  */
  /* if (MPFR_LIKELY(p % GMP_NUMB_BITS != 0))
      p += GMP_NUMB_BITS - (p%GMP_NUMB_BITS); */

  MPFR_SAVE_EXPO_MARK (expo);
  MPFR_GROUP_INIT_2 (group, p, tmp1, tmp2);

  MPFR_ZIV_INIT (loop, p);
  for (;;)
    {
      long m;
      mpfr_exp_t cancel;

      /* Calculus of m (depends on p) */
      m = (p + 1) / 2 - MPFR_GET_EXP (a) + 1;

      mpfr_mul_2si (tmp2, a, m, MPFR_RNDN);    /* s=a*2^m,        err<=1 ulp  */
      mpfr_div (tmp1, __gmpfr_four, tmp2, MPFR_RNDN);/* 4/s,      err<=2 ulps */
      mpfr_agm (tmp2, __gmpfr_one, tmp1, MPFR_RNDN); /* AG(1,4/s),err<=3 ulps */
      mpfr_mul_2ui (tmp2, tmp2, 1, MPFR_RNDN); /* 2*AG(1,4/s),    err<=3 ulps */
      mpfr_const_pi (tmp1, MPFR_RNDN);         /* compute pi,     err<=1ulp   */
      mpfr_div (tmp2, tmp1, tmp2, MPFR_RNDN);  /* pi/2*AG(1,4/s), err<=5ulps  */
      mpfr_const_log2 (tmp1, MPFR_RNDN);      /* compute log(2),  err<=1ulp   */
      mpfr_mul_si (tmp1, tmp1, m, MPFR_RNDN); /* compute m*log(2),err<=2ulps  */
      mpfr_sub (tmp1, tmp2, tmp1, MPFR_RNDN); /* log(a),    err<=7ulps+cancel */

      if (MPFR_LIKELY (MPFR_IS_PURE_FP (tmp1) && MPFR_IS_PURE_FP (tmp2)))
        {
          cancel = MPFR_GET_EXP (tmp2) - MPFR_GET_EXP (tmp1);
          MPFR_LOG_MSG (("canceled bits=%ld\n", (long) cancel));
          MPFR_LOG_VAR (tmp1);
          if (MPFR_UNLIKELY (cancel < 0))
            cancel = 0;

          /* we have 7 ulps of error from the above roundings,
             4 ulps from the 4/s^2 second order term,
             plus the canceled bits */
          if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp1, p-cancel-4, q, rnd_mode)))
            break;

          /* VL: I think it is better to have an increment that it isn't
             too low; in particular, the increment must be positive even
             if cancel = 0 (can this occur?). */
          p += cancel >= 8 ? cancel : 8;
        }
      else
        {
          /* TODO: find why this case can occur and what is best to do
             with it. */
          p += 32;
        }

      MPFR_ZIV_NEXT (loop, p);
      MPFR_GROUP_REPREC_2 (group, p, tmp1, tmp2);
    }
  MPFR_ZIV_FREE (loop);
  inexact = mpfr_set (r, tmp1, rnd_mode);
  /* We clean */
  MPFR_GROUP_CLEAR (group);

  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (r, inexact, rnd_mode);
}