Beispiel #1
0
void
_acb_poly_sin_cos_pi_series(acb_ptr s, acb_ptr c, const acb_srcptr h, slong hlen, slong n, slong prec)
{
    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        acb_sin_cos_pi(s, c, h, prec);
        _acb_vec_zero(s + 1, n - 1);
        _acb_vec_zero(c + 1, n - 1);
    }
    else if (n == 2)
    {
        acb_t t;
        acb_init(t);
        acb_const_pi(t, prec);
        acb_mul(t, t, h + 1, prec);
        acb_sin_cos_pi(s, c, h, prec);
        acb_mul(s + 1, c, t, prec);
        acb_neg(t, t);
        acb_mul(c + 1, s, t, prec);
        acb_clear(t);
    }
    else if (hlen < TANGENT_CUTOFF)
        _acb_poly_sin_cos_series_basecase(s, c, h, hlen, n, prec, 1);
    else
        _acb_poly_sin_cos_series_tangent(s, c, h, hlen, n, prec, 1);
}
Beispiel #2
0
void
acb_tan_pi(acb_t r, const acb_t z, slong prec)
{
    if (arb_is_zero(acb_imagref(z)))
    {
        arb_tan_pi(acb_realref(r), acb_realref(z), prec);
        arb_zero(acb_imagref(r));
    }
    else if (arb_is_zero(acb_realref(z)))
    {
        arb_t t;
        arb_init(t);
        arb_const_pi(t, prec + 4);
        arb_mul(t, acb_imagref(z), t, prec + 4);
        arb_tanh(acb_imagref(r), t, prec);
        arb_zero(acb_realref(r));
        arb_clear(t);
    }
    else
    {
        acb_t t;
        acb_init(t);

        if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0)
        {
            acb_sin_cos_pi(r, t, z, prec + 4);
            acb_div(r, r, t, prec);
        }
        else
        {
            acb_mul_2exp_si(t, z, 1);

            if (arf_sgn(arb_midref(acb_imagref(z))) > 0)
            {
                acb_exp_pi_i(t, t, prec + 4);
                acb_add_ui(r, t, 1, prec + 4);
                acb_div(r, t, r, prec + 4);
                acb_mul_2exp_si(r, r, 1);
                acb_sub_ui(r, r, 1, prec);
                acb_div_onei(r, r);
            }
            else
            {
                acb_neg(t, t);
                acb_exp_pi_i(t, t, prec + 4);
                acb_add_ui(r, t, 1, prec + 4);
                acb_div(r, t, r, prec + 4);
                acb_mul_2exp_si(r, r, 1);
                acb_sub_ui(r, r, 1, prec);
                acb_mul_onei(r, r);
            }
        }

        acb_clear(t);
    }
}
Beispiel #3
0
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_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);
}
Beispiel #5
0
void
acb_hypgeom_legendre_q(acb_t res, const acb_t n, const acb_t m,
    const acb_t z, int type, slong prec)
{
    if (type == 0)
    {
        /* http://functions.wolfram.com/07.11.26.0033.01 */
        /* todo: simplify the gamma quotients and the sqrt pi factor... */
        acb_t a, b, c, z2, mn, nm, t, u;

        acb_init(a);
        acb_init(b);
        acb_init(c);
        acb_init(z2);
        acb_init(mn);
        acb_init(nm);
        acb_init(t);
        acb_init(u);

        acb_add(mn, m, n, prec); /* mn = m + n */
        acb_sub(nm, n, m, prec); /* nm = n - m */
        acb_mul(z2, z, z, prec); /* z2 = z^2 */

        /* t = 2F1((1-m-n)/2, (n-m)/2+1, 3/2, z^2) */
        acb_sub_ui(a, mn, 1, prec);
        acb_neg(a, a);
        acb_mul_2exp_si(a, a, -1);
        acb_mul_2exp_si(b, nm, -1);
        acb_add_ui(b, b, 1, prec);
        acb_set_ui(c, 3);
        acb_mul_2exp_si(c, c, -1);
        acb_hypgeom_2f1(t, a, b, c, z2, 0, prec);

        /* u = 2F1(-(m+n)/2, (n-m+1)/2, 1/2, z^2) */
        acb_neg(a, mn);
        acb_mul_2exp_si(a, a, -1);
        acb_add_ui(b, nm, 1, prec);
        acb_mul_2exp_si(b, b, -1);
        acb_one(c);
        acb_mul_2exp_si(c, c, -1);
        acb_hypgeom_2f1(u, a, b, c, z2, 0, prec);

        /* a = cospi((m+n)/2) gamma((m+n)/2+1) rgamma((n-m+1)/2) z */
        /* b = sinpi((m+n)/2) gamma((m+n+1)/2) rgamma((n-m)/2+1) / 2 */
        acb_mul_2exp_si(a, mn, -1);
        acb_sin_cos_pi(b, a, a, prec);

        acb_mul_2exp_si(c, mn, -1);
        acb_add_ui(c, c, 1, prec);
        acb_gamma(c, c, prec);
        acb_mul(a, a, c, prec);
        acb_add_ui(c, nm, 1, prec);
        acb_mul_2exp_si(c, c, -1);
        acb_rgamma(c, c, prec);
        acb_mul(a, a, c, prec);
        acb_mul(a, a, z, prec);

        acb_add_ui(c, mn, 1, prec);
        acb_mul_2exp_si(c, c, -1);
        acb_gamma(c, c, prec);
        acb_mul(b, b, c, prec);
        acb_mul_2exp_si(c, nm, -1);
        acb_add_ui(c, c, 1, prec);
        acb_rgamma(c, c, prec);
        acb_mul(b, b, c, prec);
        acb_mul_2exp_si(b, b, -1);

        /* at - bu */
        acb_mul(t, t, a, prec);
        acb_mul(u, u, b, prec);
        acb_sub(t, t, u, prec);

        /* prefactor sqrt(pi) 2^m (1-z^2)^(-m/2) */
        if (!acb_is_zero(m))
        {
            acb_sub_ui(u, z2, 1, prec);
            acb_neg(u, u);
            acb_neg(c, m);
            acb_mul_2exp_si(c, c, -1);
            acb_pow(u, u, c, prec);
            acb_set_ui(c, 2);
            acb_pow(c, c, m, prec);
            acb_mul(u, u, c, prec);
            acb_mul(t, t, u, prec);
        }

        arb_const_sqrt_pi(acb_realref(u), prec);
        acb_mul_arb(t, t, acb_realref(u), prec);

        acb_set(res, t);

        acb_clear(a);
        acb_clear(b);
        acb_clear(c);
        acb_clear(z2);
        acb_clear(mn);
        acb_clear(nm);
        acb_clear(t);
        acb_clear(u);
    }
    else if (type == 1)
    {
        if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -2) < 0 &&
             arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -2) < 0) ||
            !_acb_hypgeom_legendre_q_single_valid(z))
        {
            _acb_hypgeom_legendre_q_double(res, n, m, z, prec);
        }
        else
        {
            _acb_hypgeom_legendre_q_single(res, n, m, z, prec);
        }
    }
    else
    {
        flint_printf("unsupported 'type' %d for legendre q\n", type);
        abort();
    }
}