예제 #1
0
void
_acb_hypgeom_coulomb_series(acb_ptr F, acb_ptr G,
    acb_ptr Hpos, acb_ptr Hneg, const acb_t l, const acb_t eta,
    acb_srcptr z, slong zlen, slong len, slong prec)
{
    acb_ptr t, v;

    if (len == 0)
        return;

    zlen = FLINT_MIN(zlen, len);

    if (zlen == 1)
    {
        acb_hypgeom_coulomb(F, G, Hpos, Hneg, l, eta, z, prec);
        if (F != NULL) _acb_vec_zero(F + 1, len - 1);
        if (G != NULL) _acb_vec_zero(G + 1, len - 1);
        if (Hpos != NULL) _acb_vec_zero(Hpos + 1, len - 1);
        if (Hneg != NULL) _acb_vec_zero(Hneg + 1, len - 1);
        return;
    }

    t = _acb_vec_init(len);
    v = _acb_vec_init(zlen);

    /* copy nonconstant part first to allow aliasing */
    acb_zero(v);
    _acb_vec_set(v + 1, z + 1, zlen - 1);

    acb_hypgeom_coulomb_jet(F, G, Hpos, Hneg, l, eta, z, len, prec);

    if (F != NULL)
    {
        _acb_vec_set(t, F, len);
        _acb_poly_compose_series(F, t, len, v, zlen, len, prec);
    }

    if (G != NULL)
    {
        _acb_vec_set(t, G, len);
        _acb_poly_compose_series(G, t, len, v, zlen, len, prec);
    }

    if (Hpos != NULL)
    {
        _acb_vec_set(t, Hpos, len);
        _acb_poly_compose_series(Hpos, t, len, v, zlen, len, prec);
    }

    if (Hneg != NULL)
    {
        _acb_vec_set(t, Hneg, len);
        _acb_poly_compose_series(Hneg, t, len, v, zlen, len, prec);
    }

    _acb_vec_clear(t, len);
    _acb_vec_clear(v, zlen);
}
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);
}
예제 #3
0
void
acb_poly_add_si(acb_poly_t res, const acb_poly_t x, long y, long prec)
{
    long len = x->length;

    if (len == 0)
    {
        acb_poly_set_si(res, y);
    }
    else
    {
        acb_poly_fit_length(res, len);

        if (y >= 0)
            acb_add_ui(res->coeffs, x->coeffs, y, prec);
        else
            acb_sub_ui(res->coeffs, x->coeffs, -y, prec);

        if (res != x)
            _acb_vec_set(res->coeffs + 1, x->coeffs + 1, len - 1);

        _acb_poly_set_length(res, len);
        _acb_poly_normalise(res);
    }
}
예제 #4
0
void
_acb_dirichlet_hardy_z_series(acb_ptr res, acb_srcptr s, slong slen,
    const dirichlet_group_t G, const dirichlet_char_t chi,
    slong len, slong prec)
{
    slen = FLINT_MIN(slen, len);

    if (len == 0)
        return;

    if (slen == 1)
    {
        acb_dirichlet_hardy_z(res, s, G, chi, 1, prec);
        _acb_vec_zero(res + 1, len - 1);
    }
    else
    {
        acb_ptr t, u;
        t = _acb_vec_init(len);
        u = _acb_vec_init(slen);

        acb_dirichlet_hardy_z(t, s, G, chi, len, prec);

        /* compose with nonconstant part */
        acb_zero(u);
        _acb_vec_set(u + 1, s + 1, slen - 1);
        _acb_poly_compose_series(res, t, len, u, slen, len, prec);

        _acb_vec_clear(t, len);
        _acb_vec_clear(u, slen);
    }
}
예제 #5
0
void
_acb_poly_revert_series_lagrange_fast(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong n, slong prec)
{
    slong i, j, k, m;
    acb_ptr R, S, T, tmp;
    acb_t t;

    if (n <= 2)
    {
        if (n >= 1)
            acb_zero(Qinv);
        if (n == 2)
            acb_inv(Qinv + 1, Q + 1, prec);
        return;
    }

    m = n_sqrt(n);

    acb_init(t);
    R = _acb_vec_init((n - 1) * m);
    S = _acb_vec_init(n - 1);
    T = _acb_vec_init(n - 1);

    acb_zero(Qinv);
    acb_inv(Qinv + 1, Q + 1, prec);

    _acb_poly_inv_series(Ri(1), Q + 1, FLINT_MIN(Qlen, n) - 1, n - 1, prec);
    for (i = 2; i <= m; i++)
        _acb_poly_mullow(Ri(i), Ri((i + 1) / 2), n - 1, Ri(i / 2), n - 1, n - 1, prec);

    for (i = 2; i < m; i++)
        acb_div_ui(Qinv + i, Ri(i) + i - 1, i, prec);

    _acb_vec_set(S, Ri(m), n - 1);

    for (i = m; i < n; i += m)
    {
        acb_div_ui(Qinv + i, S + i - 1, i, prec);

        for (j = 1; j < m && i + j < n; j++)
        {
            acb_mul(t, S + 0, Ri(j) + i + j - 1, prec);
            for (k = 1; k <= i + j - 1; k++)
                acb_addmul(t, S + k, Ri(j) + i + j - 1 - k, prec);
            acb_div_ui(Qinv + i + j, t, i + j, prec);
        }

        if (i + 1 < n)
        {
            _acb_poly_mullow(T, S, n - 1, Ri(m), n - 1, n - 1, prec);
            tmp = S; S = T; T = tmp;
        }
    }

    acb_clear(t);
    _acb_vec_clear(R, (n - 1) * m);
    _acb_vec_clear(S, n - 1);
    _acb_vec_clear(T, n - 1);
}
예제 #6
0
void
_acb_poly_zeta_series(acb_ptr res, acb_srcptr h, slong hlen, const acb_t a, int deflate, slong len, slong prec)
{
    acb_ptr t, u;
    hlen = FLINT_MIN(hlen, len);

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);

    _acb_poly_zeta_cpx_reflect(t, h, a, deflate, len, prec);

    /* compose with nonconstant part */
    acb_zero(u);
    _acb_vec_set(u + 1, h + 1, hlen - 1);
    _acb_poly_compose_series(res, t, len, u, hlen, len, prec);

    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
}
예제 #7
0
int
acb_mat_eig_multiple(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec)
{
    slong n;
    acb_ptr F;
    int success;

    n = arb_mat_nrows(A);
    F = _acb_vec_init(n);

    success = acb_mat_eig_simple_vdhoeven_mourrain(F, NULL, NULL, A, E_approx, R_approx, prec);

    if (!success)
        success = acb_mat_eig_multiple_rump(F, A, E_approx, R_approx, prec);

    _acb_vec_set(E, F, n);
    _acb_vec_clear(F, n);

    return success;
}
예제 #8
0
void
_acb_poly_agm1_series(acb_ptr res, acb_srcptr z, long zlen, long len, long prec)
{
    acb_ptr t, u;

    zlen = FLINT_MIN(zlen, len);

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);

    acb_agm1_cpx(t, z, len, prec);

    /* compose with nonconstant part */
    acb_zero(u);
    _acb_vec_set(u + 1, z + 1, zlen - 1);
    _acb_poly_compose_series(res, t, len, u, zlen, len, prec);

    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
}
예제 #9
0
void
_acb_poly_powsum_one_series_sieved(acb_ptr z, const acb_t s, slong n, slong len, slong prec)
{
    slong * divisors;
    slong powers_alloc;
    slong i, j, k, ibound, kprev, power_of_two, horner_point;
    int critical_line, integer;

    acb_ptr powers;
    acb_ptr t, u, x;
    acb_ptr p1, p2;
    arb_t logk, v, w;

    critical_line = arb_is_exact(acb_realref(s)) &&
        (arf_cmp_2exp_si(arb_midref(acb_realref(s)), -1) == 0);

    integer = arb_is_zero(acb_imagref(s)) && arb_is_int(acb_realref(s));

    divisors = flint_calloc(n / 2 + 1, sizeof(slong));
    powers_alloc = (n / 6 + 1) * len;
    powers = _acb_vec_init(powers_alloc);

    ibound = n_sqrt(n);
    for (i = 3; i <= ibound; i += 2)
        if (DIVISOR(i) == 0)
            for (j = i * i; j <= n; j += 2 * i)
                DIVISOR(j) = i;

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);
    x = _acb_vec_init(len);
    arb_init(logk);
    arb_init(v);
    arb_init(w);

    power_of_two = 1;
    while (power_of_two * 2 <= n)
        power_of_two *= 2;
    horner_point = n / power_of_two;

    _acb_vec_zero(z, len);

    kprev = 0;
    COMPUTE_POWER(x, 2, kprev);

    for (k = 1; k <= n; k += 2)
    {
        /* t = k^(-s) */
        if (DIVISOR(k) == 0)
        {
            COMPUTE_POWER(t, k, kprev);
        }
        else
        {
            p1 = POWER(DIVISOR(k));
            p2 = POWER(k / DIVISOR(k));

            if (len == 1)
                acb_mul(t, p1, p2, prec);
            else
                _acb_poly_mullow(t, p1, len, p2, len, len, prec);
        }

        if (k * 3 <= n)
            _acb_vec_set(POWER(k), t, len);

        _acb_vec_add(u, u, t, len, prec);

        while (k == horner_point && power_of_two != 1)
        {
            _acb_poly_mullow(t, z, len, x, len, len, prec);
            _acb_vec_add(z, t, u, len, prec);

            power_of_two /= 2;
            horner_point = n / power_of_two;
            horner_point -= (horner_point % 2 == 0);
        }
    }

    _acb_poly_mullow(t, z, len, x, len, len, prec);
    _acb_vec_add(z, t, u, len, prec);

    flint_free(divisors);
    _acb_vec_clear(powers, powers_alloc);
    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
    _acb_vec_clear(x, len);
    arb_clear(logk);
    arb_clear(v);
    arb_clear(w);
}
예제 #10
0
파일: rgamma_series.c 프로젝트: isuruf/arb
void
_acb_poly_rgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec)
{
    int reflect;
    slong i, rflen, r, n, wp;
    acb_ptr t, u, v;
    acb_struct f[2];

    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        acb_rgamma(res, h, prec);
        _acb_vec_zero(res + 1, len - 1);
        return;
    }

    /* use real code for real input */
    if (_acb_vec_is_real(h, hlen))
    {
        arb_ptr tmp = _arb_vec_init(len);
        for (i = 0; i < hlen; i++)
            arb_set(tmp + i, acb_realref(h + i));
        _arb_poly_rgamma_series(tmp, tmp, hlen, len, prec);
        for (i = 0; i < len; i++)
            acb_set_arb(res + i, tmp + i);
        _arb_vec_clear(tmp, len);
        return;
    }

    wp = prec + FLINT_BIT_COUNT(prec);

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);
    v = _acb_vec_init(len);
    acb_init(f);
    acb_init(f + 1);

    /* otherwise use Stirling series */
    acb_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp);

    /* rgamma(h) = (gamma(1-h+r) sin(pi h)) / (rf(1-h, r) * pi), h = h0 + t*/
    if (reflect)
    {
        /* u = gamma(r+1-h) */
        acb_sub_ui(f, h, r + 1, wp);
        acb_neg(f, f);
        _acb_poly_gamma_stirling_eval(t, f, n, len, wp);
        _acb_poly_exp_series(u, t, len, len, wp);
        for (i = 1; i < len; i += 2)
            acb_neg(u + i, u + i);

        /* v = sin(pi x) */
        acb_set(f, h);
        acb_one(f + 1);
        _acb_poly_sin_pi_series(v, f, 2, len, wp);

        _acb_poly_mullow(t, u, len, v, len, len, wp);

        /* rf(1-h,r) * pi */
        if (r == 0)
        {
            acb_const_pi(u, wp);
            _acb_vec_scalar_div(v, t, len, u, wp);
        }
        else
        {
            acb_sub_ui(f, h, 1, wp);
            acb_neg(f, f);
            acb_set_si(f + 1, -1);
            rflen = FLINT_MIN(len, r + 1);
            _acb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r, rflen, wp);
            acb_const_pi(u, wp);
            _acb_vec_scalar_mul(v, v, rflen, u, wp);

            /* divide by rising factorial */
            /* TODO: might better to use div_series, when it has a good basecase */
            _acb_poly_inv_series(u, v, rflen, len, wp);
            _acb_poly_mullow(v, t, len, u, len, len, wp);
        }
    }
    else
    {
        /* rgamma(h) = rgamma(h+r) rf(h,r) */
        if (r == 0)
        {
            acb_add_ui(f, h, r, wp);
            _acb_poly_gamma_stirling_eval(t, f, n, len, wp);
            _acb_vec_neg(t, t, len);
            _acb_poly_exp_series(v, t, len, len, wp);
        }
        else
        {
            acb_set(f, h);
            acb_one(f + 1);
            rflen = FLINT_MIN(len, r + 1);
            _acb_poly_rising_ui_series(t, f, FLINT_MIN(2, len), r, rflen, wp);

            acb_add_ui(f, h, r, wp);
            _acb_poly_gamma_stirling_eval(v, f, n, len, wp);
            _acb_vec_neg(v, v, len);
            _acb_poly_exp_series(u, v, len, len, wp);

            _acb_poly_mullow(v, u, len, t, rflen, len, wp);
        }
    }

    /* compose with nonconstant part */
    acb_zero(t);
    _acb_vec_set(t + 1, h + 1, hlen - 1);
    _acb_poly_compose_series(res, v, len, t, hlen, len, prec);

    acb_clear(f);
    acb_clear(f + 1);
    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
    _acb_vec_clear(v, len);
}
예제 #11
0
void
acb_dirichlet_hurwitz_precomp_init(acb_dirichlet_hurwitz_precomp_t pre,
        const acb_t s, int deflate, slong A, slong K, slong N, slong prec)
{
    slong i, k;

    if (A < 1 || K < 1 || N < 1)
        abort();

    pre->deflate = deflate;
    pre->A = A;
    pre->K = K;
    pre->N = N;
    pre->coeffs = _acb_vec_init(N * K);

    mag_init(&pre->err);
    acb_init(&pre->s);
    acb_set(&pre->s, s);

    acb_dirichlet_hurwitz_precomp_bound(&pre->err, s, A, K, N);

    if (mag_is_finite(&pre->err))
    {
        acb_t t, a;

        acb_init(t);
        acb_init(a);

        /* (-1)^k (s)_k / k! */
        acb_one(pre->coeffs + 0);
        for (k = 1; k < K; k++)
        {
            acb_add_ui(pre->coeffs + k, s, k - 1, prec);
            acb_mul(pre->coeffs + k, pre->coeffs + k, pre->coeffs + k - 1, prec);
            acb_div_ui(pre->coeffs + k, pre->coeffs + k, k, prec);
            acb_neg(pre->coeffs + k, pre->coeffs + k);
        }

        for (i = 1; i < N; i++)
            _acb_vec_set(pre->coeffs + i * K, pre->coeffs, K);

        /* zeta(s+k,a) where a = A + (2*i+1)/(2*N) */
        for (i = 0; i < N; i++)
        {
            acb_set_ui(a, 2 * i + 1);
            acb_div_ui(a, a, 2 * N, prec);
            acb_add_ui(a, a, A, prec);

            for (k = 0; k < K; k++)
            {
                acb_add_ui(t, s, k, prec);

                if (deflate && k == 0)
                    _acb_poly_zeta_cpx_series(t, t, a, 1, 1, prec);
                else
                    acb_hurwitz_zeta(t, t, a, prec);

                acb_mul(pre->coeffs + i * K + k,
                        pre->coeffs + i * K + k, t, prec);
            }
        }

        acb_clear(t);
        acb_clear(a);
    }
}
예제 #12
0
void
_acb_poly_zeta_series(acb_ptr res, acb_srcptr h, long hlen, const acb_t a, int deflate, long len, long prec)
{
    long i;
    acb_ptr t, u;

    hlen = FLINT_MIN(hlen, len);

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);

    /* use reflection formula */
    if (arf_sgn(arb_midref(acb_realref(h))) < 0 && acb_is_one(a))
    {
        /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */
        acb_t pi;
        acb_ptr f, s1, s2, s3, s4;

        acb_init(pi);
        f = _acb_vec_init(2);
        s1 = _acb_vec_init(len);
        s2 = _acb_vec_init(len);
        s3 = _acb_vec_init(len);
        s4 = _acb_vec_init(len);

        acb_const_pi(pi, prec);

        /* s1 = (2*pi)**s */
        acb_mul_2exp_si(pi, pi, 1);
        _acb_poly_pow_cpx(s1, pi, h, len, prec);
        acb_mul_2exp_si(pi, pi, -1);

        /* s2 = sin(pi*s/2) / pi */
        acb_set(f, h);
        acb_one(f + 1);
        acb_mul_2exp_si(f, f, -1);
        acb_mul_2exp_si(f + 1, f + 1, -1);
        _acb_poly_sin_pi_series(s2, f, 2, len, prec);
        _acb_vec_scalar_div(s2, s2, len, pi, prec);

        /* s3 = gamma(1-s) */
        acb_sub_ui(f, h, 1, prec);
        acb_neg(f, f);
        acb_set_si(f + 1, -1);
        _acb_poly_gamma_series(s3, f, 2, len, prec);

        /* s4 = zeta(1-s) */
        acb_sub_ui(f, h, 1, prec);
        acb_neg(f, f);
        _acb_poly_zeta_cpx_series(s4, f, a, 0, len, prec);
        for (i = 1; i < len; i += 2)
            acb_neg(s4 + i, s4 + i);

        _acb_poly_mullow(u, s1, len, s2, len, len, prec);
        _acb_poly_mullow(s1, s3, len, s4, len, len, prec);
        _acb_poly_mullow(t, u, len, s1, len, len, prec);

        /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */
        if (deflate)
        {
            acb_sub_ui(u, h, 1, prec);
            acb_neg(u, u);
            acb_inv(u, u, prec);
            for (i = 1; i < len; i++)
                acb_mul(u + i, u + i - 1, u, prec);
            _acb_vec_add(t, t, u, len, prec);
        }

        acb_clear(pi);
        _acb_vec_clear(f, 2);
        _acb_vec_clear(s1, len);
        _acb_vec_clear(s2, len);
        _acb_vec_clear(s3, len);
        _acb_vec_clear(s4, len);
    }
    else
    {
        _acb_poly_zeta_cpx_series(t, h, a, deflate, len, prec);
    }

    /* compose with nonconstant part */
    acb_zero(u);
    _acb_vec_set(u + 1, h + 1, hlen - 1);
    _acb_poly_compose_series(res, t, len, u, hlen, len, prec);

    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
}
예제 #13
0
void
_acb_poly_lgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec)
{
    int reflect;
    slong i, r, n, wp;
    acb_t zr;
    acb_ptr t, u;

    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        acb_lgamma(res, h, prec);
        if (acb_is_finite(res))
            _acb_vec_zero(res + 1, len - 1);
        else
            _acb_vec_indeterminate(res + 1, len - 1);
        return;
    }

    if (len == 2)
    {
        acb_t v;
        acb_init(v);
        acb_set(v, h + 1);
        acb_digamma(res + 1, h, prec);
        acb_lgamma(res, h, prec);
        acb_mul(res + 1, res + 1, v, prec);
        acb_clear(v);
        return;
    }

    /* use real code for real input and output */
    if (_acb_vec_is_real(h, hlen) && arb_is_positive(acb_realref(h)))
    {
        arb_ptr tmp = _arb_vec_init(len);
        for (i = 0; i < hlen; i++)
            arb_set(tmp + i, acb_realref(h + i));
        _arb_poly_lgamma_series(tmp, tmp, hlen, len, prec);
        for (i = 0; i < len; i++)
            acb_set_arb(res + i, tmp + i);
        _arb_vec_clear(tmp, len);
        return;
    }

    wp = prec + FLINT_BIT_COUNT(prec);

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);
    acb_init(zr);

    /* use Stirling series */
    acb_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp);

    if (reflect)
    {
        /* log gamma(h+x) = log rf(1-(h+x), r) - log gamma(1-(h+x)+r) - log sin(pi (h+x)) + log(pi) */
        if (r != 0) /* otherwise t = 0 */
        {
            acb_sub_ui(u, h, 1, wp);
            acb_neg(u, u);
            _log_rising_ui_series(t, u, r, len, wp);
            for (i = 1; i < len; i += 2)
                acb_neg(t + i, t + i);
        }

        acb_sub_ui(u, h, 1, wp);
        acb_neg(u, u);
        acb_add_ui(zr, u, r, wp);
        _acb_poly_gamma_stirling_eval(u, zr, n, len, wp);
        for (i = 1; i < len; i += 2)
            acb_neg(u + i, u + i);

        _acb_vec_sub(t, t, u, len, wp);

        /* log(sin) is unstable with large imaginary parts;
           cot_pi is implemented in a numerically stable way */
        acb_set(u, h);
        acb_one(u + 1);
        _acb_poly_cot_pi_series(u, u, 2, len - 1, wp);
        _acb_poly_integral(u, u, len, wp);
        acb_const_pi(u, wp);
        _acb_vec_scalar_mul(u + 1, u + 1, len - 1, u, wp);
        acb_log_sin_pi(u, h, wp);

        _acb_vec_sub(u, t, u, len, wp);

        acb_const_pi(t, wp); /* todo: constant for log pi */
        acb_log(t, t, wp);
        acb_add(u, u, t, wp);
    }
    else
    {
        /* log gamma(x) = log gamma(x+r) - log rf(x,r) */

        acb_add_ui(zr, h, r, wp);
        _acb_poly_gamma_stirling_eval(u, zr, n, len, wp);

        if (r != 0)
        {
            _log_rising_ui_series(t, h, r, len, wp);
            _acb_vec_sub(u, u, t, len, wp);
        }
    }

    /* compose with nonconstant part */
    acb_zero(t);
    _acb_vec_set(t + 1, h + 1, hlen - 1);
    _acb_poly_compose_series(res, u, len, t, hlen, len, prec);

    acb_clear(zr);
    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
}
예제 #14
0
파일: digamma_series.c 프로젝트: isuruf/arb
void
_acb_poly_digamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec)
{
    int reflect;
    slong i, r, n, rflen, wp;
    acb_t zr;
    acb_ptr t, u, v;

    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        acb_digamma(res, h, prec);
        if (acb_is_finite(res))
            _acb_vec_zero(res + 1, len - 1);
        else
            _acb_vec_indeterminate(res + 1, len - 1);
        return;
    }

    /* use real code for real input */
    if (_acb_vec_is_real(h, hlen))
    {
        arb_ptr tmp = _arb_vec_init(len);
        for (i = 0; i < hlen; i++)
            arb_set(tmp + i, acb_realref(h + i));
        _arb_poly_digamma_series(tmp, tmp, hlen, len, prec);
        for (i = 0; i < len; i++)
            acb_set_arb(res + i, tmp + i);
        _arb_vec_clear(tmp, len);
        return;
    }

    wp = prec + FLINT_BIT_COUNT(prec);

    t = _acb_vec_init(len + 1);
    u = _acb_vec_init(len + 1);
    v = _acb_vec_init(len + 1);
    acb_init(zr);

    /* use Stirling series */
    acb_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 1, wp);

    /* psi(x) = psi((1-x)+r) - h(1-x,r) - pi*cot(pi*x) */
    if (reflect)
    {
        if (r != 0) /* otherwise t = 0 */
        {
            acb_sub_ui(v, h, 1, wp);
            acb_neg(v, v);
            acb_one(v + 1);
            rflen = FLINT_MIN(len + 1, r + 1);
            _acb_poly_rising_ui_series(u, v, 2, r, rflen, wp);
            _acb_poly_derivative(v, u, rflen, wp);
            _acb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp);
            for (i = 1; i < len; i += 2)
                acb_neg(t + i, t + i);
        }

        acb_sub_ui(zr, h, r + 1, wp);
        acb_neg(zr, zr);
        _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp);
        for (i = 1; i < len; i += 2)
            acb_neg(u + i, u + i);

        _acb_vec_sub(u, u, t, len, wp);

        acb_set(t, h);
        acb_one(t + 1);
        _acb_poly_cot_pi_series(t, t, 2, len, wp);
        acb_const_pi(v, wp);
        _acb_vec_scalar_mul(t, t, len, v, wp);

        _acb_vec_sub(u, u, t, len, wp);
    }
    else
    {
        if (r == 0)
        {
            acb_add_ui(zr, h, r, wp);
            _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp);
        }
        else
        {
            acb_set(v, h);
            acb_one(v + 1);
            rflen = FLINT_MIN(len + 1, r + 1);
            _acb_poly_rising_ui_series(u, v, 2, r, rflen, wp);
            _acb_poly_derivative(v, u, rflen, wp);
            _acb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp);

            acb_add_ui(zr, h, r, wp);
            _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp);

            _acb_vec_sub(u, u, t, len, wp);
        }
    }

    /* compose with nonconstant part */
    acb_zero(t);
    _acb_vec_set(t + 1, h + 1, hlen - 1);
    _acb_poly_compose_series(res, u, len, t, hlen, len, prec);

    acb_clear(zr);
    _acb_vec_clear(t, len + 1);
    _acb_vec_clear(u, len + 1);
    _acb_vec_clear(v, len + 1);
}
예제 #15
0
파일: find_roots.c 프로젝트: isuruf/arb
slong
_acb_poly_find_roots(acb_ptr roots,
    acb_srcptr poly,
    acb_srcptr initial, slong len, slong maxiter, slong prec)
{
    slong iter, i, deg;
    slong rootmag, max_rootmag, correction, max_correction;

    deg = len - 1;

    if (deg == 0)
    {
        return 0;
    }
    else if (acb_contains_zero(poly + len - 1))
    {
        /* if the leading coefficient contains zero, roots can be anywhere */
        for (i = 0; i < deg; i++)
        {
            arb_zero_pm_inf(acb_realref(roots + i));
            arb_zero_pm_inf(acb_imagref(roots + i));
        }
        return 0;
    }
    else if (deg == 1)
    {
        acb_inv(roots + 0, poly + 1, prec);
        acb_mul(roots + 0, roots + 0, poly + 0, prec);
        acb_neg(roots + 0, roots + 0);
        return 1;
    }

    if (initial == NULL)
        _acb_poly_roots_initial_values(roots, deg, prec);
    else
        _acb_vec_set(roots, initial, deg);

    if (maxiter == 0)
        maxiter = 2 * deg + n_sqrt(prec);

    for (iter = 0; iter < maxiter; iter++)
    {
        max_rootmag = -ARF_PREC_EXACT;
        for (i = 0; i < deg; i++)
        {
            rootmag = _acb_get_mid_mag(roots + i);
            max_rootmag = FLINT_MAX(rootmag, max_rootmag);
        }

        _acb_poly_refine_roots_durand_kerner(roots, poly, len, prec);

        max_correction = -ARF_PREC_EXACT;
        for (i = 0; i < deg; i++)
        {
            correction = _acb_get_rad_mag(roots + i);
            max_correction = FLINT_MAX(correction, max_correction);
        }

        /* estimate the correction relative to the whole set of roots */
        max_correction -= max_rootmag;

        /* flint_printf("ITER %wd MAX CORRECTION: %wd\n", iter, max_correction); */

        if (max_correction < -prec / 2)
            maxiter = FLINT_MIN(maxiter, iter + 2);
        else if (max_correction < -prec / 3)
            maxiter = FLINT_MIN(maxiter, iter + 3);
        else if (max_correction < -prec / 4)
            maxiter = FLINT_MIN(maxiter, iter + 4);
    }

    return _acb_poly_validate_roots(roots, poly, len, prec);
}
예제 #16
0
void
fmpz_poly_complex_roots_squarefree(const fmpz_poly_t poly,
                                   slong initial_prec,
                                   slong target_prec,
                                   slong print_digits)
{
    slong i, j, prec, deg, deg_deflated, isolated, maxiter, deflation;
    acb_poly_t cpoly, cpoly_deflated;
    fmpz_poly_t poly_deflated;
    acb_ptr roots, roots_deflated;
    int removed_zero;

    if (fmpz_poly_degree(poly) < 1)
        return;

    fmpz_poly_init(poly_deflated);
    acb_poly_init(cpoly);
    acb_poly_init(cpoly_deflated);

    /* try to write poly as poly_deflated(x^deflation), possibly multiplied by x */
    removed_zero = fmpz_is_zero(poly->coeffs);
    if (removed_zero)
        fmpz_poly_shift_right(poly_deflated, poly, 1);
    else
        fmpz_poly_set(poly_deflated, poly);
    deflation = fmpz_poly_deflation(poly_deflated);
    fmpz_poly_deflate(poly_deflated, poly_deflated, deflation);

    deg = fmpz_poly_degree(poly);
    deg_deflated = fmpz_poly_degree(poly_deflated);

    flint_printf("searching for %wd roots, %wd deflated\n", deg, deg_deflated);

    roots = _acb_vec_init(deg);
    roots_deflated = _acb_vec_init(deg_deflated);

    for (prec = initial_prec; ; prec *= 2)
    {
        acb_poly_set_fmpz_poly(cpoly_deflated, poly_deflated, prec);
        maxiter = FLINT_MIN(FLINT_MAX(deg_deflated, 32), prec);

        TIMEIT_ONCE_START
        flint_printf("prec=%wd: ", prec);
        isolated = acb_poly_find_roots(roots_deflated, cpoly_deflated,
                                       prec == initial_prec ? NULL : roots_deflated, maxiter, prec);
        flint_printf("%wd isolated roots | ", isolated);
        TIMEIT_ONCE_STOP

        if (isolated == deg_deflated)
        {
            if (!check_accuracy(roots_deflated, deg_deflated, target_prec))
                continue;

            if (deflation == 1)
            {
                _acb_vec_set(roots, roots_deflated, deg_deflated);
            }
            else  /* compute all nth roots */
            {
                acb_t w, w2;

                acb_init(w);
                acb_init(w2);

                acb_unit_root(w, deflation, prec);
                acb_unit_root(w2, 2 * deflation, prec);

                for (i = 0; i < deg_deflated; i++)
                {
                    if (arf_sgn(arb_midref(acb_realref(roots_deflated + i))) > 0)
                    {
                        acb_root_ui(roots + i * deflation,
                                    roots_deflated + i, deflation, prec);
                    }
                    else
                    {
                        acb_neg(roots + i * deflation, roots_deflated + i);
                        acb_root_ui(roots + i * deflation,
                                    roots + i * deflation, deflation, prec);
                        acb_mul(roots + i * deflation,
                                roots + i * deflation, w2, prec);
                    }

                    for (j = 1; j < deflation; j++)
                    {
                        acb_mul(roots + i * deflation + j,
                                roots + i * deflation + j - 1, w, prec);
                    }
                }

                acb_clear(w);
                acb_clear(w2);
            }

            /* by assumption that poly is squarefree, must be just one */
            if (removed_zero)
                acb_zero(roots + deg_deflated * deflation);

            if (!check_accuracy(roots, deg, target_prec))
                continue;

            acb_poly_set_fmpz_poly(cpoly, poly, prec);

            if (!acb_poly_validate_real_roots(roots, cpoly, prec))
                continue;

            for (i = 0; i < deg; i++)
            {
                if (arb_contains_zero(acb_imagref(roots + i)))
                    arb_zero(acb_imagref(roots + i));
            }

            flint_printf("done!\n");
            break;
        }
    }

    if (print_digits != 0)
    {
        _acb_vec_sort_pretty(roots, deg);

        for (i = 0; i < deg; i++)
        {
            acb_printn(roots + i, print_digits, 0);
            flint_printf("\n");
        }
    }

    fmpz_poly_clear(poly_deflated);
    acb_poly_clear(cpoly);
    acb_poly_clear(cpoly_deflated);
    _acb_vec_clear(roots, deg);
    _acb_vec_clear(roots_deflated, deg_deflated);
}