void _acb_poly_div_root(acb_ptr Q, acb_t R, acb_srcptr A, slong len, const acb_t c, slong prec) { acb_t r, t; slong i; if (len < 2) { acb_zero(R); return; } acb_init(r); acb_init(t); acb_set(t, A + len - 2); acb_set(Q + len - 2, A + len - 1); acb_set(r, Q + len - 2); /* TODO: avoid the extra assignments (but still support aliasing) */ for (i = len - 2; i > 0; i--) { acb_mul(r, r, c, prec); acb_add(r, r, t, prec); acb_set(t, A + i - 1); acb_set(Q + i - 1, r); } acb_mul(r, r, c, prec); acb_add(R, r, t, prec); acb_clear(r); acb_clear(t); }
void _acb_poly_evaluate_rectangular(acb_t y, acb_srcptr poly, slong len, const acb_t x, slong prec) { slong i, j, m, r; acb_ptr xs; acb_t s, t, c; if (len < 3) { if (len == 0) { acb_zero(y); } else if (len == 1) { acb_set_round(y, poly + 0, prec); } else if (len == 2) { acb_mul(y, x, poly + 1, prec); acb_add(y, y, poly + 0, prec); } return; } m = n_sqrt(len) + 1; r = (len + m - 1) / m; xs = _acb_vec_init(m + 1); acb_init(s); acb_init(t); acb_init(c); _acb_vec_set_powers(xs, x, m + 1, prec); acb_set(y, poly + (r - 1) * m); for (j = 1; (r - 1) * m + j < len; j++) acb_addmul(y, xs + j, poly + (r - 1) * m + j, prec); for (i = r - 2; i >= 0; i--) { acb_set(s, poly + i * m); for (j = 1; j < m; j++) acb_addmul(s, xs + j, poly + i * m + j, prec); acb_mul(y, y, xs + m, prec); acb_add(y, y, s, prec); } _acb_vec_clear(xs, m + 1); acb_clear(s); acb_clear(t); acb_clear(c); }
void _acb_poly_reverse(acb_ptr res, acb_srcptr poly, long len, long n) { if (res == poly) { long i; for (i = 0; i < n / 2; i++) { acb_struct t = res[i]; res[i] = res[n - 1 - i]; res[n - 1 - i] = t; } for (i = 0; i < n - len; i++) acb_zero(res + i); } else { long i; for (i = 0; i < n - len; i++) acb_zero(res + i); for (i = 0; i < len; i++) acb_set(res + (n - len) + i, poly + (len - 1) - i); } }
void acb_mat_transpose(acb_mat_t B, const acb_mat_t A) { slong i, j; if (acb_mat_nrows(B) != acb_mat_ncols(A) || acb_mat_ncols(B) != acb_mat_nrows(A)) { flint_printf("Exception (acb_mat_transpose). Incompatible dimensions.\n"); flint_abort(); } if (acb_mat_is_empty(A)) return; if (A == B) /* In-place, guaranteed to be square */ { for (i = 0; i < acb_mat_nrows(A) - 1; i++) { for (j = i + 1; j < acb_mat_ncols(A); j++) { acb_swap(acb_mat_entry(A, i, j), acb_mat_entry(A, j, i)); } } } else /* Not aliased; general case */ { for (i = 0; i < acb_mat_nrows(B); i++) for (j = 0; j < acb_mat_ncols(B); j++) acb_set(acb_mat_entry(B, i, j), acb_mat_entry(A, j, i)); } }
void acb_dot_simple(acb_t res, const acb_t initial, int subtract, acb_srcptr x, slong xstep, acb_srcptr y, slong ystep, slong len, slong prec) { slong i; if (len <= 0) { if (initial == NULL) acb_zero(res); else acb_set_round(res, initial, prec); return; } if (initial == NULL) { acb_mul(res, x, y, prec); } else { if (subtract) acb_neg(res, initial); else acb_set(res, initial); acb_addmul(res, x, y, prec); } for (i = 1; i < len; i++) acb_addmul(res, x + i * xstep, y + i * ystep, prec); if (subtract) acb_neg(res, res); }
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; }
int acb_mat_lu(long * P, acb_mat_t LU, const acb_mat_t A, long prec) { acb_t d, e; acb_ptr * a; long i, j, m, n, r, row, col; int result; m = acb_mat_nrows(A); n = acb_mat_ncols(A); result = 1; if (m == 0 || n == 0) return result; acb_mat_set(LU, A); a = LU->rows; row = col = 0; for (i = 0; i < m; i++) P[i] = i; acb_init(d); acb_init(e); while (row < m && col < n) { r = acb_mat_find_pivot_partial(LU, row, m, col); if (r == -1) { result = 0; break; } else if (r != row) acb_mat_swap_rows(LU, P, row, r); acb_set(d, a[row] + col); for (j = row + 1; j < m; j++) { acb_div(e, a[j] + col, d, prec); acb_neg(e, e); _acb_vec_scalar_addmul(a[j] + col, a[row] + col, n - col, e, prec); acb_zero(a[j] + col); acb_neg(a[j] + row, e); } row++; col++; } acb_clear(d); acb_clear(e); return result; }
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_lambertw_left(acb_t res, const acb_t z, const fmpz_t k, slong prec) { if (acb_contains_zero(z) && !(fmpz_equal_si(k, -1) && acb_is_real(z))) { acb_indeterminate(res); return; } if (arb_is_positive(acb_imagref(z))) { acb_lambertw(res, z, k, 0, prec); } else if (arb_is_nonpositive(acb_imagref(z))) { fmpz_t kk; fmpz_init(kk); fmpz_add_ui(kk, k, 1); fmpz_neg(kk, kk); acb_conj(res, z); acb_lambertw(res, res, kk, 0, prec); acb_conj(res, res); fmpz_clear(kk); } else { acb_t za, zb; fmpz_t kk; acb_init(za); acb_init(zb); fmpz_init(kk); acb_set(za, z); acb_conj(zb, z); arb_nonnegative_part(acb_imagref(za), acb_imagref(za)); arb_nonnegative_part(acb_imagref(zb), acb_imagref(zb)); fmpz_add_ui(kk, k, 1); fmpz_neg(kk, kk); acb_lambertw(za, za, k, 0, prec); acb_lambertw(zb, zb, kk, 0, prec); acb_conj(zb, zb); acb_union(res, za, zb, prec); acb_clear(za); acb_clear(zb); fmpz_clear(kk); } }
void acb_hypgeom_bessel_jy(acb_t res1, acb_t res2, const acb_t nu, const acb_t z, slong prec) { acb_t jnu, t, u, v; acb_init(jnu); acb_init(t); acb_init(u); acb_init(v); acb_hypgeom_bessel_j(jnu, nu, z, prec); if (acb_is_int(nu)) { int is_real = acb_is_real(nu) && acb_is_real(z) && arb_is_positive(acb_realref(z)); acb_mul_onei(t, z); acb_hypgeom_bessel_k(t, nu, t, prec); acb_onei(u); acb_pow(u, u, nu, prec); acb_mul(t, t, u, prec); acb_const_pi(u, prec); acb_div(t, t, u, prec); acb_mul_2exp_si(t, t, 1); acb_neg(t, t); phase(v, acb_realref(z), acb_imagref(z)); acb_mul(u, jnu, v, prec); acb_mul_onei(u, u); acb_sub(res2, t, u, prec); if (is_real) arb_zero(acb_imagref(res2)); } else { acb_sin_cos_pi(t, u, nu, prec); acb_mul(v, jnu, u, prec); acb_neg(u, nu); acb_hypgeom_bessel_j(u, u, z, prec); acb_sub(v, v, u, prec); acb_div(res2, v, t, prec); } if (res1 != NULL) acb_set(res1, jnu); acb_clear(jnu); acb_clear(t); acb_clear(u); acb_clear(v); }
void _acb_poly_compose_series_brent_kung(acb_ptr res, acb_srcptr poly1, long len1, acb_srcptr poly2, long len2, long n, long prec) { acb_mat_t A, B, C; acb_ptr t, h; long i, m; if (n == 1) { acb_set(res, poly1); return; } m = n_sqrt(n) + 1; acb_mat_init(A, m, n); acb_mat_init(B, m, m); acb_mat_init(C, m, n); h = _acb_vec_init(n); t = _acb_vec_init(n); /* Set rows of B to the segments of poly1 */ for (i = 0; i < len1 / m; i++) _acb_vec_set(B->rows[i], poly1 + i*m, m); _acb_vec_set(B->rows[i], poly1 + i*m, len1 % m); /* Set rows of A to powers of poly2 */ acb_set_ui(A->rows[0] + 0, 1UL); _acb_vec_set(A->rows[1], poly2, len2); for (i = 2; i < m; i++) _acb_poly_mullow(A->rows[i], A->rows[(i + 1) / 2], n, A->rows[i / 2], n, n, prec); acb_mat_mul(C, B, A, prec); /* Evaluate block composition using the Horner scheme */ _acb_vec_set(res, C->rows[m - 1], n); _acb_poly_mullow(h, A->rows[m - 1], n, poly2, len2, n, prec); for (i = m - 2; i >= 0; i--) { _acb_poly_mullow(t, res, n, h, n, n, prec); _acb_poly_add(res, t, n, C->rows[i], n, prec); } _acb_vec_clear(h, n); _acb_vec_clear(t, n); acb_mat_clear(A); acb_mat_clear(B); acb_mat_clear(C); }
void acb_mat_set(acb_mat_t dest, const acb_mat_t src) { slong i, j; if (dest != src && acb_mat_ncols(src) != 0) { for (i = 0; i < acb_mat_nrows(src); i++) for (j = 0; j < acb_mat_ncols(src); j++) acb_set(acb_mat_entry(dest, i, j), acb_mat_entry(src, i, j)); } }
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_modular_delta(acb_t z, const acb_t tau, long prec) { psl2z_t g; arf_t one_minus_eps; acb_t tau_prime, t1, t2, t3, t4, q; psl2z_init(g); arf_init(one_minus_eps); acb_init(tau_prime); acb_init(t1); acb_init(t2); acb_init(t3); acb_init(t4); acb_init(q); arf_set_ui_2exp_si(one_minus_eps, 63, -6); acb_modular_fundamental_domain_approx(tau_prime, g, tau, one_minus_eps, prec); acb_exp_pi_i(q, tau_prime, prec); acb_modular_theta_const_sum(t2, t3, t4, q, prec); /* (t2 t3 t4) ^ 8 * q^2 */ acb_mul(t1, t2, t3, prec); acb_mul(t1, t1, t4, prec); acb_mul(t1, t1, t1, prec); acb_mul(t1, t1, t1, prec); acb_mul(t1, t1, q, prec); acb_mul(t1, t1, t1, prec); acb_mul_2exp_si(t1, t1, -8); if (!fmpz_is_zero(&g->c)) { acb_mul_fmpz(t2, tau, &g->c, prec); acb_add_fmpz(t2, t2, &g->d, prec); acb_pow_ui(t2, t2, 12, prec); acb_div(t1, t1, t2, prec); } acb_set(z, t1); psl2z_clear(g); arf_clear(one_minus_eps); acb_clear(tau_prime); acb_clear(t1); acb_clear(t2); acb_clear(t3); acb_clear(t4); acb_clear(q); }
/* u[0..l1[ contains roots re(ui)<=0 u[l1..d-2[ roots with re(ui) > 0 the last two components are set to (b-a)/2 and (a+b)/(b-a) returns l1 */ slong ab_points(acb_ptr u, acb_srcptr x, edge_t e, slong d, slong prec) { slong k, l; acb_t ab, ba; /* a + b and b - a */ acb_init(ab); acb_init(ba); acb_set(ba, x + e.b); acb_sub(ba, ba, x + e.a, prec); acb_set(ab, x + e.a); acb_add(ab, ba, x + e.b, prec); for (k = 0, l = 0; k < d; k++) { if (k == e.a || k == e.b) continue; acb_mul_2exp_si(u + l, x + k, 1); acb_sub(u + l, u + l, ab, prec); acb_div(u + l, u + l, ba, prec); l++; } /* now l = d - 2, set last two */ acb_mul_2exp_si(u + l, ba, -1); acb_div(u + l + 1, ab, ba, prec); /* reorder */ for (k = 0; k < l; k++) if (arb_is_positive(acb_realref(u + k))) acb_swap(u + k--, u + l--); acb_clear(ab); acb_clear(ba); return l; }
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_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); }
/* 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 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); } }
/* res = src * (c + x) */ void _acb_poly_mullow_cpx(acb_ptr res, acb_srcptr src, slong len, const acb_t c, slong trunc, slong prec) { slong i; if (len < trunc) acb_set(res + len, src + len - 1); for (i = len - 1; i > 0; i--) { acb_mul(res + i, src + i, c, prec); acb_add(res + i, res + i, src + i - 1, prec); } acb_mul(res, src, c, prec); }
void sec_init(sec_t * c, slong m, acb_srcptr x, slong d) { slong k; c->m = m; c->d = d; c->delta = n_gcd(m,d); c->g = ((m-1)*(d-1) - c->delta + 1)/ 2; c->roots = _acb_vec_init(d); for (k = 0; k < d; k++) acb_set(c->roots + k, x + k); }
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); }
/* compose by poly2 = a*x^n + c, no aliasing; n >= 1 */ void _acb_poly_compose_axnc(acb_ptr res, acb_srcptr poly1, slong len1, const acb_t c, const acb_t a, slong n, slong prec) { slong i; _acb_vec_set_round(res, poly1, len1, prec); /* shift by c (c = 0 case will be fast) */ _acb_poly_taylor_shift(res, c, len1, prec); /* multiply by powers of a */ if (!acb_is_one(a)) { if (acb_equal_si(a, -1)) { for (i = 1; i < len1; i += 2) acb_neg(res + i, res + i); } else if (len1 == 2) { acb_mul(res + 1, res + 1, a, prec); } else { acb_t t; acb_init(t); acb_set(t, a); for (i = 1; i < len1; i++) { acb_mul(res + i, res + i, t, prec); if (i + 1 < len1) acb_mul(t, t, a, prec); } acb_clear(t); } } /* stretch */ for (i = len1 - 1; i >= 1 && n > 1; i--) { acb_swap(res + i * n, res + i); _acb_vec_zero(res + (i - 1) * n + 1, n - 1); } }
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; }
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_shift_right(acb_ptr res, acb_srcptr poly, slong len, slong n) { slong i; /* Copy in forward order to avoid writing over unshifted coefficients */ if (res != poly) { for (i = 0; i < len - n; i++) acb_set(res + i, poly + n + i); } else { for (i = 0; i < len - n; i++) acb_swap(res + i, res + n + i); } }
static void _acb_hypgeom_2f1r_reduced(acb_t res, const acb_t b, const acb_t c, const acb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_neg(u, b); acb_pow(t, t, u, prec); acb_rgamma(u, c, prec); acb_mul(t, t, u, prec); acb_set(res, t); acb_clear(t); acb_clear(u); return; }
void _acb_poly_compose_series(acb_ptr res, acb_srcptr poly1, slong len1, acb_srcptr poly2, slong len2, slong n, slong prec) { if (len2 == 1) { acb_set_round(res, poly1, prec); _acb_vec_zero(res + 1, n - 1); } else if (_acb_vec_is_zero(poly2 + 1, len2 - 2)) /* poly2 is a monomial */ { slong i, j; acb_t t; acb_init(t); acb_set(t, poly2 + len2 - 1); acb_set_round(res, poly1, prec); for (i = 1, j = len2 - 1; i < len1 && j < n; i++, j += len2 - 1) { acb_mul(res + j, poly1 + i, t, prec); if (i + 1 < len1 && j + len2 - 1 < n) acb_mul(t, t, poly2 + len2 - 1, prec); } if (len2 != 2) for (i = 1; i < n; i++) if (i % (len2 - 1) != 0) acb_zero(res + i); acb_clear(t); } else if (len1 < 6 || n < 6) { _acb_poly_compose_series_horner(res, poly1, len1, poly2, len2, n, prec); } else { _acb_poly_compose_series_brent_kung(res, poly1, len1, poly2, len2, n, prec); } }
void acb_lambertw_cleared_cut(acb_t res, const acb_t z, const fmpz_t k, int flags, slong prec) { acb_t ez1; acb_init(ez1); /* compute e*z + 1 */ arb_const_e(acb_realref(ez1), prec); acb_mul(ez1, ez1, z, prec); acb_add_ui(ez1, ez1, 1, prec); if (acb_is_exact(z)) { acb_lambertw_main(res, z, ez1, k, flags, prec); } else { acb_t zz; mag_t err, rad; mag_init(err); mag_init(rad); acb_init(zz); acb_lambertw_bound_deriv(err, z, ez1, k); mag_hypot(rad, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); mag_mul(err, err, rad); acb_set(zz, z); mag_zero(arb_radref(acb_realref(zz))); mag_zero(arb_radref(acb_imagref(zz))); /* todo: recompute ez1? */ acb_lambertw_main(res, zz, ez1, k, flags, prec); acb_add_error_mag(res, err); mag_clear(err); mag_clear(rad); acb_clear(zz); } acb_clear(ez1); }
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); }