void arb_addmul_arf(arb_t z, const arb_t x, const arf_t y, slong prec) { mag_t ym; int inexact; if (arb_is_exact(x)) { inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z)) { mag_fast_init_set_arf(ym, y); mag_fast_addmul(arb_radref(z), ym, arb_radref(x)); inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_fast_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); } else { mag_init_set_arf(ym, y); mag_addmul(arb_radref(z), ym, arb_radref(x)); inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); mag_clear(ym); } }
void arb_set_interval_arf(arb_t x, const arf_t a, const arf_t b, slong prec) { arf_t t; int inexact; if (arf_is_inf(a) && arf_equal(a, b)) { /* [-inf, -inf] or [+inf, +inf] */ arf_set(arb_midref(x), a); mag_zero(arb_radref(x)); return; } arf_init(t); arf_sub(t, b, a, MAG_BITS, ARF_RND_UP); if (arf_sgn(t) < 0) { flint_printf("exception: arb_set_interval_arf: endpoints not ordered\n"); abort(); } arf_get_mag(arb_radref(x), t); inexact = arf_add(arb_midref(x), a, b, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(x), arb_radref(x), arb_midref(x), prec); arb_mul_2exp_si(x, x, -1); arf_clear(t); }
void arb_square(arb_t out, const arb_t in, slong prec) { mag_mul(arb_radref(out), arb_radref(in), arb_radref(in)); int inexact = arf_mul(arb_midref(out), arb_midref(in), arb_midref(in), ARB_RND, prec); if (inexact) arf_mag_add_ulp(arb_radref(out), arb_radref(out), arb_midref(out), prec); }
static __inline__ void arb_nonnegative_part(arb_t z, const arb_t x, long prec) { if (arb_contains_negative(x)) { arf_t t; arf_init(t); arf_set_mag(t, arb_radref(x)); arf_add(arb_midref(z), arb_midref(x), t, MAG_BITS, ARF_RND_CEIL); if (arf_sgn(arb_midref(z)) <= 0) { mag_zero(arb_radref(z)); } else { arf_mul_2exp_si(arb_midref(z), arb_midref(z), -1); arf_get_mag(arb_radref(z), arb_midref(z)); /* XXX: needed since arf_get_mag is inexact */ arf_set_mag(arb_midref(z), arb_radref(z)); } arf_clear(t); } else { arb_set(z, x); } }
void arb_max(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_t left, right, t, xr, yr; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) { arb_indeterminate(z); return; } arf_init(left); arf_init(right); arf_init(t); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); arf_sub(left, arb_midref(x), xr, prec, ARF_RND_FLOOR); arf_sub(t, arb_midref(y), yr, prec, ARF_RND_FLOOR); arf_max(left, left, t); arf_add(right, arb_midref(x), xr, prec, ARF_RND_CEIL); arf_add(t, arb_midref(y), yr, prec, ARF_RND_CEIL); arf_max(right, right, t); arb_set_interval_arf(z, left, right, prec); arf_clear(left); arf_clear(right); arf_clear(t); }
static void acb_set_dddd(acb_t z, double a, double ar, double b, double br) { arf_set_d(arb_midref(acb_realref(z)), a); mag_set_d(arb_radref(acb_realref(z)), ar); arf_set_d(arb_midref(acb_imagref(z)), b); mag_set_d(arb_radref(acb_imagref(z)), br); }
static void arb_root_arf(arb_t z, const arf_t x, ulong k, slong prec) { int inexact = arf_root(arb_midref(z), x, k, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); else mag_zero(arb_radref(z)); }
void arb_sub_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec) { int inexact; inexact = arf_sub_fmpz(arb_midref(z), arb_midref(x), y, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(x), arb_midref(z), prec); else mag_set(arb_radref(z), arb_radref(x)); }
static void _arb_arf_div_rounded_den_add_err(arb_t res, const arf_t x, const arf_t y, int yinexact, slong prec) { int inexact = arf_div(arb_midref(res), x, y, prec, ARB_RND); if (yinexact && !arf_is_special(arb_midref(res))) arf_mag_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec - 1); else if (inexact) arf_mag_add_ulp(arb_radref(res), arb_radref(res), arb_midref(res), prec); }
void acb_hypgeom_erf_propagated_error(mag_t re, mag_t im, const acb_t z) { mag_t x, y; mag_init(x); mag_init(y); /* |exp(-(x+y)^2)| = exp(y^2-x^2) */ arb_get_mag(y, acb_imagref(z)); mag_mul(y, y, y); arb_get_mag_lower(x, acb_realref(z)); mag_mul_lower(x, x, x); if (mag_cmp(y, x) >= 0) { mag_sub(re, y, x); mag_exp(re, re); } else { mag_sub_lower(re, x, y); mag_expinv(re, re); } /* Radius. */ mag_hypot(x, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_mul(re, re, x); /* 2/sqrt(pi) < 289/256 */ mag_mul_ui(re, re, 289); mag_mul_2exp_si(re, re, -8); if (arb_is_zero(acb_imagref(z))) { /* todo: could bound magnitude even for complex numbers */ mag_set_ui(y, 2); mag_min(re, re, y); mag_zero(im); } else if (arb_is_zero(acb_realref(z))) { mag_swap(im, re); mag_zero(re); } else { mag_set(im, re); } mag_clear(x); mag_clear(y); }
void arb_set_round_fmpz(arb_t y, const fmpz_t x, slong prec) { int inexact; inexact = arf_set_round_fmpz(arb_midref(y), x, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(y), arb_midref(y), prec); else mag_zero(arb_radref(y)); }
int main() { flint_printf("spherical_y...."); fflush(stdout); { slong i, n, m; acb_t z, w, x, y; acb_init(z); acb_init(w); acb_init(x); acb_init(y); i = 0; arb_set_str(acb_realref(x), "0.2", 64); arb_set_str(acb_imagref(x), "0.3", 64); arb_set_str(acb_realref(y), "0.3", 64); arb_set_str(acb_imagref(y), "0.4", 64); for (n = -4; n <= 4; n++) { for (m = -4; m <= 4; m++) { acb_hypgeom_spherical_y(z, n, m, x, y, 64); acb_set_d_d(w, testdata[2 * i], testdata[2 * i + 1]); mag_set_d(arb_radref(acb_realref(w)), 1e-13); mag_set_d(arb_radref(acb_imagref(w)), 1e-13); if (!acb_overlaps(z, w)) { flint_printf("FAIL: value\n\n"); flint_printf("n = %wd, m = %wd\n", n, m); flint_printf("z = "); acb_printd(z, 20); flint_printf("\n\n"); flint_printf("w = "); acb_printd(w, 20); flint_printf("\n\n"); abort(); } i++; } } acb_clear(z); acb_clear(w); acb_clear(x); acb_clear(y); } flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void arb_sub(arb_t z, const arb_t x, const arb_t y, slong prec) { int inexact; inexact = arf_sub(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND); mag_add(arb_radref(z), arb_radref(x), arb_radref(y)); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); }
void arb_fmpz_div_fmpz(arb_t z, const fmpz_t x, const fmpz_t y, long prec) { int inexact; inexact = arf_fmpz_div_fmpz(arb_midref(z), x, y, prec, ARB_RND); if (inexact) arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec); else mag_zero(arb_radref(z)); }
void arb_sin_cos_pi(arb_t s, arb_t c, const arb_t x, long prec) { arb_t t; arb_t u; fmpz_t v; if (arf_cmpabs_2exp_si(arb_midref(x), FLINT_MAX(65536, (4*prec))) > 0) { arf_zero(arb_midref(s)); mag_one(arb_radref(s)); arf_zero(arb_midref(c)); mag_one(arb_radref(c)); return; } arb_init(t); arb_init(u); fmpz_init(v); arb_mul_2exp_si(t, x, 1); arf_get_fmpz(v, arb_midref(t), ARF_RND_NEAR); arb_sub_fmpz(t, t, v, prec); arb_const_pi(u, prec); arb_mul(t, t, u, prec); arb_mul_2exp_si(t, t, -1); switch (fmpz_fdiv_ui(v, 4)) { case 0: arb_sin_cos(s, c, t, prec); break; case 1: arb_sin_cos(c, s, t, prec); arb_neg(c, c); break; case 2: arb_sin_cos(s, c, t, prec); arb_neg(s, s); arb_neg(c, c); break; default: arb_sin_cos(c, s, t, prec); arb_neg(s, s); break; } fmpz_clear(v); arb_clear(t); arb_clear(u); }
int check_accuracy(acb_ptr vec, slong len, slong prec) { slong i; for (i = 0; i < len; i++) { if (mag_cmp_2exp_si(arb_radref(acb_realref(vec + i)), -prec) >= 0 || mag_cmp_2exp_si(arb_radref(acb_imagref(vec + i)), -prec) >= 0) return 0; } return 1; }
/* note: the tmp variable t should have zero radius */ static void acb_approx_div(acb_t z, const acb_t x, const acb_t y, acb_t t, slong prec) { arf_set(arb_midref(acb_realref(t)), arb_midref(acb_realref(y))); arf_set(arb_midref(acb_imagref(t)), arb_midref(acb_imagref(y))); acb_inv(t, t, prec); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_approx_mul(z, x, t, prec); }
static void _acb_mul_slow(acb_t z, const acb_t x, const acb_t y, slong prec) { int inexact; mag_t am, bm, cm, dm, er, fr; mag_init_set_arf(am, arb_midref(a)); mag_init_set_arf(bm, arb_midref(b)); mag_init_set_arf(cm, arb_midref(c)); mag_init_set_arf(dm, arb_midref(d)); mag_init(er); mag_init(fr); mag_addmul(er, am, cr); mag_addmul(er, bm, dr); mag_addmul(er, cm, ar); mag_addmul(er, dm, br); mag_addmul(er, ar, cr); mag_addmul(er, br, dr); mag_addmul(fr, am, dr); mag_addmul(fr, bm, cr); mag_addmul(fr, cm, br); mag_addmul(fr, dm, ar); mag_addmul(fr, br, cr); mag_addmul(fr, ar, dr); inexact = arf_complex_mul(arb_midref(e), arb_midref(f), arb_midref(a), arb_midref(b), arb_midref(c), arb_midref(d), prec, ARB_RND); if (inexact & 1) arf_mag_add_ulp(arb_radref(e), er, arb_midref(e), prec); else mag_swap(arb_radref(e), er); if (inexact & 2) arf_mag_add_ulp(arb_radref(f), fr, arb_midref(f), prec); else mag_swap(arb_radref(f), fr); mag_clear(am); mag_clear(bm); mag_clear(cm); mag_clear(dm); mag_clear(er); mag_clear(fr); }
void arb_sinc(arb_t z, const arb_t x, slong prec) { mag_t c, r; mag_init(c); mag_init(r); mag_set_ui_2exp_si(c, 5, -1); arb_get_mag_lower(r, x); if (mag_cmp(c, r) < 0) { /* x is not near the origin */ _arb_sinc_direct(z, x, prec); } else if (mag_cmp_2exp_si(arb_radref(x), 1) < 0) { /* determine error magnitude using the derivative bound */ if (arb_is_exact(x)) { mag_zero(c); } else { _arb_sinc_derivative_bound(r, x); mag_mul(c, arb_radref(x), r); } /* evaluate sinc at the midpoint of x */ if (arf_is_zero(arb_midref(x))) { arb_one(z); } else { arb_get_mid_arb(z, x); _arb_sinc_direct(z, z, prec); } /* add the error */ mag_add(arb_radref(z), arb_radref(z), c); } else { /* x has a large radius and includes points near the origin */ arf_zero(arb_midref(z)); mag_one(arb_radref(z)); } mag_clear(c); mag_clear(r); }
/* assumes no aliasing */ slong acb_lambertw_initial(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, slong prec) { /* Handle z very close to 0 on the principal branch. */ if (fmpz_is_zero(k) && (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -20) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -20) <= 0)) { acb_set(res, z); acb_submul(res, res, res, prec); return 40; /* could be tightened... */ } /* For moderate input not close to the branch point, compute a double approximation as the initial value. */ if (fmpz_is_zero(k) && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 400) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 400) < 0 && (arf_cmp_d(arb_midref(acb_realref(z)), -0.37) < 0 || arf_cmp_d(arb_midref(acb_realref(z)), -0.36) > 0 || arf_cmpabs_d(arb_midref(acb_imagref(z)), 0.01) > 0)) { acb_lambertw_principal_d(res, z); return 48; } /* Check if we are close to the branch point at -1/e. */ if ((fmpz_is_zero(k) || (fmpz_is_one(k) && arb_is_negative(acb_imagref(z))) || (fmpz_equal_si(k, -1) && arb_is_nonnegative(acb_imagref(z)))) && ((arf_cmpabs_2exp_si(arb_midref(acb_realref(ez1)), -2) <= 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(ez1)), -2) <= 0))) { acb_t t; acb_init(t); acb_mul_2exp_si(t, ez1, 1); mag_zero(arb_radref(acb_realref(t))); mag_zero(arb_radref(acb_imagref(t))); acb_mul_ui(t, t, 3, prec); acb_sqrt(t, t, prec); if (!fmpz_is_zero(k)) acb_neg(t, t); acb_lambertw_branchpoint_series(res, t, 0, prec); acb_clear(t); return 1; /* todo: estimate */ } acb_lambertw_initial_asymp(res, z, k, prec); return 1; /* todo: estimate */ }
void arb_root_ui_algebraic(arb_t res, const arb_t x, ulong k, slong prec) { mag_t r, msubr, m1k, t; if (arb_is_exact(x)) { arb_root_arf(res, arb_midref(x), k, prec); return; } if (!arb_is_nonnegative(x)) { arb_indeterminate(res); return; } mag_init(r); mag_init(msubr); mag_init(m1k); mag_init(t); /* x = [m-r, m+r] */ mag_set(r, arb_radref(x)); /* m - r */ arb_get_mag_lower(msubr, x); /* m^(1/k) */ arb_root_arf(res, arb_midref(x), k, prec); /* bound for m^(1/k) */ arb_get_mag(m1k, res); /* C = min(1, log(1+r/(m-r))/k) */ mag_div(t, r, msubr); mag_log1p(t, t); mag_div_ui(t, t, k); if (mag_cmp_2exp_si(t, 0) > 0) mag_one(t); /* C m^(1/k) */ mag_mul(t, m1k, t); mag_add(arb_radref(res), arb_radref(res), t); mag_clear(r); mag_clear(msubr); mag_clear(m1k); mag_clear(t); }
int _arb_poly_newton_step(arb_t xnew, arb_srcptr poly, long len, const arb_t x, const arb_t convergence_interval, const arf_t convergence_factor, long prec) { arf_t err; arb_t t, u, v; int result; arf_init(err); arb_init(t); arb_init(u); arb_init(v); arf_set_mag(err, arb_radref(x)); arf_mul(err, err, err, MAG_BITS, ARF_RND_UP); arf_mul(err, err, convergence_factor, MAG_BITS, ARF_RND_UP); arf_set(arb_midref(t), arb_midref(x)); mag_zero(arb_radref(t)); _arb_poly_evaluate2(u, v, poly, len, t, prec); arb_div(u, u, v, prec); arb_sub(u, t, u, prec); arb_add_error_arf(u, err); if (arb_contains(convergence_interval, u) && (mag_cmp(arb_radref(u), arb_radref(x)) < 0)) { arb_swap(xnew, u); result = 1; } else { arb_set(xnew, x); result = 0; } arb_clear(t); arb_clear(u); arb_clear(v); arf_clear(err); return result; }
void arb_fprintd(FILE * file, const arb_t x, slong digits) { arf_fprintd(file, arb_midref(x), FLINT_MAX(digits, 1)); flint_fprintf(file, " +/- "); mag_fprintd(file, arb_radref(x), 5); }
void arb_fprint(FILE * file, const arb_t x) { arf_fprint(file, arb_midref(x)); flint_fprintf(file, " +/- "); mag_fprint(file, arb_radref(x)); }
void acb_lambertw_cleared_cut_fix_small(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, int flags, slong prec) { acb_t zz, zmid, zmide1; arf_t eps; acb_init(zz); acb_init(zmid); acb_init(zmide1); arf_init(eps); arf_mul_2exp_si(eps, arb_midref(acb_realref(z)), -prec); acb_set(zz, z); if (arf_sgn(arb_midref(acb_realref(zz))) < 0 && (!fmpz_is_zero(k) || arf_sgn(arb_midref(acb_realref(ez1))) < 0) && arf_cmpabs(arb_midref(acb_imagref(zz)), eps) < 0) { /* now the value must be in [0,2eps] */ arf_get_mag(arb_radref(acb_imagref(zz)), eps); arf_set_mag(arb_midref(acb_imagref(zz)), arb_radref(acb_imagref(zz))); if (arf_sgn(arb_midref(acb_imagref(z))) >= 0) { acb_lambertw_cleared_cut(res, zz, k, flags, prec); } else { fmpz_t kk; fmpz_init(kk); fmpz_neg(kk, k); acb_lambertw_cleared_cut(res, zz, kk, flags, prec); acb_conj(res, res); fmpz_clear(kk); } } else { acb_lambertw_cleared_cut(res, zz, k, flags, prec); } acb_clear(zz); acb_clear(zmid); acb_clear(zmide1); arf_clear(eps); }
static void arb_supremum(arf_t res, const arb_t x) { if (arf_is_nan(arb_midref(x))) { arf_nan(res); } else if (mag_is_inf(arb_radref(x))) { arf_pos_inf(res); } else { arf_set_mag(res, arb_radref(x)); arf_add(res, res, arb_midref(x), ARF_PREC_EXACT, ARF_RND_CEIL); } }
static void arb_infimum(arf_t res, const arb_t x) { if (arf_is_nan(arb_midref(x))) { arf_nan(res); } else if (mag_is_inf(arb_radref(x))) { arf_neg_inf(res); } else { arf_set_mag(res, arb_radref(x)); arf_sub(res, arb_midref(x), res, ARF_PREC_EXACT, ARF_RND_FLOOR); } }
void arb_get_lbound_arf(arf_t u, const arb_t x, long prec) { arf_t t; arf_init_set_mag_shallow(t, arb_radref(x)); arf_sub(u, arb_midref(x), t, prec, ARF_RND_FLOOR); }
void arb_zeta_ui_borwein_bsplit(arb_t x, ulong s, slong prec) { zeta_bsplit_t sum; mag_t err; slong wp, n; /* zeta(0) = -1/2 */ if (s == 0) { arb_set_si(x, -1); arb_mul_2exp_si(x, x, -1); return; } if (s == 1) { flint_printf("zeta_ui_borwein_bsplit: zeta(1)"); abort(); } n = prec / ERROR_B + 2; wp = prec + 30; zeta_bsplit_init(sum); zeta_bsplit(sum, 0, n + 1, n, s, 0, wp); /* A/Q3 - B/Q3 / (C/Q1) = (A*C - B*Q1) / (Q3*C) */ arb_mul(sum->A, sum->A, sum->C, wp); arb_mul(sum->B, sum->B, sum->Q1, wp); arb_sub(sum->A, sum->A, sum->B, wp); arb_mul(sum->Q3, sum->Q3, sum->C, wp); arb_div(sum->C, sum->A, sum->Q3, wp); mag_init(err); mag_borwein_error(err, n); mag_add(arb_radref(sum->C), arb_radref(sum->C), err); mag_clear(err); /* convert from eta(s) to zeta(s) */ arb_div_2expm1_ui(x, sum->C, s - 1, wp); arb_mul_2exp_si(x, x, s - 1); zeta_bsplit_clear(sum); }
void arb_bernoulli_fmpz(arb_t res, const fmpz_t n, slong prec) { if (fmpz_cmp_ui(n, UWORD_MAX) <= 0) { if (fmpz_sgn(n) >= 0) arb_bernoulli_ui(res, fmpz_get_ui(n), prec); else arb_zero(res); } else if (fmpz_is_odd(n)) { arb_zero(res); } else { arb_t t; slong wp; arb_init(t); wp = prec + 2 * fmpz_bits(n); /* zeta(n) ~= 1 */ arf_one(arb_midref(res)); mag_one(arb_radref(res)); mag_mul_2exp_si(arb_radref(res), arb_radref(res), WORD_MIN); /* |B_n| = 2 * n! / (2*pi)^n * zeta(n) */ arb_gamma_fmpz(t, n, wp); arb_mul_fmpz(t, t, n, wp); arb_mul(res, res, t, wp); arb_const_pi(t, wp); arb_mul_2exp_si(t, t, 1); arb_pow_fmpz(t, t, n, wp); arb_div(res, res, t, prec); arb_mul_2exp_si(res, res, 1); if (fmpz_fdiv_ui(n, 4) == 0) arb_neg(res, res); arb_clear(t); } }