/* IMAG: erf(z) = 2z/sqrt(pi) * 1F1(1/2, 3/2, -z^2) */ void acb_hypgeom_erf_1f1a(acb_t res, const acb_t z, slong prec) { acb_t a, t, w; acb_struct b[2]; acb_init(a); acb_init(b); acb_init(b + 1); acb_init(t); acb_init(w); acb_one(a); acb_mul_2exp_si(a, a, -1); acb_set_ui(b, 3); acb_mul_2exp_si(b, b, -1); acb_one(b + 1); acb_mul(w, z, z, prec); acb_neg(w, w); acb_hypgeom_pfq_direct(t, a, 1, b, 2, w, -1, prec); acb_mul(t, t, z, prec); arb_const_sqrt_pi(acb_realref(w), prec); acb_div_arb(t, t, acb_realref(w), prec); acb_mul_2exp_si(res, t, 1); acb_clear(a); acb_clear(b); acb_clear(b + 1); acb_clear(t); acb_clear(w); }
void acb_hypgeom_laguerre_l_ui_recurrence(acb_t res, ulong n, const acb_t m, const acb_t z, slong prec) { acb_t t, u, v; ulong k; if (n == 0) { acb_one(res); return; } if (n == 1) { acb_sub(res, m, z, prec); acb_add_ui(res, res, 1, prec); return; } acb_init(t); acb_init(u); acb_init(v); acb_one(t); acb_sub(u, m, z, prec); acb_add_ui(u, u, 1, prec); for (k = 2; k <= n; k++) { acb_add_ui(v, m, k - 1, prec); acb_mul(t, t, v, prec); acb_add_ui(v, m, 2 * k - 1, prec); acb_sub(v, v, z, prec); acb_mul(v, v, u, prec); acb_sub(t, v, t, prec); acb_div_ui(t, t, k, prec); acb_swap(t, u); } acb_set(res, u); acb_clear(t); acb_clear(u); acb_clear(v); }
void acb_sinc_pi(acb_t res, const acb_t x, slong prec) { mag_t m; acb_t t; if (acb_is_zero(x)) { acb_one(res); return; } mag_init(m); acb_init(t); acb_get_mag_lower(m, x); if (mag_cmp_2exp_si(m, -1) > 0) { acb_const_pi(t, prec + 4); acb_mul(t, t, x, prec + 4); acb_sin_pi(res, x, prec + 4); acb_div(res, res, t, prec); } else { acb_const_pi(t, prec + 4); acb_mul(t, t, x, prec + 4); acb_sinc(res, t, prec); } mag_clear(m); acb_clear(t); }
int bessel(acb_ptr out, const acb_t inp, void * params, long order, long prec) { acb_ptr t; acb_t z; ulong n; t = _acb_vec_init(order); acb_init(z); acb_set(t, inp); if (order > 1) acb_one(t + 1); n = 10; arb_set_si(acb_realref(z), 20); arb_set_si(acb_imagref(z), 10); /* z sin(t) */ _acb_poly_sin_series(out, t, FLINT_MIN(2, order), order, prec); _acb_vec_scalar_mul(out, out, order, z, prec); /* t n */ _acb_vec_scalar_mul_ui(t, t, FLINT_MIN(2, order), n, prec); _acb_poly_sub(out, t, FLINT_MIN(2, order), out, order, prec); _acb_poly_cos_series(out, out, order, order, prec); _acb_vec_clear(t, order); acb_clear(z); return 0; }
void _acb_poly_interpolation_weights(acb_ptr w, acb_ptr * tree, slong len, slong prec) { acb_ptr tmp; slong i, n, height; if (len == 0) return; if (len == 1) { acb_one(w); return; } tmp = _acb_vec_init(len + 1); height = FLINT_CLOG2(len); n = WORD(1) << (height - 1); _acb_poly_mul_monic(tmp, tree[height-1], n + 1, tree[height-1] + (n + 1), (len - n + 1), prec); _acb_poly_derivative(tmp, tmp, len + 1, prec); _acb_poly_evaluate_vec_fast_precomp(w, tmp, len, tree, len, prec); for (i = 0; i < len; i++) acb_inv(w + i, w + i, prec); _acb_vec_clear(tmp, len + 1); }
void acb_modular_elliptic_e(acb_t res, const acb_t m, long prec) { if (acb_is_zero(m)) { acb_const_pi(res, prec); acb_mul_2exp_si(res, res, -1); } else if (acb_is_one(m)) { acb_one(res); } else { acb_struct t[2]; acb_init(t + 0); acb_init(t + 1); acb_modular_elliptic_k_cpx(t, m, 2, prec); acb_mul(t + 1, t + 1, m, prec); acb_mul_2exp_si(t + 1, t + 1, 1); acb_add(t, t, t + 1, prec); acb_sub_ui(t + 1, m, 1, prec); acb_mul(res, t, t + 1, prec); acb_neg(res, res); acb_clear(t + 0); acb_clear(t + 1); } }
/* f(z) = sin((1/1000 + (1-z)^2)^(-3/2)), example from Mioara Joldes' thesis (suggested by Nicolas Brisebarre) */ int f_sin_near_essing(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t, u; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_init(u); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_mul(t, t, t, prec); acb_one(u); acb_div_ui(u, u, 1000, prec); acb_add(t, t, u, prec); acb_set_d(u, -1.5); acb_pow_analytic(t, t, u, order != 0, prec); acb_sin(res, t, prec); acb_clear(t); acb_clear(u); return 0; }
void acb_hypgeom_jacobi_p_ui_direct(acb_t res, ulong n, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_ptr terms; acb_t t, u, v; slong k; terms = _acb_vec_init(n + 1); acb_init(t); acb_init(u); acb_init(v); acb_one(terms); acb_add_ui(u, z, 1, prec); for (k = 1; k <= n; k++) { acb_add_ui(t, a, n + 1 - k, prec); acb_mul(t, t, u, prec); acb_div_ui(t, t, 2 * k, prec); acb_mul(terms + k, terms + k - 1, t, prec); } acb_sub_ui(u, z, 1, prec); acb_one(v); for (k = 1; k <= n; k++) { acb_add_ui(t, b, n + 1 - k, prec); acb_mul(t, t, u, prec); acb_div_ui(t, t, 2 * k, prec); acb_mul(v, v, t, prec); acb_mul(terms + n - k, terms + n - k, v, prec); } acb_set(res, terms); for (k = 1; k <= n; k++) acb_add(res, res, terms + k, prec); _acb_vec_clear(terms, n + 1); acb_clear(t); acb_clear(u); acb_clear(v); }
void _acb_poly_product_roots(acb_ptr poly, acb_srcptr xs, slong n, slong prec) { if (n == 0) { acb_one(poly); } else if (n == 1) { acb_neg(poly, xs); acb_one(poly + 1); } else if (n == 2) { acb_mul(poly, xs + 0, xs + 1, prec); acb_add(poly + 1, xs + 0, xs + 1, prec); acb_neg(poly + 1, poly + 1); acb_one(poly + 2); } else if (n == 3) { acb_mul(poly + 1, xs, xs + 1, prec); acb_mul(poly, poly + 1, xs + 2, prec); acb_neg(poly, poly); acb_add(poly + 2, xs, xs + 1, prec); acb_addmul(poly + 1, poly + 2, xs + 2, prec); acb_add(poly + 2, poly + 2, xs + 2, prec); acb_neg(poly + 2, poly + 2); acb_one(poly + 3); } else { const slong m = (n + 1) / 2; acb_ptr tmp; tmp = _acb_vec_init(n + 2); _acb_poly_product_roots(tmp, xs, m, prec); _acb_poly_product_roots(tmp + m + 1, xs + m, n - m, prec); _acb_poly_mul_monic(poly, tmp, m + 1, tmp + m + 1, n - m + 1, prec); _acb_vec_clear(tmp, n + 2); } }
int sinx(acb_ptr out, const acb_t inp, void * params, long order, long prec) { int xlen = FLINT_MIN(2, order); acb_set(out, inp); if (xlen > 1) acb_one(out + 1); _acb_poly_sin_series(out, out, xlen, order, prec); return 0; }
void acb_mat_one(acb_mat_t mat) { slong i, j; for (i = 0; i < acb_mat_nrows(mat); i++) for (j = 0; j < acb_mat_ncols(mat); j++) if (i == j) acb_one(acb_mat_entry(mat, i, j)); else acb_zero(acb_mat_entry(mat, i, j)); }
/* f(z) = sqrt(1-z^2) */ int f_circle(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_one(res); acb_submul(res, z, z, prec); acb_real_sqrtpos(res, res, order != 0, prec); return 0; }
void acb_mat_ones(acb_mat_t mat) { slong R, C, i, j; R = acb_mat_nrows(mat); C = acb_mat_ncols(mat); for (i = 0; i < R; i++) for (j = 0; j < C; j++) acb_one(acb_mat_entry(mat, i, j)); }
int main() { long iter; flint_rand_t state; printf("exp_invexp...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000; iter++) { acb_t a, b, c, d, e; long prec; acb_init(a); acb_init(b); acb_init(c); acb_init(d); acb_init(e); acb_randtest(a, state, 1 + n_randint(state, 200), 3); acb_randtest(b, state, 1 + n_randint(state, 200), 3); acb_randtest(c, state, 1 + n_randint(state, 200), 3); prec = 2 + n_randint(state, 200); acb_exp_invexp(b, c, a, prec); acb_mul(b, b, c, prec); acb_one(c); if (!acb_contains(b, c)) { printf("FAIL: overlap\n\n"); printf("a = "); acb_print(a); printf("\n\n"); printf("b = "); acb_print(b); printf("\n\n"); abort(); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(d); acb_clear(e); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
void acb_hypgeom_bessel_j_0f1(acb_t res, const acb_t nu, const acb_t z, long prec) { acb_struct b[2]; acb_t w, c, t; if (acb_is_int(nu) && arb_is_negative(acb_realref(nu))) { acb_init(t); acb_neg(t, nu); acb_hypgeom_bessel_j_0f1(res, t, z, prec); acb_mul_2exp_si(t, t, -1); if (!acb_is_int(t)) acb_neg(res, res); acb_clear(t); return; } acb_init(b + 0); acb_init(b + 1); acb_init(w); acb_init(c); acb_init(t); acb_add_ui(b + 0, nu, 1, prec); acb_one(b + 1); /* (z/2)^nu / gamma(nu+1) */ acb_mul_2exp_si(c, z, -1); acb_pow(c, c, nu, prec); acb_rgamma(t, b + 0, prec); acb_mul(c, t, c, prec); /* -z^2/4 */ acb_mul(w, z, z, prec); acb_mul_2exp_si(w, w, -2); acb_neg(w, w); acb_hypgeom_pfq_direct(t, NULL, 0, b, 2, w, -1, prec); acb_mul(res, t, c, prec); acb_clear(b + 0); acb_clear(b + 1); acb_clear(w); acb_clear(c); acb_clear(t); }
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_erf_asymp(acb_t res, const acb_t z, slong prec, slong prec2) { acb_t a, t, u; acb_init(a); acb_init(t); acb_init(u); acb_one(a); acb_mul_2exp_si(a, a, -1); acb_mul(t, z, z, prec2); acb_hypgeom_u_asymp(u, a, a, t, -1, prec2); acb_neg(t, t); acb_exp(t, t, prec2); acb_mul(u, u, t, prec2); acb_const_pi(t, prec2); acb_sqrt(t, t, prec2); acb_mul(t, t, z, prec2); acb_div(u, u, t, prec2); /* branch cut term: -1 or 1 */ if (arb_contains_zero(acb_realref(z))) { arb_zero(acb_imagref(t)); arf_zero(arb_midref(acb_realref(t))); mag_one(arb_radref(acb_realref(t))); } else { acb_set_si(t, arf_sgn(arb_midref(acb_realref(z)))); } acb_sub(t, t, u, prec); if (arb_is_zero(acb_imagref(z))) arb_zero(acb_imagref(t)); else if (arb_is_zero(acb_realref(z))) arb_zero(acb_realref(t)); acb_set(res, t); acb_clear(a); acb_clear(t); acb_clear(u); }
void acb_rising2_ui_bs(acb_t u, acb_t v, const acb_t x, ulong n, slong prec) { if (n == 0) { acb_zero(v); acb_one(u); } else if (n == 1) { acb_set(u, x); acb_one(v); } else { acb_t t; slong wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n)); acb_init(t); /* support aliasing */ acb_set(t, x); bsplit(v, u, t, 0, n, wp); acb_clear(t); } }
void acb_pow_arb(acb_t z, const acb_t x, const arb_t y, long prec) { const arf_struct * ymid = arb_midref(y); const mag_struct * yrad = arb_radref(y); if (arb_is_zero(y)) { acb_one(z); return; } if (mag_is_zero(yrad)) { /* small half-integer or integer */ if (arf_cmpabs_2exp_si(ymid, BINEXP_LIMIT) < 0 && arf_is_int_2exp_si(ymid, -1)) { fmpz_t e; fmpz_init(e); if (arf_is_int(ymid)) { arf_get_fmpz_fixed_si(e, ymid, 0); acb_pow_fmpz_binexp(z, x, e, prec); } else { /* hack: give something finite here (should fix sqrt/rsqrt etc) */ if (arb_contains_zero(acb_imagref(x)) && arb_contains_nonpositive(acb_realref(x))) { _acb_pow_arb_exp(z, x, y, prec); fmpz_clear(e); return; } arf_get_fmpz_fixed_si(e, ymid, -1); acb_sqrt(z, x, prec + fmpz_bits(e)); acb_pow_fmpz_binexp(z, z, e, prec); } fmpz_clear(e); return; } } _acb_pow_arb_exp(z, x, y, prec); }
void acb_mat_det(acb_t det, const acb_mat_t A, slong prec) { slong n; if (!acb_mat_is_square(A)) { flint_printf("acb_mat_det: a square matrix is required!\n"); flint_abort(); } n = acb_mat_nrows(A); if (n == 0) { acb_one(det); } else if (n == 1) { acb_set_round(det, acb_mat_entry(A, 0, 0), prec); } else if (n == 2) { _acb_mat_det_cofactor_2x2(det, A, prec); } else if (!acb_mat_is_finite(A)) { acb_indeterminate(det); } else if (acb_mat_is_tril(A) || acb_mat_is_triu(A)) { acb_mat_diag_prod(det, A, prec); } else if (n == 3) { _acb_mat_det_cofactor_3x3(det, A, prec); /* note: 4x4 performs worse than LU */ } else { if (n <= 14 || prec > 10.0 * n) acb_mat_det_lu(det, A, prec); else acb_mat_det_precond(det, A, prec); } }
int elliptic(acb_ptr out, const acb_t inp, void * params, long order, long prec) { acb_ptr t; t = _acb_vec_init(order); acb_set(t, inp); if (order > 1) acb_one(t + 1); _acb_poly_sin_series(t, t, FLINT_MIN(2, order), order, prec); _acb_poly_mullow(out, t, order, t, order, order, prec); _acb_vec_scalar_mul_2exp_si(t, out, order, -1); acb_sub_ui(t, t, 1, prec); _acb_vec_neg(t, t, order); _acb_poly_rsqrt_series(out, t, order, order, prec); _acb_vec_clear(t, order); return 0; }
static void bsplit(acb_t p, acb_t q, const acb_t x, ulong a, ulong b, slong prec) { if (b - a < 8) { ulong k; acb_t t; acb_one(p); acb_add_ui(q, x, a, prec); acb_init(t); for (k = a + 1; k < b; k++) { acb_add_ui(t, x, k, prec); acb_mul(p, p, t, prec); acb_add(p, p, q, prec); acb_mul(q, q, t, prec); } acb_clear(t); } else { acb_t r, s; ulong m; acb_init(r); acb_init(s); m = a + (b - a) / 2; bsplit(p, q, x, a, m, prec); bsplit(r, s, x, m, b, prec); acb_mul(p, p, s, prec); acb_mul(r, r, q, prec); acb_add(p, p, r, prec); acb_mul(q, q, s, prec); acb_clear(r); acb_clear(s); } }
void acb_unit_root(acb_t res, ulong order, slong prec) { switch (order) { case 1: acb_one(res); break; case 2: acb_set_si(res, -1); break; case 4: acb_onei(res); break; default: _acb_unit_root(res, order, prec); break; } }
/* (+/- iz)^(-1/2-v) * z^v * exp(+/- iz) */ void acb_hypgeom_bessel_j_asymp_prefactors_fallback(acb_t Ap, acb_t Am, acb_t C, const acb_t nu, const acb_t z, long prec) { acb_t t, u, v; acb_init(t); acb_init(u); acb_init(v); /* v = -1/2-nu */ acb_one(v); acb_mul_2exp_si(v, v, -1); acb_add(v, v, nu, prec); acb_neg(v, v); acb_mul_onei(t, z); /* t = iz */ acb_neg(u, t); /* u = -iz */ /* Ap, Am = (+/- iz)^(-1/2-nu) */ acb_pow(Ap, t, v, prec); acb_pow(Am, u, v, prec); /* Ap, Am *= exp(+/- iz) */ acb_exp_invexp(u, v, t, prec); acb_mul(Ap, Ap, u, prec); acb_mul(Am, Am, v, prec); /* z^nu */ acb_pow(t, z, nu, prec); acb_mul(Ap, Ap, t, prec); acb_mul(Am, Am, t, prec); /* (2 pi)^(-1/2) */ acb_const_pi(C, prec); acb_mul_2exp_si(C, C, 1); acb_rsqrt(C, C, prec); acb_clear(t); acb_clear(u); acb_clear(v); }
void integrals_edge_factors_gc(acb_ptr res, const acb_t cab, const acb_t ba2, sec_t c, slong prec) { slong i; acb_t cj, ci; acb_init(cj); acb_init(ci); /* polynomial shift */ acb_vec_polynomial_shift(res, cab, c.g, prec); /* constants cj, j = 1 */ /* c_1 = (1-zeta^-1) ba2^(-d/2) (-I)^i * = 2 / ba2^(d/2) */ acb_pow_ui(cj, ba2, c.d / 2, prec); if (c.d % 2) { acb_t t; acb_init(t); acb_sqrt(t, ba2, prec); acb_mul(cj, cj, t, prec); acb_clear(t); } acb_inv(cj, cj, prec); acb_mul_2exp_si(cj, cj, 1); _acb_vec_scalar_mul(res, res, c.g, cj, prec); /* constant ci = -I * ba2*/ acb_one(ci); for (i = 1; i < c.g; i++) { acb_mul(ci, ci, ba2, prec); acb_div_onei(ci, ci); acb_mul(res + i, res + i, ci, prec); } acb_clear(ci); acb_clear(cj); }
static void phase(acb_t res, const arb_t re, const arb_t im) { if (arb_is_nonnegative(re) || arb_is_negative(im)) { acb_one(res); } else if (arb_is_negative(re) && arb_is_nonnegative(im)) { acb_set_si(res, -3); } else { arb_zero(acb_imagref(res)); /* -1 +/- 2 */ arf_set_si(arb_midref(acb_realref(res)), -1); mag_one(arb_radref(acb_realref(res))); mag_mul_2exp_si(arb_radref(acb_realref(res)), arb_radref(acb_realref(res)), 1); } }
void _acb_poly_taylor_shift_divconquer(acb_ptr poly, const acb_t c, slong len, slong prec) { acb_struct d[2]; if (len <= 1 || acb_is_zero(c)) return; if (len == 2) { acb_addmul(poly, poly + 1, c, prec); return; } d[0] = *c; acb_init(d + 1); acb_one(d + 1); /* no need to free */ _acb_poly_compose_divconquer(poly, poly, len, d, 2, prec); }
static void _acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, long prec) { 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); } }
static __inline__ void _log_rising_ui_series(acb_ptr t, const acb_t x, slong r, slong len, slong prec) { acb_struct f[2]; slong rflen; acb_init(f); acb_init(f + 1); acb_set(f, x); acb_one(f + 1); rflen = FLINT_MIN(len, r + 1); _acb_poly_rising_ui_series(t, f, FLINT_MIN(2, len), r, rflen, prec); _acb_poly_log_series(t, t, rflen, len, prec); _acb_log_rising_correct_branch(t, t, x, r, prec); acb_clear(f); acb_clear(f + 1); }
void acb_hypgeom_ci_2f3(acb_t res, const acb_t z, slong prec) { acb_t a, t, u; acb_struct b[3]; acb_init(a); acb_init(b); acb_init(b + 1); acb_init(b + 2); acb_init(t); acb_init(u); acb_one(a); acb_set_ui(b, 2); acb_set(b + 1, b); acb_set_ui(b + 2, 3); acb_mul_2exp_si(b + 2, b + 2, -1); acb_mul(t, z, z, prec); acb_mul_2exp_si(t, t, -2); acb_neg(t, t); acb_hypgeom_pfq_direct(u, a, 1, b, 3, t, -1, prec); acb_mul(u, u, t, prec); acb_log(t, z, prec); acb_add(u, u, t, prec); arb_const_euler(acb_realref(t), prec); arb_add(acb_realref(u), acb_realref(u), acb_realref(t), prec); acb_swap(res, u); acb_clear(a); acb_clear(b); acb_clear(b + 1); acb_clear(b + 2); acb_clear(t); acb_clear(u); }