int main() { slong iter; flint_rand_t state; flint_printf("integrate_taylor...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 150 * arb_test_multiplier(); iter++) { acb_t ans, res, a, b; arf_t inr, outr; double t; slong goal, prec; acb_init(ans); acb_init(res); acb_init(a); acb_init(b); arf_init(inr); arf_init(outr); goal = 2 + n_randint(state, 300); prec = 2 + n_randint(state, 300); acb_randtest(a, state, 1 + n_randint(state, 200), 2); acb_randtest(b, state, 1 + n_randint(state, 200), 2); acb_cos(ans, a, prec); acb_cos(res, b, prec); acb_sub(ans, ans, res, prec); t = (1 + n_randint(state, 20)) / 10.0; arf_set_d(inr, t); arf_set_d(outr, t + (1 + n_randint(state, 20)) / 5.0); acb_calc_integrate_taylor(res, sin_x, NULL, a, b, inr, outr, goal, prec); if (!acb_overlaps(res, ans)) { flint_printf("FAIL! (iter = %wd)\n", iter); flint_printf("prec = %wd, goal = %wd\n", prec, goal); flint_printf("inr = "); arf_printd(inr, 15); flint_printf("\n"); flint_printf("outr = "); arf_printd(outr, 15); flint_printf("\n"); flint_printf("a = "); acb_printd(a, 15); flint_printf("\n"); flint_printf("b = "); acb_printd(b, 15); flint_printf("\n"); flint_printf("res = "); acb_printd(res, 15); flint_printf("\n\n"); flint_printf("ans = "); acb_printd(ans, 15); flint_printf("\n\n"); abort(); } acb_clear(ans); acb_clear(res); acb_clear(a); acb_clear(b); arf_clear(inr); arf_clear(outr); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int main() { long iter; flint_rand_t state; printf("atan_arf...."); fflush(stdout); flint_randinit(state); /* self-consistency test */ for (iter = 0; iter < 5000; iter++) { arf_t x; arb_t y1, y2; long prec1, prec2, acc1, acc2; prec1 = 2 + n_randint(state, 9000); prec2 = 2 + n_randint(state, 9000); arf_init(x); arb_init(y1); arb_init(y2); arf_randtest_special(x, state, 1 + n_randint(state, 9000), 200); arb_randtest_special(y1, state, 1 + n_randint(state, 9000), 200); arb_randtest_special(y2, state, 1 + n_randint(state, 9000), 200); if (n_randint(state, 2)) arf_add_ui(x, x, 1, 2 + n_randint(state, 9000), ARF_RND_DOWN); arb_atan_arf(y1, x, prec1); arb_atan_arf(y2, x, prec2); if (!arb_overlaps(y1, y2)) { printf("FAIL: overlap\n\n"); printf("prec1 = %ld, prec2 = %ld\n\n", prec1, prec2); printf("x = "); arf_print(x); printf("\n\n"); printf("y1 = "); arb_print(y1); printf("\n\n"); printf("y2 = "); arb_print(y2); printf("\n\n"); abort(); } acc1 = arb_rel_accuracy_bits(y1); acc2 = arb_rel_accuracy_bits(y2); if (!arf_is_nan(x)) { if (acc1 < prec1 - 2 || acc2 < prec2 - 2) { printf("FAIL: accuracy\n\n"); printf("prec1 = %ld, prec2 = %ld\n\n", prec1, prec2); printf("acc1 = %ld, acc2 = %ld\n\n", acc1, acc2); printf("x = "); arf_printd(x, 50); printf("\n\n"); printf("y1 = "); arb_printd(y1, 50); printf("\n\n"); printf("y2 = "); arb_printd(y2, 50); printf("\n\n"); abort(); } } arf_clear(x); arb_clear(y1); arb_clear(y2); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int main() { slong iter; flint_rand_t state; flint_printf("get_mpn_fixed_mod_pi4...."); fflush(stdout); flint_randinit(state); /* _flint_rand_init_gmp(state); */ for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++) { arf_t x; int octant; fmpz_t q; mp_ptr w; arb_t wb, t, u; mp_size_t wn; slong prec, prec2; int success; mp_limb_t error; prec = 2 + n_randint(state, 10000); wn = 1 + n_randint(state, 200); prec2 = FLINT_MAX(prec, wn * FLINT_BITS) + 100; arf_init(x); arb_init(wb); arb_init(t); arb_init(u); fmpz_init(q); w = flint_malloc(sizeof(mp_limb_t) * wn); arf_randtest(x, state, prec, 14); /* this should generate numbers close to multiples of pi/4 */ if (n_randint(state, 4) == 0) { arb_const_pi(t, prec); arb_mul_2exp_si(t, t, -2); fmpz_randtest(q, state, 200); arb_mul_fmpz(t, t, q, prec); arf_add(x, x, arb_midref(t), prec, ARF_RND_DOWN); } arf_abs(x, x); success = _arb_get_mpn_fixed_mod_pi4(w, q, &octant, &error, x, wn); if (success) { /* could round differently */ if (fmpz_fdiv_ui(q, 8) != octant) { flint_printf("bad octant\n"); abort(); } _arf_set_mpn_fixed(arb_midref(wb), w, wn, wn, 0, FLINT_BITS * wn, ARB_RND); mag_set_ui_2exp_si(arb_radref(wb), error, -FLINT_BITS * wn); arb_const_pi(u, prec2); arb_mul_2exp_si(u, u, -2); arb_set(t, wb); if (octant % 2 == 1) arb_sub(t, u, t, prec2); arb_addmul_fmpz(t, u, q, prec2); if (!arb_contains_arf(t, x)) { flint_printf("FAIL (containment)\n"); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n\n"); flint_printf("w = "); arb_printd(wb, 50); flint_printf("\n\n"); flint_printf("t = "); arb_printd(t, 50); flint_printf("\n\n"); abort(); } arb_const_pi(t, prec2); arb_mul_2exp_si(t, t, -2); if (arf_sgn(arb_midref(wb)) < 0 || arf_cmp(arb_midref(wb), arb_midref(t)) >= 0) { flint_printf("FAIL (expected 0 <= w < pi/4)\n"); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("w = "); arb_printd(wb, 50); flint_printf("\n\n"); abort(); } } flint_free(w); fmpz_clear(q); arf_clear(x); arb_clear(wb); arb_clear(t); arb_clear(u); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int acb_calc_integrate_taylor(acb_t res, acb_calc_func_t func, void * param, const acb_t a, const acb_t b, const arf_t inner_radius, const arf_t outer_radius, long accuracy_goal, long prec) { long num_steps, step, N, bp; int result; acb_t delta, m, x, y1, y2, sum; acb_ptr taylor_poly; arf_t err; acb_init(delta); acb_init(m); acb_init(x); acb_init(y1); acb_init(y2); acb_init(sum); arf_init(err); acb_sub(delta, b, a, prec); /* precision used for bounds calculations */ bp = MAG_BITS; /* compute the number of steps */ { arf_t t; arf_init(t); acb_get_abs_ubound_arf(t, delta, bp); arf_div(t, t, inner_radius, bp, ARF_RND_UP); arf_mul_2exp_si(t, t, -1); num_steps = (long) (arf_get_d(t, ARF_RND_UP) + 1.0); /* make sure it's not something absurd */ num_steps = FLINT_MIN(num_steps, 10 * prec); num_steps = FLINT_MAX(num_steps, 1); arf_clear(t); } result = ARB_CALC_SUCCESS; acb_zero(sum); for (step = 0; step < num_steps; step++) { /* midpoint of subinterval */ acb_mul_ui(m, delta, 2 * step + 1, prec); acb_div_ui(m, m, 2 * num_steps, prec); acb_add(m, m, a, prec); if (arb_calc_verbose) { printf("integration point %ld/%ld: ", 2 * step + 1, 2 * num_steps); acb_printd(m, 15); printf("\n"); } /* evaluate at +/- x */ /* TODO: exactify m, and include error in x? */ acb_div_ui(x, delta, 2 * num_steps, prec); /* compute bounds and number of terms to use */ { arb_t cbound, xbound, rbound; arf_t C, D, R, X, T; double DD, TT, NN; arb_init(cbound); arb_init(xbound); arb_init(rbound); arf_init(C); arf_init(D); arf_init(R); arf_init(X); arf_init(T); /* R is the outer radius */ arf_set(R, outer_radius); /* X = upper bound for |x| */ acb_get_abs_ubound_arf(X, x, bp); arb_set_arf(xbound, X); /* Compute C(m,R). Important subtlety: due to rounding when computing m, we will in general be farther than R away from the integration path. But since acb_calc_cauchy_bound actually integrates over the area traced by a complex interval, it will catch any extra singularities (giving an infinite bound). */ arb_set_arf(rbound, outer_radius); acb_calc_cauchy_bound(cbound, func, param, m, rbound, 8, bp); arf_set_mag(C, arb_radref(cbound)); arf_add(C, arb_midref(cbound), C, bp, ARF_RND_UP); /* Sanity check: we need C < inf and R > X */ if (arf_is_finite(C) && arf_cmp(R, X) > 0) { /* Compute upper bound for D = C * R * X / (R - X) */ arf_mul(D, C, R, bp, ARF_RND_UP); arf_mul(D, D, X, bp, ARF_RND_UP); arf_sub(T, R, X, bp, ARF_RND_DOWN); arf_div(D, D, T, bp, ARF_RND_UP); /* Compute upper bound for T = (X / R) */ arf_div(T, X, R, bp, ARF_RND_UP); /* Choose N */ /* TODO: use arf arithmetic to avoid overflow */ /* TODO: use relative accuracy (look at |f(m)|?) */ DD = arf_get_d(D, ARF_RND_UP); TT = arf_get_d(T, ARF_RND_UP); NN = -(accuracy_goal * 0.69314718055994530942 + log(DD)) / log(TT); N = NN + 0.5; N = FLINT_MIN(N, 100 * prec); N = FLINT_MAX(N, 1); /* Tail bound: D / (N + 1) * T^N */ { mag_t TT; mag_init(TT); arf_get_mag(TT, T); mag_pow_ui(TT, TT, N); arf_set_mag(T, TT); mag_clear(TT); } arf_mul(D, D, T, bp, ARF_RND_UP); arf_div_ui(err, D, N + 1, bp, ARF_RND_UP); } else { N = 1; arf_pos_inf(err); result = ARB_CALC_NO_CONVERGENCE; } if (arb_calc_verbose) { printf("N = %ld; bound: ", N); arf_printd(err, 15); printf("\n"); printf("R: "); arf_printd(R, 15); printf("\n"); printf("C: "); arf_printd(C, 15); printf("\n"); printf("X: "); arf_printd(X, 15); printf("\n"); } arb_clear(cbound); arb_clear(xbound); arb_clear(rbound); arf_clear(C); arf_clear(D); arf_clear(R); arf_clear(X); arf_clear(T); } /* evaluate Taylor polynomial */ taylor_poly = _acb_vec_init(N + 1); func(taylor_poly, m, param, N, prec); _acb_poly_integral(taylor_poly, taylor_poly, N + 1, prec); _acb_poly_evaluate(y2, taylor_poly, N + 1, x, prec); acb_neg(x, x); _acb_poly_evaluate(y1, taylor_poly, N + 1, x, prec); acb_neg(x, x); /* add truncation error */ arb_add_error_arf(acb_realref(y1), err); arb_add_error_arf(acb_imagref(y1), err); arb_add_error_arf(acb_realref(y2), err); arb_add_error_arf(acb_imagref(y2), err); acb_add(sum, sum, y2, prec); acb_sub(sum, sum, y1, prec); if (arb_calc_verbose) { printf("values: "); acb_printd(y1, 15); printf(" "); acb_printd(y2, 15); printf("\n"); } _acb_vec_clear(taylor_poly, N + 1); if (result == ARB_CALC_NO_CONVERGENCE) break; } acb_set(res, sum); acb_clear(delta); acb_clear(m); acb_clear(x); acb_clear(y1); acb_clear(y2); acb_clear(sum); arf_clear(err); return result; }