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); } }
static slong _fmpr_sub_special(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd) { if (fmpr_is_zero(x)) { return fmpr_neg_round(z, y, prec, rnd); } else if (fmpr_is_zero(y)) { return fmpr_set_round(z, x, prec, rnd); } else if (fmpr_is_nan(x) || fmpr_is_nan(y) || (fmpr_is_pos_inf(x) && fmpr_is_pos_inf(y)) || (fmpr_is_neg_inf(x) && fmpr_is_neg_inf(y))) { fmpr_nan(z); return FMPR_RESULT_EXACT; } else if (fmpr_is_special(x)) { fmpr_set(z, x); return FMPR_RESULT_EXACT; } else { fmpr_neg(z, y); return FMPR_RESULT_EXACT; } }
int fmpr_get_mpfr(mpfr_t x, const fmpr_t y, mpfr_rnd_t rnd) { int r; if (fmpr_is_special(y)) { if (fmpr_is_zero(y)) mpfr_set_zero(x, 0); else if (fmpr_is_pos_inf(y)) mpfr_set_inf(x, 1); else if (fmpr_is_neg_inf(y)) mpfr_set_inf(x, -1); else mpfr_set_nan(x); r = 0; } else if (COEFF_IS_MPZ(*fmpr_expref(y))) { flint_printf("exception: exponent too large to convert to mpfr"); abort(); } else { if (!COEFF_IS_MPZ(*fmpr_manref(y))) #if defined(__MINGW64__) r = mpfr_set_sj_2exp(x, *fmpr_manref(y), *fmpr_expref(y), rnd); #else r = mpfr_set_si_2exp(x, *fmpr_manref(y), *fmpr_expref(y), rnd); #endif else r = mpfr_set_z_2exp(x, COEFF_TO_PTR(*fmpr_manref(y)), *fmpr_expref(y), rnd); if (!mpfr_regular_p(x)) { flint_printf("exception: exponent too large to convert to mpfr"); abort(); } }
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; } }
void arf_set_fmpr(arf_t y, const fmpr_t x) { if (fmpr_is_special(x)) { if (fmpr_is_zero(x)) arf_zero(y); else if (fmpr_is_pos_inf(x)) arf_pos_inf(y); else if (fmpr_is_neg_inf(x)) arf_neg_inf(y); else arf_nan(y); } else { arf_set_fmpz(y, fmpr_manref(x)); fmpz_add_inline(ARF_EXPREF(y), ARF_EXPREF(y), fmpr_expref(x)); } }
int fmpr_cmp(const fmpr_t x, const fmpr_t y) { int res, xsign, ysign; fmpr_t t; if (fmpr_equal(x, y)) return 0; if (fmpr_is_special(x) || fmpr_is_special(y)) { if (fmpr_is_nan(x) || fmpr_is_nan(y)) return 0; if (fmpr_is_zero(y)) return fmpr_sgn(x); if (fmpr_is_zero(x)) return -fmpr_sgn(y); if (fmpr_is_pos_inf(x)) return 1; if (fmpr_is_neg_inf(y)) return 1; return -1; } xsign = fmpr_sgn(x); ysign = fmpr_sgn(y); if (xsign != ysign) return (xsign < 0) ? -1 : 1; /* Reduces to integer comparison if bottom exponents are the same */ if (fmpz_equal(fmpr_expref(x), fmpr_expref(y))) return fmpz_cmp(fmpr_manref(x), fmpr_manref(y)) < 0 ? -1 : 1; /* TODO: compare position of top exponents to avoid subtraction */ fmpr_init(t); fmpr_sub(t, x, y, 2, FMPR_RND_DOWN); res = fmpr_sgn(t); fmpr_clear(t); return res; }
void fmprb_sqrtpos(fmprb_t z, const fmprb_t x, slong prec) { if (!fmprb_is_finite(x)) { if (fmpr_is_zero(fmprb_radref(x)) && fmpr_is_pos_inf(fmprb_midref(x))) fmprb_pos_inf(z); else fmprb_zero_pm_inf(z); } else if (fmprb_contains_nonpositive(x)) { fmpr_t t; fmpr_init(t); fmpr_add(t, fmprb_midref(x), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_CEIL); if (fmpr_sgn(t) <= 0) { fmprb_zero(z); } else { fmpr_sqrt(t, t, FMPRB_RAD_PREC, FMPR_RND_CEIL); fmpr_mul_2exp_si(t, t, -1); fmpr_set(fmprb_midref(z), t); fmpr_set(fmprb_radref(z), t); } fmpr_clear(t); } else { fmprb_sqrt(z, x, prec); } fmprb_nonnegative_part(z, z, prec); }
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); }