void acb_hypgeom_beta_lower(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { acb_t t, u; if (acb_is_zero(z) && arb_is_positive(acb_realref(a))) { acb_zero(res); return; } if (acb_is_one(z) && arb_is_positive(acb_realref(b))) { if (regularized) acb_one(res); else acb_beta(res, a, b, prec); return; } acb_init(t); acb_init(u); acb_sub_ui(t, b, 1, prec); acb_neg(t, t); acb_add_ui(u, a, 1, prec); if (regularized) { acb_hypgeom_2f1(t, a, t, u, z, 1, prec); acb_add(u, a, b, prec); acb_gamma(u, u, prec); acb_mul(t, t, u, prec); acb_rgamma(u, b, prec); acb_mul(t, t, u, prec); } else { acb_hypgeom_2f1(t, a, t, u, z, 0, prec); acb_div(t, t, a, prec); } acb_pow(u, z, a, prec); acb_mul(t, t, u, prec); acb_set(res, t); acb_clear(t); acb_clear(u); }
void acb_hypgeom_jacobi_p(acb_t res, const acb_t n, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_t t, u, v, w; if (use_recurrence(n, a, b, prec)) { acb_hypgeom_jacobi_p_ui_direct(res, arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), a, b, z, prec); return; } acb_init(t); acb_init(u); acb_init(v); acb_init(w); acb_neg(t, n); acb_add_ui(v, a, 1, prec); acb_add(u, n, v, prec); acb_add(u, u, b, prec); acb_sub_ui(w, z, 1, prec); acb_mul_2exp_si(w, w, -1); acb_neg(w, w); acb_hypgeom_2f1(w, t, u, v, w, 0, prec); acb_rising(t, v, n, prec); acb_mul(w, w, t, prec); acb_add_ui(t, n, 1, prec); acb_rgamma(t, t, prec); acb_mul(w, w, t, prec); acb_set(res, w); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); }
void arb_hypgeom_2f1(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec) { acb_t t, u, v, w; acb_init(t); acb_init(u); acb_init(v); acb_init(w); arb_set(acb_realref(t), a); arb_set(acb_realref(u), b); arb_set(acb_realref(v), c); arb_set(acb_realref(w), z); acb_hypgeom_2f1(t, t, u, v, w, regularized, prec); if (acb_is_finite(t) && acb_is_real(t)) arb_swap(res, acb_realref(t)); else arb_indeterminate(res); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); }
int main(int argc, char *argv[]) { int function, i, numtests; slong prec, goal; double t, total, logtotal; acb_t a, b, c, z, r, s; acb_init(a); acb_init(b); acb_init(c); acb_init(z); acb_init(r); acb_init(s); /* J(0,pi x) I(0,pi x) K(0,pi x) */ for (function = 0; function < 3; function++) { total = 0.0; logtotal = 0.0; if (function < 2) numtests = 40; else numtests = 30; for (i = 0; i < numtests; i++) { // printf("%2d ", i + 1); fflush(stdout); TIMEIT_START prec = 96; for (;;) { if (function == 0) { acb_set_d_d(a, input_1f1[i][0], input_1f1[i][1]); acb_set_d_d(b, input_1f1[i][2], input_1f1[i][3]); acb_set_d_d(z, input_1f1[i][4], input_1f1[i][5]); acb_hypgeom_m(r, a, b, z, 0, prec); } else if (function == 1) { acb_set_d_d(a, input_1f1[i][0], input_1f1[i][1]); acb_set_d_d(b, input_1f1[i][2], input_1f1[i][3]); acb_set_d_d(z, input_1f1[i][4], input_1f1[i][5]); acb_hypgeom_u(r, a, b, z, prec); } else if (function == 2) { acb_set_d_d(a, input_2f1[i][0], input_2f1[i][1]); acb_set_d_d(b, input_2f1[i][2], input_2f1[i][3]); acb_set_d_d(c, input_2f1[i][4], input_2f1[i][5]); acb_set_d_d(z, input_2f1[i][6], input_2f1[i][7]); acb_hypgeom_2f1(r, a, b, c, z, 0, prec); } else { acb_set_d_d(a, input_2f1[i][0], input_2f1[i][1]); acb_set_d_d(b, input_2f1[i][2], input_2f1[i][3]); acb_set_d_d(c, input_2f1[i][4], input_2f1[i][5]); acb_set_d_d(z, input_2f1[i][6], input_2f1[i][7]); acb_mul_2exp_si(z, z, 1); acb_sub_ui(z, z, 1, prec); acb_neg(z, z); acb_hypgeom_legendre_q(r, a, c, z, 0, prec); } if (function == 3) { if (acb_rel_accuracy_bits(r) >= goal) break; } else { if (arb_can_round_arf(acb_realref(r), goal, ARF_RND_NEAR) && arb_can_round_arf(acb_imagref(r), goal, ARF_RND_NEAR)) break; } prec *= 2; } TIMEIT_STOP_VAL(t) total += t; logtotal += log(t); #if 1 printf("%8g, ", t); #else printf("%8ld %8g ", prec, t); _acb_print(r, 25); printf("\n"); #endif } printf("---------------------------------------------------------------\n"); printf("Mean %g s; geometric mean %g\n", total, exp(logtotal / numtests)); printf("---------------------------------------------------------------\n"); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(z); acb_clear(r); acb_clear(s); }
void acb_hypgeom_chebyshev_t(acb_t res, const acb_t n, const acb_t z, slong prec) { acb_t t; if (acb_is_int(n) && arf_cmpabs_2exp_si(arb_midref(acb_realref(n)), FLINT_BITS - 1) < 0) { slong k = arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN); acb_chebyshev_t_ui(res, FLINT_ABS(k), z, prec); return; } if (acb_is_zero(z)) { acb_mul_2exp_si(res, n, -1); acb_cos_pi(res, res, prec); return; } if (acb_is_one(z)) { acb_one(res); return; } acb_init(t); acb_set_si(t, -1); if (acb_equal(t, z)) { acb_cos_pi(res, n, prec); } else { acb_sub_ui(t, z, 1, prec); if (arf_cmpabs_2exp_si(arb_midref(acb_realref(t)), -2 - prec / 10) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(t)), -2 - prec / 10) < 0) { acb_t a, c; acb_init(a); acb_init(c); acb_neg(a, n); acb_one(c); acb_mul_2exp_si(c, c, -1); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_hypgeom_2f1(res, a, n, c, t, 0, prec); acb_clear(a); acb_clear(c); } else if (arb_is_nonnegative(acb_realref(t))) { acb_acosh(t, z, prec); acb_mul(t, t, n, prec); acb_cosh(res, t, prec); } else { acb_acos(t, z, prec); acb_mul(t, t, n, prec); acb_cos(res, t, prec); } } acb_clear(t); }
int main() { slong iter; flint_rand_t state; flint_printf("2f1...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 3000; iter++) { acb_t a, b, c, z, w1, w2, t; slong prec1, prec2; int reg1, reg2, ebits; int alg1, alg2; acb_init(a); acb_init(b); acb_init(c); acb_init(z); acb_init(w1); acb_init(w2); acb_init(t); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); if (n_randint(state, 20) == 0) ebits = 30; else ebits = 5; switch (n_randint(state, 3)) { case 0: acb_set_si(a, n_randint(state, 500)); acb_set_si(b, n_randint(state, 500)); acb_set_si(c, n_randint(state, 10)); break; case 1: acb_set_si(a, n_randint(state, 200) - 100); acb_set_si(b, n_randint(state, 200) - 100); acb_set_si(c, n_randint(state, 200) - 100); break; default: acb_randtest_param(a, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest_param(b, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest_param(c, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); } acb_randtest_param(z, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest(w1, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest(w2, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); reg1 = n_randint(state, 2); reg2 = n_randint(state, 2); alg1 = n_randint(state, 10); alg2 = n_randint(state, 10); switch (alg1) { case 0: acb_hypgeom_2f1_direct(w1, a, b, c, z, reg1, prec1); break; case 1: case 2: case 3: case 4: case 5: acb_hypgeom_2f1_transform(w1, a, b, c, z, reg1, alg1, prec1); break; case 6: acb_hypgeom_2f1_corner(w1, a, b, c, z, reg1, prec1); break; default: acb_hypgeom_2f1(w1, a, b, c, z, reg1, prec1); } switch (alg2) { case 0: acb_hypgeom_2f1_direct(w2, a, b, c, z, reg2, prec2); break; case 1: case 2: case 3: case 4: case 5: acb_hypgeom_2f1_transform(w2, a, b, c, z, reg2, alg2, prec2); break; case 6: acb_hypgeom_2f1_corner(w2, a, b, c, z, reg2, prec2); break; default: acb_hypgeom_2f1(w2, a, b, c, z, reg2, prec2); } if (reg1 != reg2) { acb_rgamma(t, c, prec2); if (reg1) acb_mul(w2, w2, t, prec2); else acb_mul(w1, w1, t, prec2); } if (!acb_overlaps(w1, w2)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("alg1 = %d, alg2 = %d\n\n", alg1, alg2); flint_printf("reg1 = %d, reg2 = %d\n\n", reg1, reg2); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n"); flint_printf("w2 = "); acb_printd(w2, 30); flint_printf("\n\n"); abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(z); acb_clear(w1); acb_clear(w2); acb_clear(t); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int main() { long iter; flint_rand_t state; printf("chebyshev_t...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000; iter++) { acb_t n, z, a, b, c, t, res1, res2; long prec; acb_init(n); acb_init(z); acb_init(a); acb_init(b); acb_init(c); acb_init(t); acb_init(res1); acb_init(res2); prec = 2 + n_randint(state, 300); acb_randtest_param(n, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(z, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(res1, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_randtest_param(res2, state, 1 + n_randint(state, 400), 1 + n_randint(state, 10)); acb_hypgeom_chebyshev_t(res1, n, z, prec); acb_neg(a, n); acb_set(b, n); acb_one(c); acb_mul_2exp_si(c, c, -1); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_hypgeom_2f1(res2, a, b, c, t, 0, 2 + n_randint(state, 300)); if (!acb_overlaps(res1, res2)) { printf("FAIL: consistency\n\n"); printf("iter = %ld\n\n", iter); printf("n = "); acb_printd(n, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("res1 = "); acb_printd(res1, 30); printf("\n\n"); printf("res2 = "); acb_printd(res2, 30); printf("\n\n"); abort(); } acb_clear(n); acb_clear(z); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(t); acb_clear(res1); acb_clear(res2); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int main() { slong iter; flint_rand_t state; flint_printf("2f1_continuation...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++) { acb_t a, b, c, z1, z2, f1, f2, g1, g2, h1, h2, aa, bb, cc; mag_t d0, d1, dt; slong prec; int regularized, ebits; acb_init(a); acb_init(b); acb_init(c); acb_init(aa); acb_init(bb); acb_init(cc); acb_init(z1); acb_init(z2); acb_init(f1); acb_init(f2); acb_init(g1); acb_init(g2); acb_init(h1); acb_init(h2); mag_init(d0); mag_init(d1); mag_init(dt); prec = 2 + n_randint(state, 300); ebits = 10; regularized = n_randint(state, 2); acb_randtest_param(a, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2)); acb_randtest_param(b, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2)); acb_randtest_param(c, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2)); acb_randtest(h1, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest(h2, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); do { int left, upper, lower; acb_randtest_param(z1, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); acb_randtest_param(z2, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits)); /* we test both convergent and non-convergent cases, but try to be more efficient by generating more convergent cases */ if (n_randint(state, 2)) { acb_sub_ui(aa, z1, 1, prec); acb_get_mag(d0, z1); acb_get_mag(d1, aa); acb_get_mag(dt, z2); if (mag_cmp(dt, d0) >= 0 || mag_cmp(dt, d1) >= 0) continue; } acb_add(z2, z1, z2, prec); /* for the test, don't cross the branch cut */ acb_sub_ui(aa, z1, 1, prec); acb_sub_ui(bb, z2, 1, prec); left = arb_is_negative(acb_realref(aa)) && arb_is_negative(acb_realref(bb)); upper = arb_is_positive(acb_imagref(aa)) && arb_is_positive(acb_imagref(bb)); lower = arb_is_nonpositive(acb_imagref(aa)) && arb_is_nonpositive(acb_imagref(bb)); if (left || upper || lower) break; } while (1); acb_add_ui(aa, a, 1, prec); acb_add_ui(bb, b, 1, prec); acb_add_ui(cc, c, 1, prec); acb_hypgeom_2f1(f1, a, b, c, z1, regularized, prec); acb_hypgeom_2f1(f2, aa, bb, cc, z1, regularized, prec); acb_mul(f2, f2, a, prec); acb_mul(f2, f2, b, prec); if (!regularized) acb_div(f2, f2, c, prec); acb_hypgeom_2f1_continuation(h1, h2, a, b, c, z1, z2, f1, f2, prec); if (acb_is_finite(h1) || acb_is_finite(h2)) { acb_hypgeom_2f1(g1, a, b, c, z2, regularized, prec); acb_hypgeom_2f1(g2, aa, bb, cc, z2, regularized, prec); acb_mul(g2, g2, a, prec); acb_mul(g2, g2, b, prec); if (!regularized) acb_div(g2, g2, c, prec); if (!acb_overlaps(g1, h1) || !acb_overlaps(g2, h2)) { flint_printf("FAIL: consistency\n\n"); flint_printf("regularized = %d, prec = %wd\n\n", regularized, prec); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n"); flint_printf("F(a,b,c,z1) and F'(a,b,c,z1):\n"); flint_printf("f1 = "); acb_printd(f1, 30); flint_printf("\n\n"); flint_printf("f2 = "); acb_printd(f2, 30); flint_printf("\n\n"); flint_printf("F(a,b,c,z2) and F'(a,b,c,z2):\n"); flint_printf("g1 = "); acb_printd(g1, 30); flint_printf("\n\n"); flint_printf("g2 = "); acb_printd(g2, 30); flint_printf("\n\n"); flint_printf("Computed F and F':\n"); flint_printf("h1 = "); acb_printd(h1, 30); flint_printf("\n\n"); flint_printf("h2 = "); acb_printd(h2, 30); flint_printf("\n\n"); flint_abort(); } } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(aa); acb_clear(bb); acb_clear(cc); acb_clear(z1); acb_clear(z2); acb_clear(f1); acb_clear(f2); acb_clear(g1); acb_clear(g2); acb_clear(h1); acb_clear(h2); mag_clear(d0); mag_clear(d1); mag_clear(dt); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void acb_hypgeom_legendre_q(acb_t res, const acb_t n, const acb_t m, const acb_t z, int type, slong prec) { if (type == 0) { /* http://functions.wolfram.com/07.11.26.0033.01 */ /* todo: simplify the gamma quotients and the sqrt pi factor... */ acb_t a, b, c, z2, mn, nm, t, u; acb_init(a); acb_init(b); acb_init(c); acb_init(z2); acb_init(mn); acb_init(nm); acb_init(t); acb_init(u); acb_add(mn, m, n, prec); /* mn = m + n */ acb_sub(nm, n, m, prec); /* nm = n - m */ acb_mul(z2, z, z, prec); /* z2 = z^2 */ /* t = 2F1((1-m-n)/2, (n-m)/2+1, 3/2, z^2) */ acb_sub_ui(a, mn, 1, prec); acb_neg(a, a); acb_mul_2exp_si(a, a, -1); acb_mul_2exp_si(b, nm, -1); acb_add_ui(b, b, 1, prec); acb_set_ui(c, 3); acb_mul_2exp_si(c, c, -1); acb_hypgeom_2f1(t, a, b, c, z2, 0, prec); /* u = 2F1(-(m+n)/2, (n-m+1)/2, 1/2, z^2) */ acb_neg(a, mn); acb_mul_2exp_si(a, a, -1); acb_add_ui(b, nm, 1, prec); acb_mul_2exp_si(b, b, -1); acb_one(c); acb_mul_2exp_si(c, c, -1); acb_hypgeom_2f1(u, a, b, c, z2, 0, prec); /* a = cospi((m+n)/2) gamma((m+n)/2+1) rgamma((n-m+1)/2) z */ /* b = sinpi((m+n)/2) gamma((m+n+1)/2) rgamma((n-m)/2+1) / 2 */ acb_mul_2exp_si(a, mn, -1); acb_sin_cos_pi(b, a, a, prec); acb_mul_2exp_si(c, mn, -1); acb_add_ui(c, c, 1, prec); acb_gamma(c, c, prec); acb_mul(a, a, c, prec); acb_add_ui(c, nm, 1, prec); acb_mul_2exp_si(c, c, -1); acb_rgamma(c, c, prec); acb_mul(a, a, c, prec); acb_mul(a, a, z, prec); acb_add_ui(c, mn, 1, prec); acb_mul_2exp_si(c, c, -1); acb_gamma(c, c, prec); acb_mul(b, b, c, prec); acb_mul_2exp_si(c, nm, -1); acb_add_ui(c, c, 1, prec); acb_rgamma(c, c, prec); acb_mul(b, b, c, prec); acb_mul_2exp_si(b, b, -1); /* at - bu */ acb_mul(t, t, a, prec); acb_mul(u, u, b, prec); acb_sub(t, t, u, prec); /* prefactor sqrt(pi) 2^m (1-z^2)^(-m/2) */ if (!acb_is_zero(m)) { acb_sub_ui(u, z2, 1, prec); acb_neg(u, u); acb_neg(c, m); acb_mul_2exp_si(c, c, -1); acb_pow(u, u, c, prec); acb_set_ui(c, 2); acb_pow(c, c, m, prec); acb_mul(u, u, c, prec); acb_mul(t, t, u, prec); } arb_const_sqrt_pi(acb_realref(u), prec); acb_mul_arb(t, t, acb_realref(u), prec); acb_set(res, t); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(z2); acb_clear(mn); acb_clear(nm); acb_clear(t); acb_clear(u); } else if (type == 1) { if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -2) < 0 && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -2) < 0) || !_acb_hypgeom_legendre_q_single_valid(z)) { _acb_hypgeom_legendre_q_double(res, n, m, z, prec); } else { _acb_hypgeom_legendre_q_single(res, n, m, z, prec); } } else { flint_printf("unsupported 'type' %d for legendre q\n", type); abort(); } }
void _acb_hypgeom_legendre_q_single(acb_t res, const acb_t n, const acb_t m, const acb_t z, slong prec) { acb_t a, b, c, z2, t, u; acb_init(a); acb_init(b); acb_init(c); acb_init(z2); acb_init(t); acb_init(u); /* invalid in (-1,0) */ if (!_acb_hypgeom_legendre_q_single_valid(z)) { acb_indeterminate(res); return; } acb_pow_si(z2, z, -2, prec); /* z2 = 1/z^2 */ /* t = 2F1r((m+n+1)/2, (m+n)/2+1, n+3/2, 1/z^2) */ acb_add(b, m, n, prec); acb_add_ui(a, b, 1, prec); acb_mul_2exp_si(a, a, -1); acb_mul_2exp_si(b, b, -1); acb_add_ui(b, b, 1, prec); acb_set_ui(c, 3); acb_mul_2exp_si(c, c, -1); acb_add(c, c, n, prec); acb_hypgeom_2f1(t, a, b, c, z2, 1, prec); /* prefactor sqrt(pi) 2^-n (z+1)^(m/2) (z-1)^(m/2) exp(i pi m) */ /* (1/2) gamma(m+n+1) z^(-m-n-1) */ if (!acb_is_zero(m)) { acb_add_ui(z2, z, 1, prec); acb_mul_2exp_si(c, m, -1); acb_pow(z2, z2, c, prec); acb_mul(t, t, z2, prec); acb_sub_ui(z2, z, 1, prec); acb_mul_2exp_si(c, m, -1); acb_pow(z2, z2, c, prec); acb_mul(t, t, z2, prec); acb_exp_pi_i(z2, m, prec); acb_mul(t, t, z2, prec); } acb_set_ui(z2, 2); acb_neg(c, n); acb_pow(z2, z2, c, prec); acb_mul(t, t, z2, prec); acb_add(c, m, n, prec); acb_add_ui(c, c, 1, prec); acb_gamma(z2, c, prec); acb_mul(t, t, z2, prec); acb_neg(c, c); acb_pow(z2, z, c, prec); acb_mul(t, t, z2, prec); acb_mul_2exp_si(t, t, -1); arb_const_sqrt_pi(acb_realref(u), prec); acb_mul_arb(t, t, acb_realref(u), prec); acb_set(res, t); acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(z2); acb_clear(t); acb_clear(u); }