/* assumes no aliasing of w and p */ void acb_lambertw_branchpoint_series(acb_t w, const acb_t t, int bound, slong prec) { slong i; static const int coeffs[] = {-130636800,130636800,-43545600,19958400, -10402560,5813640,-3394560,2042589,-1256320}; acb_zero(w); for (i = 8; i >= 0; i--) { acb_mul(w, w, t, prec); acb_add_si(w, w, coeffs[i], prec); } acb_div_si(w, w, -coeffs[0], prec); if (bound) { mag_t err; mag_init(err); acb_get_mag(err, t); mag_geom_series(err, err, 9); if (acb_is_real(t)) arb_add_error_mag(acb_realref(w), err); else acb_add_error_mag(w, err); mag_clear(err); } }
static void bsplit(arb_poly_t pol, const arb_t sqrtD, const slong * qbf, slong a, slong b, slong prec) { if (b - a == 0) { arb_poly_one(pol); } else if (b - a == 1) { acb_t z; acb_init(z); /* j((-b+sqrt(-D))/(2a)) */ arb_set_si(acb_realref(z), -FLINT_ABS(qbf[3 * a + 1])); arb_set(acb_imagref(z), sqrtD); acb_div_si(z, z, 2 * qbf[3 * a], prec); acb_modular_j(z, z, prec); if (qbf[3 * a + 1] < 0) { /* (x^2 - 2re(j) x + |j|^2) */ arb_poly_fit_length(pol, 3); arb_mul(pol->coeffs, acb_realref(z), acb_realref(z), prec); arb_addmul(pol->coeffs, acb_imagref(z), acb_imagref(z), prec); arb_mul_2exp_si(pol->coeffs + 1, acb_realref(z), 1); arb_neg(pol->coeffs + 1, pol->coeffs + 1); arb_one(pol->coeffs + 2); _arb_poly_set_length(pol, 3); } else { /* (x-j) */ arb_poly_fit_length(pol, 2); arb_neg(pol->coeffs, acb_realref(z)); arb_one(pol->coeffs + 1); _arb_poly_set_length(pol, 2); } acb_clear(z); } else { arb_poly_t tmp; arb_poly_init(tmp); bsplit(pol, sqrtD, qbf, a, a + (b - a) / 2, prec); bsplit(tmp, sqrtD, qbf, a + (b - a) / 2, b, prec); arb_poly_mul(pol, pol, tmp, prec); arb_poly_clear(tmp); } }