void fmprb_mul_main_naive(fmprb_t z, const fmprb_t x, const fmprb_t y, slong prec) { if (fmpr_is_pos_inf(fmprb_radref(x)) || fmpr_is_pos_inf(fmprb_radref(y))) { fmpr_mul(fmprb_midref(z), fmprb_midref(x), fmprb_midref(y), prec, FMPR_RND_DOWN); fmpr_pos_inf(fmprb_radref(z)); } else { fmpr_t t, u; slong r; fmpr_init(t); fmpr_init(u); /* (x+a)*(y+b) = x*y + x*b + y*a + a*b*/ fmpr_mul(t, fmprb_midref(x), fmprb_radref(y), FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_abs(t, t); fmpr_mul(u, fmprb_midref(y), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_abs(u, u); fmpr_add(t, t, u, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_addmul(t, fmprb_radref(x), fmprb_radref(y), FMPRB_RAD_PREC, FMPR_RND_UP); r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), fmprb_midref(y), prec, FMPR_RND_DOWN); fmpr_add_error_result(fmprb_radref(z), t, fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_clear(t); fmpr_clear(u); } }
void fmprb_sqrt(fmprb_t z, const fmprb_t x, slong prec) { slong r; if (fmprb_contains_negative(x)) { fmpr_nan(fmprb_midref(z)); fmpr_pos_inf(fmprb_radref(z)); return; } if (fmprb_is_exact(x)) { r = fmpr_sqrt(fmprb_midref(z), fmprb_midref(x), prec, FMPR_RND_DOWN); fmpr_set_error_result(fmprb_radref(z), fmprb_midref(z), r); } else { fmpr_t err; fmpr_init(err); fmpr_sub(err, fmprb_midref(x), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_DOWN); fmpr_rsqrt(err, err, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul(err, fmprb_radref(x), err, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul_2exp_si(err, err, -1); r = fmpr_sqrt(fmprb_midref(z), fmprb_midref(x), prec, FMPR_RND_DOWN); fmpr_add_error_result(fmprb_radref(z), err, fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_clear(err); } fmprb_adjust(z); }
void gamma_taylor_bound_remainder(fmpr_t err, const fmpr_t z, long n) { fmpr_t t, u; gamma_taylor_bound_extend_cache(n + 1); fmpr_init(t); fmpr_init(u); /* denominator: 1 - r(n+1) * z, rounded down */ fmpr_mul(t, gamma_taylor_bound_ratio_cache + n + 1, z, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_one(u); fmpr_sub(u, u, t, FMPRB_RAD_PREC, FMPR_RND_DOWN); if (fmpr_sgn(u) <= 0) { fmpr_pos_inf(err); } else { fmpr_pow_sloppy_ui(t, z, n, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul_2exp_si(t, t, gamma_taylor_bound_mag_cache[n + 1]); fmpr_div(err, t, u, FMPRB_RAD_PREC, FMPR_RND_UP); } fmpr_clear(t); fmpr_clear(u); }
void fmprb_mul_fmpr_naive(fmprb_t z, const fmprb_t x, const fmpr_t y, slong prec) { /* (x+a) * y = x*y + y*a */ if (fmpr_is_pos_inf(fmprb_radref(x))) { fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN); fmpr_pos_inf(fmprb_radref(z)); } else if (fmpr_is_zero(fmprb_radref(x))) { slong r; r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN); fmpr_set_error_result(fmprb_radref(z), fmprb_midref(z), r); } else { slong r; fmpr_mul(fmprb_radref(z), fmprb_radref(x), y, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_abs(fmprb_radref(z), fmprb_radref(z)); r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN); fmpr_add_error_result(fmprb_radref(z), fmprb_radref(z), fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP); } }
slong fmpr_rsqrt(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd) { slong r; if (fmpr_is_special(x)) { if (fmpr_is_zero(x)) fmpr_pos_inf(y); else if (fmpr_is_pos_inf(x)) fmpr_zero(y); else fmpr_nan(y); return FMPR_RESULT_EXACT; } if (fmpr_sgn(x) < 0) { fmpr_nan(y); return FMPR_RESULT_EXACT; } /* special case: 4^n */ if (fmpz_is_one(fmpr_manref(x)) && fmpz_is_even(fmpr_expref(x))) { r = fmpr_set_round(y, x, prec, rnd); fmpz_tdiv_q_2exp(fmpr_expref(y), fmpr_expref(y), 1); fmpz_neg(fmpr_expref(y), fmpr_expref(y)); return r; } { fmpr_t t; fmpz_t e; fmpr_init(t); fmpz_init(e); fmpz_neg(e, fmpr_expref(x)); if (fmpz_is_odd(e)) fmpz_add_ui(e, e, 1); fmpr_mul_2exp_fmpz(t, x, e); CALL_MPFR_FUNC(r, mpfr_rec_sqrt, y, t, prec, rnd); fmpz_tdiv_q_2exp(e, e, 1); fmpr_mul_2exp_fmpz(y, y, e); fmpr_clear(t); fmpz_clear(e); return r; } }
slong fmpr_mul_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, slong prec, fmpr_rnd_t rnd) { fmpz xv, yv; fmpz yexp; if (fmpr_is_special(x) || fmpz_is_zero(y)) { if (fmpr_is_zero(x)) { fmpr_zero(z); } else if (fmpz_is_zero(y) && fmpr_is_finite(x)) { fmpr_zero(z); } else if (fmpr_is_inf(x) && !fmpz_is_zero(y)) { if (fmpr_sgn(x) == fmpz_sgn(y)) fmpr_pos_inf(z); else fmpr_neg_inf(z); } else { fmpr_nan(z); } return FMPR_RESULT_EXACT; } xv = *fmpr_manref(x); yv = *y; if (!COEFF_IS_MPZ(xv) && !COEFF_IS_MPZ(yv)) { mp_limb_t ytmp; unsigned int bc; ytmp = FLINT_ABS(yv); count_trailing_zeros(bc, ytmp); ytmp >>= bc; yexp = bc; return _fmpr_mul_1x1(z, FLINT_ABS(xv), fmpr_expref(x), ytmp, &yexp, (xv ^ yv) < 0, prec, rnd); }
static void _fmpr_div_special(fmpr_t z, const fmpr_t x, const fmpr_t y) { if ((fmpr_is_zero(x) && !fmpr_is_zero(y) && !fmpr_is_nan(y)) || (fmpr_is_inf(y) && !fmpr_is_special(x))) { fmpr_zero(z); } else if (fmpr_is_zero(y) || (fmpr_is_special(x) && fmpr_is_special(y)) || fmpr_is_nan(x) || fmpr_is_nan(y)) { fmpr_nan(z); } else if (fmpr_sgn(x) == fmpr_sgn(y)) fmpr_pos_inf(z); else fmpr_neg_inf(z); }
void arf_get_fmpr(fmpr_t y, const arf_t x) { if (arf_is_special(x)) { if (arf_is_zero(x)) fmpr_zero(y); else if (arf_is_pos_inf(x)) fmpr_pos_inf(y); else if (arf_is_neg_inf(x)) fmpr_neg_inf(y); else fmpr_nan(y); } else { arf_get_fmpz_2exp(fmpr_manref(y), fmpr_expref(y), x); } }
void fmpr_randtest_special(fmpr_t x, flint_rand_t state, slong bits, slong mag_bits) { switch (n_randint(state, 32)) { case 0: fmpr_zero(x); break; case 1: fmpr_pos_inf(x); break; case 2: fmpr_neg_inf(x); break; case 3: fmpr_nan(x); break; default: fmpr_randtest_not_zero(x, state, bits, mag_bits); } }
void zeta_series_em_vec_bound(fmprb_ptr bound, const fmpcb_t s, const fmpcb_t a, ulong N, ulong M, long len, long wp) { fmprb_t K, C, AN, S2M; fmprb_ptr F, R; long k; fmprb_srcptr alpha = fmpcb_realref(a); fmprb_srcptr beta = fmpcb_imagref(a); fmprb_srcptr sigma = fmpcb_realref(s); fmprb_srcptr tau = fmpcb_imagref(s); fmprb_init(AN); fmprb_init(S2M); /* require alpha + N > 1, sigma + 2M > 1 */ fmprb_add_ui(AN, alpha, N - 1, wp); fmprb_add_ui(S2M, sigma, 2*M - 1, wp); if (!fmprb_is_positive(AN) || !fmprb_is_positive(S2M) || N < 1 || M < 1) { fmprb_clear(AN); fmprb_clear(S2M); for (k = 0; k < len; k++) { fmpr_pos_inf(fmprb_midref(bound + k)); fmpr_zero(fmprb_radref(bound + k)); } return; } /* alpha + N, sigma + 2M */ fmprb_add_ui(AN, AN, 1, wp); fmprb_add_ui(S2M, S2M, 1, wp); R = _fmprb_vec_init(len); F = _fmprb_vec_init(len); fmprb_init(K); fmprb_init(C); /* bound for power integral */ bound_C(C, AN, beta, wp); bound_K(K, AN, beta, tau, wp); bound_I(R, AN, S2M, C, len, wp); for (k = 0; k < len; k++) { fmprb_mul(R + k, R + k, K, wp); fmprb_div_ui(K, K, k + 1, wp); } /* bound for rising factorial */ bound_rfac(F, s, 2*M, len, wp); /* product (TODO: only need upper bound; write a function for this) */ _fmprb_poly_mullow(bound, F, len, R, len, len, wp); /* bound for bernoulli polynomials, 4 / (2pi)^(2M) */ fmprb_const_pi(C, wp); fmprb_mul_2exp_si(C, C, 1); fmprb_pow_ui(C, C, 2 * M, wp); fmprb_ui_div(C, 4, C, wp); _fmprb_vec_scalar_mul(bound, bound, len, C, wp); fmprb_clear(K); fmprb_clear(C); fmprb_clear(AN); fmprb_clear(S2M); _fmprb_vec_clear(R, len); _fmprb_vec_clear(F, len); }
static void _fmprb_gamma(fmprb_t y, const fmprb_t x, long prec, int inverse) { int reflect; long r, n, wp; fmprb_t t, u, v; if (fmprb_is_exact(x)) { const fmpr_struct * mid = fmprb_midref(x); if (fmpr_is_special(mid)) { if (!inverse && fmpr_is_pos_inf(mid)) { fmprb_set(y, x); } else if (fmpr_is_nan(mid) || fmpr_is_neg_inf(mid) || !inverse) { fmpr_nan(fmprb_midref(y)); fmpr_pos_inf(fmprb_radref(y)); } else { fmprb_zero(y); } return; } else { const fmpz exp = *fmpr_expref(mid); const fmpz man = *fmpr_manref(mid); /* fast gamma(n), gamma(n/2) or gamma(n/4) */ if (!COEFF_IS_MPZ(exp) && (exp >= -2) && ((double) fmpz_bits(&man) + exp < prec)) { fmpq_t a; fmpq_init(a); fmpr_get_fmpq(a, mid); fmprb_gamma_fmpq(y, a, prec + 2 * inverse); if (inverse) fmprb_ui_div(y, 1, y, prec); fmpq_clear(a); return; } } } wp = prec + FLINT_BIT_COUNT(prec); gamma_stirling_choose_param_fmprb(&reflect, &r, &n, x, 1, 0, wp); fmprb_init(t); fmprb_init(u); fmprb_init(v); if (reflect) { /* gamma(x) = (rf(1-x, r) * pi) / (gamma(1-x+r) sin(pi x)) */ fmprb_sub_ui(t, x, 1, wp); fmprb_neg(t, t); gamma_rising_fmprb_ui_bsplit(u, t, r, wp); fmprb_const_pi(v, wp); fmprb_mul(u, u, v, wp); fmprb_add_ui(t, t, r, wp); gamma_stirling_eval_fmprb(v, t, n, 0, wp); fmprb_exp(v, v, wp); fmprb_sin_pi(t, x, wp); fmprb_mul(v, v, t, wp); } else { /* gamma(x) = gamma(x+r) / rf(x,r) */ fmprb_add_ui(t, x, r, wp); gamma_stirling_eval_fmprb(u, t, n, 0, wp); fmprb_exp(u, u, prec); gamma_rising_fmprb_ui_bsplit(v, x, r, wp); } if (inverse) fmprb_div(y, v, u, prec); else fmprb_div(y, u, v, prec); fmprb_clear(t); fmprb_clear(u); fmprb_clear(v); }