コード例 #1
0
ファイル: integrals2.c プロジェクト: bluescarni/arb
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;
}
コード例 #2
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);
}
コード例 #3
0
void
_acb_poly_sin_cos_series_tangent(acb_ptr s, acb_ptr c,
        const acb_srcptr h, slong hlen, slong len, slong prec, int times_pi)
{
    acb_ptr t, u, v;
    acb_t s0, c0;
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        if (times_pi)
            acb_sin_cos_pi(s, c, h, prec);
        else
            acb_sin_cos(s, c, h, prec);
        _acb_vec_zero(s + 1, len - 1);
        _acb_vec_zero(c + 1, len - 1);
        return;
    }

    /*
    sin(x) = 2*tan(x/2)/(1+tan(x/2)^2)
    cos(x) = (1-tan(x/2)^2)/(1+tan(x/2)^2)
    */

    acb_init(s0);
    acb_init(c0);

    t = _acb_vec_init(3 * len);
    u = t + len;
    v = u + len;

    /* sin, cos of h0 */
    if (times_pi)
        acb_sin_cos_pi(s0, c0, h, prec);
    else
        acb_sin_cos(s0, c0, h, prec);

    /* t = tan((h-h0)/2) */
    acb_zero(u);
    _acb_vec_scalar_mul_2exp_si(u + 1, h + 1, hlen - 1, -1);
    if (times_pi)
    {
        acb_const_pi(t, prec);
        _acb_vec_scalar_mul(u + 1, u + 1, hlen - 1, t, prec);
    }

    _acb_poly_tan_series(t, u, hlen, len, prec);

    /* v = 1 + t^2 */
    _acb_poly_mullow(v, t, len, t, len, len, prec);
    acb_add_ui(v, v, 1, prec);

    /* u = 1/(1+t^2) */
    _acb_poly_inv_series(u, v, len, len, prec);

    /* sine */
    _acb_poly_mullow(s, t, len, u, len, len, prec);
    _acb_vec_scalar_mul_2exp_si(s, s, len, 1);

    /* cosine */
    acb_sub_ui(v, v, 2, prec);
    _acb_vec_neg(v, v, len);
    _acb_poly_mullow(c, v, len, u, len, len, prec);

    /* sin(h0 + h1) = cos(h0) sin(h1) + sin(h0) cos(h1)
       cos(h0 + h1) = cos(h0) cos(h1) - sin(h0) sin(h1) */
    if (!acb_is_zero(s0))
    {
        _acb_vec_scalar_mul(t, s, len, c0, prec);
        _acb_vec_scalar_mul(u, c, len, s0, prec);
        _acb_vec_scalar_mul(v, s, len, s0, prec);
        _acb_vec_add(s, t, u, len, prec);
        _acb_vec_scalar_mul(t, c, len, c0, prec);
        _acb_vec_sub(c, t, v, len, prec);
    }

    _acb_vec_clear(t, 3 * len);

    acb_clear(s0);
    acb_clear(c0);
}
コード例 #4
0
ファイル: inv_series.c プロジェクト: fredrik-johansson/arb
void
_acb_poly_inv_series(acb_ptr Qinv,
    acb_srcptr Q, slong Qlen, slong len, slong prec)
{
    Qlen = FLINT_MIN(Qlen, len);

    acb_inv(Qinv, Q, prec);

    if (Qlen == 1)
    {
        _acb_vec_zero(Qinv + 1, len - 1);
    }
    else if (len == 2)
    {
        acb_mul(Qinv + 1, Qinv, Qinv, prec);
        acb_mul(Qinv + 1, Qinv + 1, Q + 1, prec);
        acb_neg(Qinv + 1, Qinv + 1);
    }
    else
    {
        slong i, blen;

        /* The basecase algorithm is faster for much larger Qlen or len than
           this, but unfortunately also much less numerically stable. */
        if (Qlen == 2 || len <= 8)
            blen = len;
        else
            blen = FLINT_MIN(len, 4);

        for (i = 1; i < blen; i++)
        {
            acb_dot(Qinv + i, NULL, 1,
                Q + 1, 1, Qinv + i - 1, -1, FLINT_MIN(i, Qlen - 1), prec);
            if (!acb_is_one(Qinv))
                acb_mul(Qinv + i, Qinv + i, Qinv, prec);
        }

        if (len > blen)
        {
            slong Qnlen, Wlen, W2len;
            acb_ptr W;

            W = _acb_vec_init(len);

            NEWTON_INIT(blen, len)
            NEWTON_LOOP(m, n)

            Qnlen = FLINT_MIN(Qlen, n);
            Wlen = FLINT_MIN(Qnlen + m - 1, n);
            W2len = Wlen - m;
            MULLOW(W, Q, Qnlen, Qinv, m, Wlen, prec);
            MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m, prec);
            _acb_vec_neg(Qinv + m, Qinv + m, n - m);

            NEWTON_END_LOOP
            NEWTON_END

            _acb_vec_clear(W, len);
        }
    }
}