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; }
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; }
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); }
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; }
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; }
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); }
/// @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); }
/// @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)); }
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; }
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; }
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); } }
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; }
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; }
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; }
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; }
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; }
/* 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; }
/* 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); }
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; }
/* 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; } }
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); }