void _acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec, slong gamma_prec, int kummer) { if (regularized) { /* Remove singularity */ if (acb_is_int(b) && arb_is_nonpositive(acb_realref(b)) && arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 30) < 0) { acb_t c, d, t, u; slong n; n = arf_get_si(arb_midref(acb_realref(b)), ARF_RND_DOWN); acb_init(c); acb_init(d); acb_init(t); acb_init(u); acb_sub(c, a, b, prec); acb_add_ui(c, c, 1, prec); acb_neg(d, b); acb_add_ui(d, d, 2, prec); _acb_hypgeom_m_1f1(t, c, d, z, 0, prec, gamma_prec, kummer); acb_pow_ui(u, z, 1 - n, prec); acb_mul(t, t, u, prec); acb_rising_ui(u, a, 1 - n, prec); acb_mul(t, t, u, prec); arb_fac_ui(acb_realref(u), 1 - n, prec); acb_div_arb(res, t, acb_realref(u), prec); acb_clear(c); acb_clear(d); acb_clear(t); acb_clear(u); } else { acb_t t; acb_init(t); acb_rgamma(t, b, gamma_prec); _acb_hypgeom_m_1f1(res, a, b, z, 0, prec, gamma_prec, kummer); acb_mul(res, res, t, prec); acb_clear(t); } return; } /* Kummer's transformation */ if (kummer) { acb_t u, v; acb_init(u); acb_init(v); acb_sub(u, b, a, prec); acb_neg(v, z); _acb_hypgeom_m_1f1(u, u, b, v, regularized, prec, gamma_prec, 0); acb_exp(v, z, prec); acb_mul(res, u, v, prec); acb_clear(u); acb_clear(v); return; } if (acb_is_one(a)) { acb_hypgeom_pfq_direct(res, NULL, 0, b, 1, z, -1, prec); } else { acb_struct c[3]; c[0] = *a; c[1] = *b; acb_init(c + 2); acb_one(c + 2); acb_hypgeom_pfq_direct(res, c, 1, c + 1, 2, z, -1, prec); acb_clear(c + 2); } }
void acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, long prec) { long m = LONG_MAX; long n = LONG_MAX; if (acb_is_int(a) && arf_cmpabs_2exp_si(arb_midref(acb_realref(a)), 30) < 0) { m = arf_get_si(arb_midref(acb_realref(a)), ARF_RND_DOWN); } if (acb_is_int(b) && arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 30) < 0) { n = arf_get_si(arb_midref(acb_realref(b)), ARF_RND_DOWN); } /* terminating */ if (m <= 0 && m < n && m > -10 * prec && (n > 0 || !regularized)) { acb_hypgeom_m_1f1(res, a, b, z, regularized, prec); return; } /* large */ if (acb_hypgeom_u_use_asymp(z, prec)) { acb_hypgeom_m_asymp(res, a, b, z, regularized, prec); return; } /* remove singularity */ if (n <= 0 && n > -10 * prec && regularized) { acb_t c, d, t, u; acb_init(c); acb_init(d); acb_init(t); acb_init(u); acb_sub(c, a, b, prec); acb_add_ui(c, c, 1, prec); acb_neg(d, b); acb_add_ui(d, d, 2, prec); acb_hypgeom_m_1f1(t, c, d, z, 0, prec); acb_pow_ui(u, z, 1 - n, prec); acb_mul(t, t, u, prec); acb_rising_ui(u, a, 1 - n, prec); acb_mul(t, t, u, prec); arb_fac_ui(acb_realref(u), 1 - n, prec); acb_div_arb(res, t, acb_realref(u), prec); acb_clear(c); acb_clear(d); acb_clear(t); acb_clear(u); } else { acb_hypgeom_m_1f1(res, a, b, z, regularized, prec); } }
int main() { slong iter; flint_rand_t state; flint_printf("rising_ui...."); fflush(stdout); flint_randinit(state); /* check functional equation */ for (iter = 0; iter < 1000; iter++) { acb_t x, xn, y, z; ulong n, m; acb_init(x); acb_init(xn); acb_init(y); acb_init(z); acb_randtest(x, state, 1 + n_randint(state, 4000), 10); n = n_randint(state, 80); m = n_randint(state, 40); acb_add_ui(xn, x, n, 1 + n_randint(state, 4000)); acb_rising_ui(y, x, n, 2 + n_randint(state, 4000)); acb_rising_ui(z, xn, m, 2 + n_randint(state, 4000)); acb_mul(y, y, z, 2 + n_randint(state, 4000)); acb_rising_ui(z, x, n + m, 2 + n_randint(state, 4000)); if (!acb_overlaps(y, z)) { flint_printf("FAIL: overlap\n\n"); flint_printf("n = %wu\n", n); flint_printf("m = %wu\n", m); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("xn = "); acb_print(xn); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("z = "); acb_print(z); flint_printf("\n\n"); abort(); } acb_clear(x); acb_clear(xn); acb_clear(y); acb_clear(z); } /* aliasing of y and x */ for (iter = 0; iter < 1000; iter++) { acb_t x, y; ulong n; slong prec; acb_init(x); acb_init(y); acb_randtest(x, state, 1 + n_randint(state, 200), 10); acb_randtest(y, state, 1 + n_randint(state, 200), 10); n = n_randint(state, 100); prec = 2 + n_randint(state, 4000); acb_rising_ui(y, x, n, prec); acb_rising_ui(x, x, n, prec); if (!acb_equal(x, y)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("n = %wu\n", n); abort(); } acb_clear(x); acb_clear(y); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }