Ejemplo n.º 1
0
void
acb_real_min(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec)
{
    arb_t t;

    if (!acb_is_finite(x) || !acb_is_finite(y))
    {
        acb_indeterminate(res);
        return;
    }

    arb_init(t);
    arb_sub(t, acb_realref(x), acb_realref(y), prec);

    if (arb_is_positive(t))
        acb_set_round(res, y, prec);
    else if (arb_is_negative(t))
        acb_set_round(res, x, prec);
    else if (!analytic)
        acb_union(res, x, y, prec);
    else
        acb_indeterminate(res);

    arb_clear(t);
}
Ejemplo n.º 2
0
void
acb_hypgeom_fresnel(acb_t res1, acb_t res2, const acb_t z, int normalized, slong prec)
{
    slong wp;
    acb_t w;
    arb_t c;

    if (!acb_is_finite(z))
    {
        if (res1 != NULL) acb_indeterminate(res1);
        if (res2 != NULL) acb_indeterminate(res2);
        return;
    }

    acb_init(w);
    arb_init(c);

    wp = prec + 8;

    if (normalized)
    {
        arb_const_pi(c, wp);
        arb_sqrt(c, c, wp);
        arb_mul_2exp_si(c, c, -1);
        acb_mul_arb(w, z, c, wp);
        acb_hypgeom_fresnel_erf_error(res1, res2, w, wp);
    }
    else
    {
        arb_sqrt_ui(c, 2, wp);
        arb_mul_2exp_si(c, c, -1);
        acb_mul_arb(w, z, c, wp);
        acb_hypgeom_fresnel_erf_error(res1, res2, w, wp);
        arb_const_pi(c, wp);
        arb_mul_2exp_si(c, c, -1);
        arb_sqrt(c, c, wp);

        if (res1 != NULL) acb_mul_arb(res1, res1, c, wp);
        if (res2 != NULL) acb_mul_arb(res2, res2, c, wp);
    }

    if (res1 != NULL)
    {
        acb_mul_2exp_si(res1, res1, -2);
        acb_set_round(res1, res1, prec);
    }

    if (res2 != NULL)
    {
        acb_mul_2exp_si(res2, res2, -2);
        acb_set_round(res2, res2, prec);
    }

    acb_clear(w);
    arb_clear(c);
}
Ejemplo n.º 3
0
void
_acb_poly_add(acb_ptr res, acb_srcptr poly1, long len1,
    acb_srcptr poly2, long len2, long prec)
{
    long i, min = FLINT_MIN(len1, len2);

    for (i = 0; i < min; i++)
        acb_add(res + i, poly1 + i, poly2 + i, prec);

    for (i = min; i < len1; i++)
        acb_set_round(res + i, poly1 + i, prec);

    for (i = min; i < len2; i++)
        acb_set_round(res + i, poly2 + i, prec);
}
Ejemplo n.º 4
0
void
_acb_poly_compose(acb_ptr res,
    acb_srcptr poly1, slong len1,
    acb_srcptr poly2, slong len2, slong prec)
{
    if (len1 == 1)
    {
        acb_set_round(res, poly1, prec);
    }
    else if (len2 == 1)
    {
        _acb_poly_evaluate(res, poly1, len1, poly2, prec);
    }
    else if (_acb_vec_is_zero(poly2 + 1, len2 - 2))
    {
        _acb_poly_compose_axnc(res, poly1, len1, poly2, poly2 + len2 - 1, len2 - 1, prec);
    }
    else if (len1 <= 7)
    {
        _acb_poly_compose_horner(res, poly1, len1, poly2, len2, prec);
    }
    else
    {
        _acb_poly_compose_divconquer(res, poly1, len1, poly2, len2, prec);
    }
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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);
    }
}
Ejemplo n.º 8
0
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);
    }
}
Ejemplo n.º 9
0
Archivo: m.c Proyecto: argriffing/arb
void
acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec)
{
    int asymp, kummer;
    slong wp;

    acb_hypgeom_m_choose(&asymp, &kummer, &wp, a, b, z, regularized, prec);

    if (asymp)
    {
        acb_hypgeom_m_asymp(res, a, b, z, regularized, wp);
    }
    else
    {
        _acb_hypgeom_m_1f1(res, a, b, z, regularized, wp, FLINT_MIN(wp, prec), kummer);
    }

    acb_set_round(res, res, prec);
}
Ejemplo n.º 10
0
void
acb_hypgeom_erf_1f1(acb_t res, const acb_t z, slong prec,
    slong wp, int more_imaginary)
{
    if (acb_rel_accuracy_bits(z) >= wp)
    {
        if (more_imaginary)
            acb_hypgeom_erf_1f1a(res, z, wp);
        else
            acb_hypgeom_erf_1f1b(res, z, wp);
    }
    else
    {
        acb_t zmid;
        mag_t re_err, im_err;

        acb_init(zmid);
        mag_init(re_err);
        mag_init(im_err);

        acb_hypgeom_erf_propagated_error(re_err, im_err, z);
        arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z)));
        arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z)));

        if (more_imaginary)
            acb_hypgeom_erf_1f1a(res, zmid, wp);
        else
            acb_hypgeom_erf_1f1b(res, zmid, wp);

        arb_add_error_mag(acb_realref(res), re_err);
        arb_add_error_mag(acb_imagref(res), im_err);

        acb_clear(zmid);
        mag_clear(re_err);
        mag_clear(im_err);
    }

    acb_set_round(res, res, prec);
}
Ejemplo n.º 11
0
void
_acb_mat_diag_prod(acb_t res, const acb_mat_t A, slong a, slong b, slong prec)
{
    if (b - a == 0)
        acb_one(res);
    else if (b - a == 1)
        acb_set_round(res, acb_mat_entry(A, a, a), prec);
    else if (b - a == 2)
        acb_mul(res, acb_mat_entry(A, a, a), acb_mat_entry(A, a + 1, a + 1), prec);
    else if (b - a == 3)
    {
        acb_mul(res, acb_mat_entry(A, a, a), acb_mat_entry(A, a + 1, a + 1), prec);
        acb_mul(res, res, acb_mat_entry(A, a + 2, a + 2), prec);
    }
    else
    {
        acb_t t;
        acb_init(t);
        _acb_mat_diag_prod(t, A, a, a + (b - a) / 2, prec);
        _acb_mat_diag_prod(res, A, a + (b - a) / 2, b, prec);
        acb_mul(res, res, t, prec);
        acb_clear(t);
    }
}
Ejemplo n.º 12
0
void
acb_hypgeom_airy(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong prec)
{
    arf_srcptr re, im;
    double x, y, t, zmag, z15, term_est, airy_est, abstol;
    slong n, wp;

    if (!acb_is_finite(z))
    {
        if (ai != NULL) acb_indeterminate(ai);
        if (aip != NULL) acb_indeterminate(aip);
        if (bi != NULL) acb_indeterminate(bi);
        if (bip != NULL) acb_indeterminate(bip);
        return;
    }

    re = arb_midref(acb_realref(z));
    im = arb_midref(acb_imagref(z));
    wp = prec * 1.03 + 15;

    /* tiny input -- use direct method and pick n without underflowing */
    if (arf_cmpabs_2exp_si(re, -64) < 0 && arf_cmpabs_2exp_si(im, -64) < 0)
    {
        if (arf_cmpabs_2exp_si(re, -wp) < 0 && arf_cmpabs_2exp_si(im, -wp) < 0)
        {
            n = 1;  /* very tiny input */
        }
        else
        {
            if (arf_cmpabs(re, im) > 0)
                zmag = fmpz_get_d(ARF_EXPREF(re));
            else
                zmag = fmpz_get_d(ARF_EXPREF(im));
            zmag = (zmag + 1) * (1.0 / LOG2);
            n = wp / (-zmag) + 1;
        }

        acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp);
    }  /* huge input -- use asymptotics and pick n without overflowing */
    else if ((arf_cmpabs_2exp_si(re, 64) > 0 || arf_cmpabs_2exp_si(im, 64) > 0))
    {
        if (arf_cmpabs_2exp_si(re, prec) > 0 || arf_cmpabs_2exp_si(im, prec) > 0)
        {
            n = 1;   /* very huge input */
        }
        else
        {
            x = fmpz_get_d(ARF_EXPREF(re));
            y = fmpz_get_d(ARF_EXPREF(im));
            zmag = (FLINT_MAX(x, y) - 2) * (1.0 / LOG2);
            n = asymp_pick_terms(wp, zmag);
            n = FLINT_MAX(n, 1);
        }

        acb_hypgeom_airy_asymp(ai, aip, bi, bip, z, n, wp);
    }
    else /* moderate input */
    {
        x = arf_get_d(re, ARF_RND_DOWN);
        y = arf_get_d(im, ARF_RND_DOWN);

        zmag = sqrt(x * x + y * y);
        z15 = zmag * sqrt(zmag);

        if (zmag >= 4.0 && (n = asymp_pick_terms(wp, log(zmag))) != -1)
        {
            acb_hypgeom_airy_asymp(ai, aip, bi, bip, z, n, wp);
        }
        else if (zmag <= 1.5)
        {
            t = 3 * (wp * LOG2) / (2 * z15 * EXP1);
            t = (wp * LOG2) / (2 * d_lambertw(t));
            n = FLINT_MAX(t + 1, 2);
            acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp);
        }
        else
        {
            /* estimate largest term: log2(exp(2(z^3/9)^(1/2))) */
            term_est = 0.96179669392597560491 * z15;

            /* estimate the smaller of Ai and Bi */
            airy_est = estimate_airy(x, y, (ai != NULL || aip != NULL));

            /* estimate absolute tolerance and necessary working precision */
            abstol = airy_est - wp;
            wp = wp + term_est - airy_est;
            wp = FLINT_MAX(wp, 10);

            t = 3 * (-abstol * LOG2) / (2 * z15 * EXP1);
            t = (-abstol * LOG2) / (2 * d_lambertw(t));
            n = FLINT_MAX(t + 1, 2);

            if (acb_is_exact(z))
                acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp);
            else
                acb_hypgeom_airy_direct_prop(ai, aip, bi, bip, z, n, wp);
        }
    }

    if (ai != NULL) acb_set_round(ai, ai, prec);
    if (aip != NULL) acb_set_round(aip, aip, prec);
    if (bi != NULL) acb_set_round(bi, bi, prec);
    if (bip != NULL) acb_set_round(bip, bip, prec);
}
Ejemplo n.º 13
0
void
acb_gamma_stirling_eval(acb_t s, const acb_t z, long nterms, int digamma, long prec)
{
    acb_t t, logz, zinv, zinv2;
    arb_t b;
    mag_t err;

    long k, term_prec;
    double z_mag, term_mag;

    acb_init(t);
    acb_init(logz);
    acb_init(zinv);
    acb_init(zinv2);
    arb_init(b);

    acb_log(logz, z, prec);
    acb_inv(zinv, z, prec);

    nterms = FLINT_MAX(nterms, 1);

    acb_zero(s);
    if (nterms > 1)
    {
        acb_mul(zinv2, zinv, zinv, prec);

        z_mag = arf_get_d(arb_midref(acb_realref(logz)), ARF_RND_UP) * 1.44269504088896;

        for (k = nterms - 1; k >= 1; k--)
        {
            term_mag = bernoulli_bound_2exp_si(2 * k);
            term_mag -= (2 * k - 1) * z_mag;
            term_prec = prec + term_mag;
            term_prec = FLINT_MIN(term_prec, prec);
            term_prec = FLINT_MAX(term_prec, 10);

            arb_gamma_stirling_coeff(b, k, digamma, term_prec);

            if (prec > 2000)
            {
                acb_set_round(t, zinv2, term_prec);
                acb_mul(s, s, t, term_prec);
            }
            else
                acb_mul(s, s, zinv2, term_prec);

            arb_add(acb_realref(s), acb_realref(s), b, term_prec);
        }

        if (digamma)
            acb_mul(s, s, zinv2, prec);
        else
            acb_mul(s, s, zinv, prec);
    }

    /* remainder bound */
    mag_init(err);
    acb_gamma_stirling_bound(err, z, digamma ? 1 : 0, 1, nterms);
    mag_add(arb_radref(acb_realref(s)), arb_radref(acb_realref(s)), err);
    mag_add(arb_radref(acb_imagref(s)), arb_radref(acb_imagref(s)), err);
    mag_clear(err);

    if (digamma)
    {
        acb_neg(s, s);
        acb_mul_2exp_si(zinv, zinv, -1);
        acb_sub(s, s, zinv, prec);
        acb_add(s, s, logz, prec);
    }
    else
    {
        /* (z-0.5)*log(z) - z + log(2*pi)/2 */
        arb_one(b);
        arb_mul_2exp_si(b, b, -1);
        arb_set(acb_imagref(t), acb_imagref(z));
        arb_sub(acb_realref(t), acb_realref(z), b, prec);
        acb_mul(t, logz, t, prec);
        acb_add(s, s, t, prec);
        acb_sub(s, s, z, prec);
        arb_const_log_sqrt2pi(b, prec);
        arb_add(acb_realref(s), acb_realref(s), b, prec);
    }

    acb_clear(t);
    acb_clear(logz);
    acb_clear(zinv);
    acb_clear(zinv2);
    arb_clear(b);
}
Ejemplo n.º 14
0
int
acb_mat_eig_simple_rump(acb_ptr E, acb_mat_t L, acb_mat_t R,
    const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec)
{
    slong i, j, n;
    acb_mat_t X, R2;
    int result;

    n = acb_mat_nrows(A);

    if (n == 0)
        return 1;

    if (n == 1)
    {
        acb_set_round(E, acb_mat_entry(A, 0, 0), prec);
        if (L != NULL)
            acb_one(acb_mat_entry(L, 0, 0));
        if (R != NULL)
            acb_one(acb_mat_entry(R, 0, 0));
        return 1;
    }

    acb_mat_init(X, n, 1);
    acb_mat_init(R2, n, n);

    result = 1;

    for (i = 0; i < n && result; i++)
    {
        for (j = 0; j < n; j++)
            acb_set(acb_mat_entry(X, j, 0), acb_mat_entry(R_approx, j, i));

        acb_mat_eig_enclosure_rump(E + i, NULL, X, A, E_approx + i, X, prec);

        if (!acb_is_finite(E + i))
            result = 0;

        for (j = 0; j < i; j++)
            if (acb_overlaps(E + i, E + j))
                result = 0;

        for (j = 0; j < n; j++)
            acb_set(acb_mat_entry(R2, j, i), acb_mat_entry(X, j, 0));
    }

    if (R != NULL)
    {
        if (result)
            acb_mat_set(R, R2);
        else
            acb_mat_indeterminate(R);
    }

    if (L != NULL)
    {
        if (!result || !acb_mat_inv(L, R, prec))
            acb_mat_indeterminate(L);
    }

    if (!result)
        _acb_vec_indeterminate(E, n);

    acb_mat_clear(X);
    acb_mat_clear(R2);

    return result;
}
Ejemplo n.º 15
0
void
acb_pow_fmpz_binexp(acb_t y, const acb_t b, const fmpz_t e, long prec)
{
    long i, wp, bits;

    if (-2L <= *e && *e <= 4L)
    {
        if (*e == 0L)
        {
            acb_one(y);
        }
        else if (*e == 1L)
        {
            acb_set_round(y, b, prec);
        }
        else if (*e == -1L)
        {
            acb_inv(y, b, prec);
        }
        else if (*e == 2L)
        {
            acb_mul(y, b, b, prec);
        }
        else if (*e == 3L)
        {
            acb_cube(y, b, prec);
        }
        else if (*e == 4L)
        {
            acb_mul(y, b, b, prec);
            acb_mul(y, y, y, prec);
        }
        else
        {
            acb_inv(y, b, prec);
            acb_mul(y, y, y, prec);
        }
        return;
    }

    if (fmpz_sgn(e) < 0)
    {
        fmpz_t f;
        fmpz_init(f);
        fmpz_neg(f, e);
        acb_pow_fmpz_binexp(y, b, f, prec + 2);
        acb_inv(y, y, prec);
        fmpz_clear(f);
        return;
    }

    if (!COEFF_IS_MPZ(*e) && ((*e) % 3 == 0))
    {
        fmpz e3 = (*e) / 3;
        acb_pow_fmpz_binexp(y, b, &e3, prec);
        acb_cube(y, y, prec);
        return;
    }

    if (y == b)
    {
        acb_t t;
        acb_init(t);
        acb_set(t, b);
        acb_pow_fmpz_binexp(y, t, e, prec);
        acb_clear(t);
        return;
    }

    acb_set(y, b);

    bits = fmpz_bits(e);
    wp = ARF_PREC_ADD(prec, bits);

    for (i = bits - 2; i >= 0; i--)
    {
        acb_mul(y, y, y, wp);
        if (fmpz_tstbit(e, i))
            acb_mul(y, y, b, wp);
    }
}
Ejemplo n.º 16
0
void
_acb_lambertw(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, int flags, slong prec)
{
    slong goal, ebits, ebits2, ls, lt;
    const fmpz * expo;

    /* Estimated accuracy goal. */
    /* todo: account for exponent bits and bits in k. */
    goal = acb_rel_accuracy_bits(z);
    goal = FLINT_MAX(goal, 10);
    goal = FLINT_MIN(goal, prec);

    /* Handle tiny z directly. For k >= 2, |c_k| <= 4^k / 16. */
    if (fmpz_is_zero(k)
        && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -goal / 2) < 0
        && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -goal / 2) < 0)
    {
        mag_t err;
        mag_init(err);
        acb_get_mag(err, z);
        mag_mul_2exp_si(err, err, 2);
        acb_set(res, z);
        acb_submul(res, res, res, prec);
        mag_geom_series(err, err, 3);
        mag_mul_2exp_si(err, err, -4);
        acb_add_error_mag(res, err);
        mag_clear(err);
        return;
    }

    if (arf_cmpabs(arb_midref(acb_realref(z)), arb_midref(acb_imagref(z))) >= 0)
        expo = ARF_EXPREF(arb_midref(acb_realref(z)));
    else
        expo = ARF_EXPREF(arb_midref(acb_imagref(z)));

    ebits = fmpz_bits(expo);

    /* ebits ~= log2(|log(z) + 2 pi i k|) */
    /* ebits2 ~= log2(log(log(z))) */
    ebits = FLINT_MAX(ebits, fmpz_bits(k));
    ebits = FLINT_MAX(ebits, 1) - 1;
    ebits2 = FLINT_BIT_COUNT(ebits);
    ebits2 = FLINT_MAX(ebits2, 1) - 1;

    /* We gain accuracy from the exponent when W ~ log - log log */
    if (fmpz_sgn(expo) > 0 || (fmpz_sgn(expo) < 0 && !fmpz_is_zero(k)))
    {
        goal += ebits - ebits2;
        goal = FLINT_MAX(goal, 10);
        goal = FLINT_MIN(goal, prec);

        /* The asymptotic series with truncation L, M gives us about 
           t - max(2+lt+L*(2+ls), M*(2+lt)) bits of accuracy where
           ls = -ebits, lt = ebits2 - ebits. */
        ls = 2 - ebits;
        lt = 2 + ebits2 - ebits;

        if (ebits - FLINT_MAX(lt + 1*ls, 1*lt) > goal)
        {
            acb_lambertw_asymp(res, z, k, 1, 1, goal);
            acb_set_round(res, res, prec);
            return;
        }
        else if (ebits - FLINT_MAX(lt + 3*ls, 5*lt) > goal)
        {
            acb_lambertw_asymp(res, z, k, 3, 5, goal);
            acb_set_round(res, res, prec);
            return;
        }
    }

    /* Extremely close to the branch point at -1/e, use the series expansion directly. */
    if (acb_lambertw_try_near_branch_point(res, z, ez1, k, flags, goal))
    {
        acb_set_round(res, res, prec);
        return;
    }

    /* compute union of both sides */
    if (acb_lambertw_branch_crossing(z, ez1, k))
    {
        acb_t za, zb, eza1, ezb1;
        fmpz_t kk;

        acb_init(za);
        acb_init(zb);
        acb_init(eza1);
        acb_init(ezb1);
        fmpz_init(kk);

        fmpz_neg(kk, k);

        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));

        acb_set(eza1, ez1);
        acb_conj(ezb1, ez1);
        arb_nonnegative_part(acb_imagref(eza1), acb_imagref(eza1));
        arb_nonnegative_part(acb_imagref(ezb1), acb_imagref(ezb1));

        /* Check series expansion again, because now there is no crossing. */
        if (!acb_lambertw_try_near_branch_point(res, za, eza1, k, flags, goal))
            acb_lambertw_cleared_cut_fix_small(za, za, eza1, k, flags, goal);

        if (!acb_lambertw_try_near_branch_point(res, zb, ezb1, kk, flags, goal))
            acb_lambertw_cleared_cut_fix_small(zb, zb, ezb1, kk, flags, goal);

        acb_conj(zb, zb);
        acb_union(res, za, zb, prec);

        acb_clear(za);
        acb_clear(zb);
        acb_clear(eza1);
        acb_clear(ezb1);
        fmpz_clear(kk);
    }
    else
    {
        acb_lambertw_cleared_cut_fix_small(res, z, ez1, k, flags, goal);
        acb_set_round(res, res, prec);
    }
}
Ejemplo n.º 17
0
void
acb_modular_theta_const_sum_rs(acb_t theta2, acb_t theta3, acb_t theta4,
                               const acb_t q, long N, long prec)
{
    long * tab;
    long k, term_prec, i, e, eprev;
    long M, m2, m3, num_square, num_trigonal;
    double log2q_approx, log2term_approx;
    acb_ptr qpow;
    acb_t tmp1, tmp2;
    mag_t qmag;

    mag_init(qmag);
    acb_get_mag(qmag, q);
    log2q_approx = mag_get_log2_d_approx(qmag);
    mag_clear(qmag);

    acb_init(tmp1);
    acb_init(tmp2);

    /* choose rectangular splitting parameters */
    m2 = acb_modular_rs_optimal_m(trigonal_best_m, trigonal_best_m_residues, N);
    m3 = acb_modular_rs_optimal_m(square_best_m, square_best_m_residues, N);
    M = FLINT_MAX(m2, m3) + 1;

    /* build addition sequence */
    tab = flint_calloc(M, sizeof(long));

    for (k = 0; k*(k+1) < N; k++)
        tab[(k*(k+1)) % m2] = -1;
    num_trigonal = k;

    for (k = 0; k*k < N; k++)
        tab[(k*k) % m3] = -1;
    num_square = k;

    tab[m2] = -1;
    tab[m3] = -1;

    /* compute powers in addition sequence */
    qpow = _acb_vec_init(M);
    acb_modular_fill_addseq(tab, M);

    for (k = 0; k < M; k++)
    {
        if (k == 0)
        {
            acb_one(qpow + k);
        }
        else if (k == 1)
        {
            acb_set_round(qpow + k, q, prec);
        }
        else if (tab[k] != 0)
        {
            log2term_approx = k * log2q_approx;
            term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec);
            acb_mul_approx(qpow + k, tmp1, tmp2, qpow + tab[k], qpow + k - tab[k], term_prec, prec);
        }
    }

    /* compute theta2 */
    acb_zero(theta2);
    term_prec = prec;

    for (k = num_trigonal - 1; k >= 0; k--)
    {
        e = k * (k + 1);  /* exponent */
        eprev = (k + 1) * (k + 2);

        log2term_approx = e * log2q_approx;
        term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec);

        /* giant steps */
        for (i = e / m2; i < eprev / m2; i++)
        {
            if (!acb_is_zero(theta2))
                acb_mul_approx(theta2, tmp1, tmp2, theta2, qpow + m2, term_prec, prec);
        }

        acb_add(theta2, theta2, qpow + (e % m2), prec);
    }

    acb_mul_2exp_si(theta2, theta2, 1);

    /* compute theta3, theta4 */
    acb_zero(theta3);
    acb_zero(theta4);
    term_prec = prec;

    for (k = num_square - 1; k >= 0; k--)
    {
        e = k * k;  /* exponent */
        eprev = (k + 1) * (k + 1);

        log2term_approx = e * log2q_approx;
        term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec);

        /* giant steps */
        for (i = e / m3; i < eprev / m3; i++)
        {
            if (!acb_is_zero(theta3))
                acb_mul_approx(theta3, tmp1, tmp2, theta3, qpow + m3, term_prec, prec);

            if (!acb_is_zero(theta4))
                acb_mul_approx(theta4, tmp1, tmp2, theta4, qpow + m3, term_prec, prec);
        }

        if (k == 0)
        {
            acb_mul_2exp_si(theta3, theta3, 1);
            acb_mul_2exp_si(theta4, theta4, 1);
        }

        acb_add(theta3, theta3, qpow + (e % m3), prec);

        if (k % 2 == 0)
            acb_add(theta4, theta4, qpow + (e % m3), prec);
        else
            acb_sub(theta4, theta4, qpow + (e % m3), prec);
    }

    acb_clear(tmp1);
    acb_clear(tmp2);

    _acb_vec_clear(qpow, M);
    flint_free(tab);
}
Ejemplo n.º 18
0
void
acb_modular_theta_const_sum_basecase(acb_t theta2, acb_t theta3, acb_t theta4,
    const acb_t q, slong N, slong prec)
{
    slong * tab;
    slong k, term_prec;
    double log2q_approx, log2term_approx;
    mag_t qmag;
    acb_ptr qpow;
    acb_t s1, s2, s3, t1, t2;

    if (N < 2)
    {
        acb_set_ui(theta2, 2 * (N > 0));
        acb_set_ui(theta3, N > 0);
        acb_set(theta4, theta3);
        return;
    }

    if (N < 25)
    {
        acb_t q1, q2, q4, q8, q16;

        acb_init(q1);
        acb_init(q2);
        acb_init(q4);
        acb_init(q8);
        acb_init(q16);

        acb_set_round(q1, q, prec);

        if (N > 2) acb_mul(q2, q1, q1, prec);
        if (N > 4) acb_mul(q4, q2, q2, prec);
        if (N > 9) acb_mul(q8, q4, q4, prec);
        if (N > 16) acb_mul(q16, q8, q8, prec);

        /* theta2 = 2 + 2q^2 + 2q^4 [2q^2 + 2q^8 + 2q^16] */
        if (N > 6)
        {
            if (N > 12)
            {
                acb_add(theta2, q2, q8, prec);
                if (N > 20)
                    acb_add(theta2, theta2, q16, prec);
                acb_mul(theta2, theta2, q4, prec);
            }
            else
            {
                acb_mul(theta2, q2, q4, prec);
            }
            acb_add(theta2, theta2, q2, prec);
            acb_add_ui(theta2, theta2, 1, prec);
        }
        else if (N > 2)
            acb_add_ui(theta2, q2, 1, prec);
        else
            acb_one(theta2);

        acb_mul_2exp_si(theta2, theta2, 1);

        /* theta3 = [1 + 2q^4 + 2q^16] + [2q + 2q^9] */
        /* theta4 = [1 + 2q^4 + 2q^16] - [2q + 2q^9] */
        if (N > 4)
        {
            if (N > 16)
                acb_add(q4, q4, q16, prec);
            acb_mul_2exp_si(q4, q4, 1);
            acb_add_ui(q4, q4, 1, prec);

            if (N > 9)
                acb_addmul(q1, q1, q8, prec);
            acb_mul_2exp_si(q1, q1, 1);

            acb_add(theta3, q4, q1, prec);
            acb_sub(theta4, q4, q1, prec);
        }
        else
        {
            acb_mul_2exp_si(q1, q1, 1);
            acb_add_ui(theta3, q1, 1, prec);
            acb_sub_ui(theta4, q1, 1, prec);
            acb_neg(theta4, theta4);
        }

        acb_clear(q1);
        acb_clear(q2);
        acb_clear(q4);
        acb_clear(q8);
        acb_clear(q16);

        return;
    }

    mag_init(qmag);
    acb_init(s1);
    acb_init(s2);
    acb_init(s3);
    acb_init(t1);
    acb_init(t2);

    tab = flint_calloc(N, sizeof(slong));
    qpow = _acb_vec_init(N);

    for (k = 0; k*(k+1) < N; k++) tab[k*(k+1)] = -1;
    for (k = 0; 4*k*k < N; k++) tab[4*k*k] = -1;
    for (k = 0; 4*k*(k+1) + 1 < N; k++) tab[4*k*(k+1)] = -1;
    if (N > 0) tab[0] = 0;
    if (N > 1) tab[1] = 1;

    acb_modular_fill_addseq(tab, N);

    acb_get_mag(qmag, q);
    log2q_approx = mag_get_log2_d_approx(qmag);

    for (k = 0; k < N; k++)
    {
        if (k == 0)
        {
            acb_one(qpow + k);
        }
        else if (k == 1)
        {
            acb_set_round(qpow + k, q, prec);
        }
        else if (tab[k] != 0)
        {
            log2term_approx = k * log2q_approx;
            term_prec = FLINT_MIN(FLINT_MAX(prec + log2term_approx + 16.0, 16.0), prec);
            acb_mul_approx(qpow + k, t1, t2, qpow + tab[k], qpow + k - tab[k], term_prec, prec);
        }
    }

    for (k = 0; k*(k+1) < N; k++) acb_add(s1, s1, qpow + k*(k+1), prec);
    for (k = 1; 4*k*k < N; k++) acb_add(s2, s2, qpow + 4*k*k, prec);
    for (k = 0; 4*k*(k+1) + 1 < N; k++) acb_add(s3, s3, qpow + 4*k*(k+1), prec);

    /*
    theta2 = 2 + 2q^2 + 2q^6 + 2q^12 + 2q^20 + 2q^30 + ...
    theta3 = 1 + 2 (q^4 + q^16 + ...) + 2q (1 + q^8 + q^24 + ...)
    theta4 = 1 + 2 (q^4 + q^16 + ...) - 2q (1 + q^8 + q^24 + ...)
    */
    acb_mul(s3, s3, q, prec);
    acb_mul_2exp_si(s3, s3, 1);
    acb_mul_2exp_si(s2, s2, 1);
    acb_add(theta3, s2, s3, prec);
    acb_sub(theta4, s2, s3, prec);
    acb_add_ui(theta3, theta3, 1, prec);
    acb_add_ui(theta4, theta4, 1, prec);
    acb_mul_2exp_si(theta2, s1, 1);
 
    _acb_vec_clear(qpow, N);
    flint_free(tab);

    acb_clear(s1);
    acb_clear(s2);
    acb_clear(s3);
    acb_clear(t1);
    acb_clear(t2);
    mag_clear(qmag);
}
Ejemplo n.º 19
0
void
acb_rising_ui_rs(acb_t y, const acb_t x, ulong n, ulong m, slong prec)
{
    acb_ptr xs;
    acb_t t, u, v;
    ulong i, k, rem;
    fmpz_t c, h;
    fmpz *s, *d;
    slong wp;

    if (n == 0)
    {
        acb_one(y);
        return;
    }

    if (n == 1)
    {
        acb_set_round(y, x, prec);
        return;
    }

    wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n));

    acb_init(t);
    acb_init(u);
    acb_init(v);
    fmpz_init(c);
    fmpz_init(h);

    if (m == 0)
    {
        ulong m1, m2;
        m1 = 0.2 * pow(2.0 * wp, 0.4);
        m2 = n_sqrt(n);
        m = FLINT_MIN(m1, m2);
    }

    m = FLINT_MIN(m, n);
    m = FLINT_MAX(m, 1);

    xs = _acb_vec_init(m + 1);
    d = _fmpz_vec_init(m * m);
    s = _fmpz_vec_init(m + 1);

    _acb_vec_set_powers(xs, x, m + 1, wp);

    rising_difference_polynomial(s, d, m);

    /* tail */
    rem = m;
    while (rem + m <= n)
        rem += m;
    acb_one(y);
    for (k = rem; k < n; k++)
    {
        acb_add_ui(t, xs + 1, k, wp);
        acb_mul(y, y, t, wp);
    }

    /* initial rising factorial */
    acb_zero(t);
    for (i = 1; i <= m; i++)
        acb_addmul_fmpz(t, xs + i, s + i, wp);

    acb_mul(y, y, t, wp);

    /* the leading coefficient is always the same */
    acb_mul_fmpz(xs + m - 1, xs + m - 1, d + m - 1 + 0, wp);

    for (k = 0; k + 2 * m <= n; k += m)
    {
        for (i = 0; i < m - 1; i++)
        {
            fmpz_set_ui(h, k);
            _fmpz_poly_evaluate_horner_fmpz(c, d + i * m, m - i, h);

            if (i == 0)
                acb_add_fmpz(t, t, c, wp);
            else
                acb_addmul_fmpz(t, xs + i, c, wp);
        }

        acb_add(t, t, xs + m - 1, wp);
        acb_mul(y, y, t, wp);
    }

    acb_set_round(y, y, prec);

    acb_clear(t);
    acb_clear(u);
    acb_clear(v);
    _acb_vec_clear(xs, m + 1);
    _fmpz_vec_clear(d, m * m);
    _fmpz_vec_clear(s, m + 1);
    fmpz_clear(c);
    fmpz_clear(h);
}