Пример #1
0
Файл: mul.c Проект: isuruf/arb
void
acb_mul(acb_t z, const acb_t x, const acb_t y, slong prec)
{
    if (arb_is_zero(b))
    {
        arb_mul(f, d, a, prec);
        arb_mul(e, c, a, prec);
    }
    else if (arb_is_zero(d))
    {
        arb_mul(f, b, c, prec);
        arb_mul(e, a, c, prec);
    }
    else if (arb_is_zero(a))
    {
        arb_mul(e, c, b, prec);
        arb_mul(f, d, b, prec);
        acb_mul_onei(z, z);
    }
    else if (arb_is_zero(c))
    {
        arb_mul(e, a, d, prec);
        arb_mul(f, b, d, prec);
        acb_mul_onei(z, z);
    }
    /* squaring = a^2-b^2, 2ab */
    else if (x == y)
    {
        if (ARB_IS_LAGOM(a) && ARB_IS_LAGOM(b))
            _acb_sqr_fast(z, x, prec);
        else
            _acb_sqr_slow(z, x, prec);
    }
    else
    {
        if (ARB_IS_LAGOM(a) && ARB_IS_LAGOM(b) &&
            ARB_IS_LAGOM(c) && ARB_IS_LAGOM(d))
            _acb_mul_fast(z, x, y, prec);
        else
            _acb_mul_slow(z, x, y, prec);
    }
}
Пример #2
0
void
acb_pow(acb_t z, const acb_t x, const acb_t y, long prec)
{
    if (arb_is_zero(acb_imagref(y)))
    {
        acb_pow_arb(z, x, acb_realref(y), prec);
    }
    else
    {
        _acb_pow_exp(z, x, y, prec);
    }
}
Пример #3
0
void
arb_poly_compose_series(arb_poly_t res,
                    const arb_poly_t poly1,
                    const arb_poly_t poly2, slong n, slong prec)
{
    slong len1 = poly1->length;
    slong len2 = poly2->length;
    slong lenr;

    if (len2 != 0 && !arb_is_zero(poly2->coeffs))
    {
        flint_printf("exception: compose_series: inner "
                "polynomial must have zero constant term\n");
        abort();
    }

    if (len1 == 0 || n == 0)
    {
        arb_poly_zero(res);
        return;
    }

    if (len2 == 0 || len1 == 1)
    {
        arb_poly_set_arb(res, poly1->coeffs);
        return;
    }

    lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n);
    len1 = FLINT_MIN(len1, lenr);
    len2 = FLINT_MIN(len2, lenr);

    if ((res != poly1) && (res != poly2))
    {
        arb_poly_fit_length(res, lenr);
        _arb_poly_compose_series(res->coeffs, poly1->coeffs, len1,
                                        poly2->coeffs, len2, lenr, prec);
        _arb_poly_set_length(res, lenr);
        _arb_poly_normalise(res);
    }
    else
    {
        arb_poly_t t;
        arb_poly_init2(t, lenr);
        _arb_poly_compose_series(t->coeffs, poly1->coeffs, len1,
                                        poly2->coeffs, len2, lenr, prec);
        _arb_poly_set_length(t, lenr);
        _arb_poly_normalise(t);
        arb_poly_swap(res, t);
        arb_poly_clear(t);
    }
}
Пример #4
0
Файл: pow.c Проект: akobel/arb
void
arb_pow(arb_t z, const arb_t x, const arb_t y, long prec)
{
    if (arb_is_zero(y))
    {
        arb_one(z);
        return;
    }

    if (arb_is_exact(y) && !arf_is_special(arb_midref(x)))
    {
        const arf_struct * ymid = arb_midref(y);

        /* small half-integer or integer */
        if (arf_cmpabs_2exp_si(ymid, BINEXP_LIMIT) < 0 &&
            arf_is_int_2exp_si(ymid, -1))
        {
            fmpz_t e;
            fmpz_init(e);            

            if (arf_is_int(ymid))
            {
                arf_get_fmpz_fixed_si(e, ymid, 0);
                arb_pow_fmpz_binexp(z, x, e, prec);
            }
            else
            {
                arf_get_fmpz_fixed_si(e, ymid, -1);
                arb_sqrt(z, x, prec + fmpz_bits(e));
                arb_pow_fmpz_binexp(z, z, e, prec);
            }

            fmpz_clear(e);
            return;
        }
        else if (arf_is_int(ymid) && arf_sgn(arb_midref(x)) < 0)
        {
            /* use (-x)^n = (-1)^n * x^n to avoid NaNs
               at least at high enough precision */
            int odd = !arf_is_int_2exp_si(ymid, 1);
            _arb_pow_exp(z, x, 1, y, prec);
            if (odd)
                arb_neg(z, z);
            return;
        }
    }

    _arb_pow_exp(z, x, 0, y, prec);
}
Пример #5
0
int
arb_mat_is_triu(const arb_mat_t A)
{
    slong i, j, n, m;

    n = arb_mat_nrows(A);
    m = arb_mat_ncols(A);

    for (i = 1; i < n; i++)
        for (j = 0; j < FLINT_MIN(i, m); j++)
            if (!arb_is_zero(arb_mat_entry(A, i, j)))
                return 0;

    return 1;
}
Пример #6
0
void
acb_pow_arb(acb_t z, const acb_t x, const arb_t y, long prec)
{
    const arf_struct * ymid = arb_midref(y);
    const mag_struct * yrad = arb_radref(y);

    if (arb_is_zero(y))
    {
        acb_one(z);
        return;
    }

    if (mag_is_zero(yrad))
    {
        /* small half-integer or integer */
        if (arf_cmpabs_2exp_si(ymid, BINEXP_LIMIT) < 0 &&
            arf_is_int_2exp_si(ymid, -1))
        {
            fmpz_t e;
            fmpz_init(e);            

            if (arf_is_int(ymid))
            {
                arf_get_fmpz_fixed_si(e, ymid, 0);
                acb_pow_fmpz_binexp(z, x, e, prec);
            }
            else
            {
                /* hack: give something finite here (should fix sqrt/rsqrt etc) */
                if (arb_contains_zero(acb_imagref(x)) && arb_contains_nonpositive(acb_realref(x)))
                {
                    _acb_pow_arb_exp(z, x, y, prec);
                    fmpz_clear(e);
                    return;
                }

                arf_get_fmpz_fixed_si(e, ymid, -1);
                acb_sqrt(z, x, prec + fmpz_bits(e));
                acb_pow_fmpz_binexp(z, z, e, prec);
            }

            fmpz_clear(e);
            return;
        }
    }

    _acb_pow_arb_exp(z, x, y, prec);
}
Пример #7
0
void
_arb_poly_interpolate_newton(arb_ptr poly, arb_srcptr xs,
    arb_srcptr ys, long n, long prec)
{
    if (n == 1)
    {
        arb_set(poly, ys);
    }
    else
    {
        _arb_vec_set(poly, ys, n);
        _interpolate_newton(poly, xs, n, prec);
        while (n > 0 && arb_is_zero(poly + n - 1)) n--;
        _newton_to_monomial(poly, xs, n, prec);
    }
}
Пример #8
0
Файл: atanh.c Проект: isuruf/arb
void
arb_atanh(arb_t z, const arb_t x, slong prec)
{
    if (arb_is_zero(x))
    {
        arb_zero(z);
    }
    else
    {
        arb_t t;
        arb_init(t);

        arb_sub_ui(t, x, 1, prec + 4);
        arb_div(t, x, t, prec + 4);
        arb_mul_2exp_si(t, t, 1);
        arb_neg(t, t);
        arb_log1p(z, t, prec);
        arb_mul_2exp_si(z, z, -1);

        arb_clear(t);
    }
}
Пример #9
0
void
_arb_poly_evaluate_horner(arb_t y, arb_srcptr f, slong len,
                           const arb_t x, slong prec)
{
    if (len == 0)
    {
        arb_zero(y);
    }
    else if (len == 1 || arb_is_zero(x))
    {
        arb_set_round(y, f, prec);
    }
    else if (len == 2)
    {
        arb_mul(y, x, f + 1, prec);
        arb_add(y, y, f + 0, prec);
    }
    else
    {
        slong i = len - 1;
        arb_t t, u;

        arb_init(t);
        arb_init(u);
        arb_set(u, f + i);

        for (i = len - 2; i >= 0; i--)
        {
            arb_mul(t, u, x, prec);
            arb_add(u, f + i, t, prec);
        }

        arb_swap(y, u);

        arb_clear(t);
        arb_clear(u);
    }
}
Пример #10
0
void
acb_acosh(acb_t res, const acb_t z, slong prec)
{
    if (acb_is_one(z))
    {
        acb_zero(res);
    }
    else
    {
        acb_t t, u;
        acb_init(t);
        acb_init(u);

        acb_add_ui(t, z, 1, prec);
        acb_sub_ui(u, z, 1, prec);
        acb_sqrt(t, t, prec);
        acb_sqrt(u, u, prec);
        acb_mul(t, t, u, prec);
        acb_add(t, t, z, prec);

        if (!arb_is_zero(acb_imagref(z)))
        {
            acb_log(res, t, prec);
        }
        else
        {
            /* pure imaginary on (-1,1) */
            arb_abs(acb_realref(u), acb_realref(z));
            arb_one(acb_imagref(u));
            acb_log(res, t, prec);
            if (arb_lt(acb_realref(u), acb_imagref(u)))
                arb_zero(acb_realref(res));
        }

        acb_clear(t);
        acb_clear(u);
    }
}
Пример #11
0
void
_arb_poly_sqrt_series(arb_ptr g,
    arb_srcptr h, slong hlen, slong len, slong prec)
{
    hlen = FLINT_MIN(hlen, len);

    while (hlen > 0 && arb_is_zero(h + hlen - 1))
        hlen--;

    if (hlen <= 1)
    {
        arb_sqrt(g, h, prec);
        _arb_vec_zero(g + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_sqrt(g, h, prec);
        arb_div(g + 1, h + 1, h, prec);
        arb_mul(g + 1, g + 1, g, prec);
        arb_mul_2exp_si(g + 1, g + 1, -1);
    }
    else if (_arb_vec_is_zero(h + 1, hlen - 2))
    {
        arb_t t;
        arb_init(t);
        arf_set_si_2exp_si(arb_midref(t), 1, -1);
        _arb_poly_binomial_pow_arb_series(g, h, hlen, t, len, prec);
        arb_clear(t);
    }
    else
    {
        arb_ptr t;
        t = _arb_vec_init(len);
        _arb_poly_rsqrt_series(t, h, hlen, len, prec);
        _arb_poly_mullow(g, t, len, h, hlen, len, prec);
        _arb_vec_clear(t, len);
    }
}
Пример #12
0
static void
_acb_print(const acb_t z, slong n)
{
    arb_printn(acb_realref(z), n, ARB_STR_NO_RADIUS);

    if (!arb_is_zero(acb_imagref(z)))
    {
        if (arb_is_negative(acb_imagref(z)))
        {
            arb_t t;
            arb_init(t);
            arb_neg(t, acb_imagref(z));
            printf(" - ");
            arb_printn(t, n, ARB_STR_NO_RADIUS);
        }
        else
        {
            printf(" + ");
            arb_printn(acb_imagref(z), n, ARB_STR_NO_RADIUS);
        }
        printf("i");
    }
}
Пример #13
0
void
_arb_poly_taylor_shift_horner(arb_ptr poly, const arb_t c, slong n, slong prec)
{
    slong i, j;

    if (arb_is_one(c))
    {
        for (i = n - 2; i >= 0; i--)
            for (j = i; j < n - 1; j++)
                arb_add(poly + j, poly + j, poly + j + 1, prec);
    }
    else if (arb_equal_si(c, -1))
    {
        for (i = n - 2; i >= 0; i--)
            for (j = i; j < n - 1; j++)
                arb_sub(poly + j, poly + j, poly + j + 1, prec);
    }
    else if (!arb_is_zero(c))
    {
        for (i = n - 2; i >= 0; i--)
            for (j = i; j < n - 1; j++)
                arb_addmul(poly + j, poly + j + 1, c, prec);
    }
}
Пример #14
0
void
_arb_poly_sin_cos_series_tangent(arb_ptr s, arb_ptr c,
        arb_srcptr h, slong hlen, slong len, slong prec, int times_pi)
{
    arb_ptr t, u, v;
    arb_t s0, c0;
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        if (times_pi)
            arb_sin_cos_pi(s, c, h, prec);
        else
            arb_sin_cos(s, c, h, prec);
        _arb_vec_zero(s + 1, len - 1);
        _arb_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)
    */

    arb_init(s0);
    arb_init(c0);

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

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

    /* t = tan((h-h0)/2) */
    arb_zero(u);
    _arb_vec_scalar_mul_2exp_si(u + 1, h + 1, hlen - 1, -1);
    if (times_pi)
    {
        arb_const_pi(t, prec);
        _arb_vec_scalar_mul(u + 1, u + 1, hlen - 1, t, prec);
    }

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

    /* v = 1 + t^2 */
    _arb_poly_mullow(v, t, len, t, len, len, prec);
    arb_add_ui(v, v, 1, prec);

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

    /* sine */
    _arb_poly_mullow(s, t, len, u, len, len, prec);
    _arb_vec_scalar_mul_2exp_si(s, s, len, 1);

    /* cosine */
    arb_sub_ui(v, v, 2, prec);
    _arb_vec_neg(v, v, len);
    _arb_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 (!arb_is_zero(s0))
    {
        _arb_vec_scalar_mul(t, s, len, c0, prec);
        _arb_vec_scalar_mul(u, c, len, s0, prec);
        _arb_vec_scalar_mul(v, s, len, s0, prec);
        _arb_vec_add(s, t, u, len, prec);
        _arb_vec_scalar_mul(t, c, len, c0, prec);
        _arb_vec_sub(c, t, v, len, prec);
    }

    _arb_vec_clear(t, 3 * len);

    arb_clear(s0);
    arb_clear(c0);
}
Пример #15
0
void
acb_hypgeom_erf_asymp(acb_t res, const acb_t z, int complementary, slong prec, slong prec2)
{
    acb_t a, t, u;

    acb_init(a);
    acb_init(t);
    acb_init(u);

    if (!acb_is_exact(z) &&
        (arf_cmpabs_ui(arb_midref(acb_realref(z)), prec) < 0) &&
        (arf_cmpabs_ui(arb_midref(acb_imagref(z)), prec) < 0))
    {
        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)));

        acb_hypgeom_erf_asymp(res, zmid, complementary, prec, prec2);

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

        return;
    }

    acb_one(a);
    acb_mul_2exp_si(a, a, -1);
    acb_mul(t, z, z, prec2);

    acb_hypgeom_u_asymp(u, a, a, t, -1, prec2);

    acb_neg(t, t);
    acb_exp(t, t, prec2);
    acb_mul(u, u, t, prec2);

    arb_const_sqrt_pi(acb_realref(t), prec2);
    arb_zero(acb_imagref(t));
    acb_mul(t, t, z, prec2);
    acb_div(u, u, t, prec2);

    /* branch cut term: -1 or 1 */
    acb_csgn(acb_realref(t), z);
    arb_zero(acb_imagref(t));

    if (complementary)
    {
        /* erfc(z) = 1 - erf(z) = u - (sgn - 1) */
        acb_sub_ui(t, t, 1, prec);
        acb_sub(t, u, t, prec);
    }
    else
    {
        /* erf(z) = sgn - u */
        acb_sub(t, t, u, prec);
    }

    if (arb_is_zero(acb_imagref(z)))
    {
        arb_zero(acb_imagref(t));
    }
    else if (arb_is_zero(acb_realref(z)))
    {
        if (complementary)
            arb_one(acb_realref(t));
        else
            arb_zero(acb_realref(t));
    }

    acb_set(res, t);

    acb_clear(a);
    acb_clear(t);
    acb_clear(u);
}
Пример #16
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);
}
Пример #17
0
void
acb_sqrt(acb_t y, const acb_t x, slong prec)
{
    arb_t r, t, u;
    slong wp;

#define a acb_realref(x)
#define b acb_imagref(x)
#define c acb_realref(y)
#define d acb_imagref(y)

    if (arb_is_zero(b))
    {
        if (arb_is_nonnegative(a))
        {
            arb_sqrt(c, a, prec);
            arb_zero(d);
            return;
        }
        else if (arb_is_nonpositive(a))
        {
            arb_neg(d, a);
            arb_sqrt(d, d, prec);
            arb_zero(c);
            return;
        }
    }

    if (arb_is_zero(a))
    {
        if (arb_is_nonnegative(b))
        {
            arb_mul_2exp_si(c, b, -1);
            arb_sqrt(c, c, prec);
            arb_set(d, c);
            return;
        }
        else if (arb_is_nonpositive(b))
        {
            arb_mul_2exp_si(c, b, -1);
            arb_neg(c, c);
            arb_sqrt(c, c, prec);
            arb_neg(d, c);
            return;
        }
    }

    wp = prec + 4;

    arb_init(r);
    arb_init(t);
    arb_init(u);

    acb_abs(r, x, wp);
    arb_add(t, r, a, wp);

    if (arb_rel_accuracy_bits(t) > 8)
    {
        /* sqrt(a+bi) = sqrt((r+a)/2) + b/sqrt(2*(r+a))*i, r = |a+bi| */

        arb_mul_2exp_si(u, t, 1);
        arb_sqrt(u, u, wp);
        arb_div(d, b, u, prec);

        arb_set_round(c, u, prec);
        arb_mul_2exp_si(c, c, -1);
    }
    else
    {
        /*
            sqrt(a+bi) = sqrt((r+a)/2) + (b/|b|)*sqrt((r-a)/2)*i
                                         (sign)
        */

        arb_mul_2exp_si(t, t, -1);

        arb_sub(u, r, a, wp);
        arb_mul_2exp_si(u, u, -1);

        arb_sqrtpos(c, t, prec);

        if (arb_is_nonnegative(b))
        {
            arb_sqrtpos(d, u, prec);
        }
        else if (arb_is_nonpositive(b))
        {
            arb_sqrtpos(d, u, prec);
            arb_neg(d, d);
        }
        else
        {
            arb_sqrtpos(t, u, wp);
            arb_neg(u, t);
            arb_union(d, t, u, prec);
        }
    }

    arb_clear(r);
    arb_clear(t);
    arb_clear(u);

#undef a
#undef b
#undef c
#undef d
}
Пример #18
0
Файл: ci.c Проект: isuruf/arb
void
acb_hypgeom_ci_asymp(acb_t res, const acb_t z, slong prec)
{
    acb_t t, u, w, v, one;

    acb_init(t);
    acb_init(u);
    acb_init(w);
    acb_init(v);
    acb_init(one);

    acb_one(one);
    acb_mul_onei(w, z);

    /* u = U(1,1,iz) */
    acb_hypgeom_u_asymp(u, one, one, w, -1, prec);
    /* v = e^(-iz) */
    acb_neg(v, w);
    acb_exp(v, v, prec);
    acb_mul(t, u, v, prec);

    if (acb_is_real(z))
    {
        arb_div(acb_realref(t), acb_imagref(t), acb_realref(z), prec);
        arb_zero(acb_imagref(t));
        acb_neg(t, t);
    }
    else
    {
        /* u = U(1,1,-iz) */
        acb_neg(w, w);
        acb_hypgeom_u_asymp(u, one, one, w, -1, prec);
        acb_inv(v, v, prec);
        acb_submul(t, u, v, prec);

        acb_div(t, t, w, prec);
        acb_mul_2exp_si(t, t, -1);
    }

    if (arb_is_zero(acb_realref(z)))
    {
        if (arb_is_positive(acb_imagref(z)))
        {
            arb_const_pi(acb_imagref(t), prec);
            arb_mul_2exp_si(acb_imagref(t), acb_imagref(t), -1);
        }
        else if (arb_is_negative(acb_imagref(z)))
        {
            arb_const_pi(acb_imagref(t), prec);
            arb_mul_2exp_si(acb_imagref(t), acb_imagref(t), -1);
            arb_neg(acb_imagref(t), acb_imagref(t));
        }
        else
        {
            acb_const_pi(u, prec);
            acb_mul_2exp_si(u, u, -1);
            arb_zero(acb_imagref(t));
            arb_add_error(acb_imagref(t), acb_realref(u));
        }
    }
    else
    {
        /* 0 if positive or positive imaginary
           pi if upper left quadrant (including negative real axis)
           -pi if lower left quadrant (including negative imaginary axis) */
        if (arb_is_positive(acb_realref(z)))
        {
            /* do nothing */
        }
        else if (arb_is_negative(acb_realref(z)) && arb_is_nonnegative(acb_imagref(z)))
        {
            acb_const_pi(u, prec);
            arb_add(acb_imagref(t), acb_imagref(t), acb_realref(u), prec);
        }
        else if (arb_is_nonpositive(acb_realref(z)) && arb_is_negative(acb_imagref(z)))
        {
            acb_const_pi(u, prec);
            arb_sub(acb_imagref(t), acb_imagref(t), acb_realref(u), prec);
        }
        else
        {
            /* add [-pi,pi] */
            acb_const_pi(u, prec);
            arb_add_error(acb_imagref(t), acb_realref(u));
        }
    }

    acb_swap(res, t);

    acb_clear(t);
    acb_clear(u);
    acb_clear(w);
    acb_clear(v);
    acb_clear(one);
}
Пример #19
0
void
acb_inv(acb_t res, const acb_t z, slong prec)
{
    mag_t am, bm;
    slong hprec;

#define a arb_midref(acb_realref(z))
#define b arb_midref(acb_imagref(z))
#define x arb_radref(acb_realref(z))
#define y arb_radref(acb_imagref(z))

    /* choose precision for the floating-point approximation of a^2+b^2 so
       that the double rounding result in less than
       2 ulp error; also use at least MAG_BITS bits since the
       value will be recycled for error bounds */
    hprec = FLINT_MAX(prec + 3, MAG_BITS);

    if (arb_is_zero(acb_imagref(z)))
    {
        arb_inv(acb_realref(res), acb_realref(z), prec);
        arb_zero(acb_imagref(res));
        return;
    }

    if (arb_is_zero(acb_realref(z)))
    {
        arb_inv(acb_imagref(res), acb_imagref(z), prec);
        arb_neg(acb_imagref(res), acb_imagref(res));
        arb_zero(acb_realref(res));
        return;
    }

    if (!acb_is_finite(z))
    {
        acb_indeterminate(res);
        return;
    }

    if (mag_is_zero(x) && mag_is_zero(y))
    {
        int inexact;

        arf_t a2b2;
        arf_init(a2b2);

        inexact = arf_sosq(a2b2, a, b, hprec, ARF_RND_DOWN);

        if (arf_is_special(a2b2))
        {
            acb_indeterminate(res);
        }
        else
        {
            _arb_arf_div_rounded_den(acb_realref(res), a, a2b2, inexact, prec);
            _arb_arf_div_rounded_den(acb_imagref(res), b, a2b2, inexact, prec);
            arf_neg(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(res)));
        }

        arf_clear(a2b2);
        return;
    }

    mag_init(am);
    mag_init(bm);

    /* first bound |a|-x, |b|-y */
    arb_get_mag_lower(am, acb_realref(z));
    arb_get_mag_lower(bm, acb_imagref(z));

    if ((mag_is_zero(am) && mag_is_zero(bm)))
    {
        acb_indeterminate(res);
    }
    else
    {
        /*
        The propagated error in the real part is given exactly by

             (a+x')/((a+x')^2+(b+y'))^2 - a/(a^2+b^2) = P / Q,

             P = [(b^2-a^2) x' - a (x'^2+y'^2 + 2y'b)]
             Q = [(a^2+b^2)((a+x')^2+(b+y')^2)]

        where |x'| <= x and |y'| <= y, and analogously for the imaginary part.
        */
        mag_t t, u, v, w;
        arf_t a2b2;
        int inexact;

        mag_init(t);
        mag_init(u);
        mag_init(v);
        mag_init(w);

        arf_init(a2b2);

        inexact = arf_sosq(a2b2, a, b, hprec, ARF_RND_DOWN);

        /* compute denominator */
        /* t = (|a|-x)^2 + (|b|-x)^2 (lower bound) */
        mag_mul_lower(t, am, am);
        mag_mul_lower(u, bm, bm);
        mag_add_lower(t, t, u);
        /* u = a^2 + b^2 (lower bound) */
        arf_get_mag_lower(u, a2b2);
        /* t = ((|a|-x)^2 + (|b|-x)^2)(a^2 + b^2) (lower bound) */
        mag_mul_lower(t, t, u);

        /* compute numerator */
        /* real: |a^2-b^2| x  + |a| ((x^2 + y^2) + 2 |b| y)) */
        /* imag: |a^2-b^2| y  + |b| ((x^2 + y^2) + 2 |a| x)) */
        /* am, bm = upper bounds for a, b */
        arf_get_mag(am, a);
        arf_get_mag(bm, b);

        /* v = x^2 + y^2 */
        mag_mul(v, x, x);
        mag_addmul(v, y, y);

        /* u = |a| ((x^2 + y^2) + 2 |b| y) */
        mag_mul_2exp_si(u, bm, 1);
        mag_mul(u, u, y);
        mag_add(u, u, v);
        mag_mul(u, u, am);

        /* v = |b| ((x^2 + y^2) + 2 |a| x) */
        mag_mul_2exp_si(w, am, 1);
        mag_addmul(v, w, x);
        mag_mul(v, v, bm);

        /* w = |b^2 - a^2| (upper bound) */
        if (arf_cmpabs(a, b) >= 0)
            mag_mul(w, am, am);
        else
            mag_mul(w, bm, bm);

        mag_addmul(u, w, x);
        mag_addmul(v, w, y);

        mag_div(arb_radref(acb_realref(res)), u, t);
        mag_div(arb_radref(acb_imagref(res)), v, t);

        _arb_arf_div_rounded_den_add_err(acb_realref(res), a, a2b2, inexact, prec);
        _arb_arf_div_rounded_den_add_err(acb_imagref(res), b, a2b2, inexact, prec);
        arf_neg(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(res)));

        mag_clear(t);
        mag_clear(u);
        mag_clear(v);
        mag_clear(w);

        arf_clear(a2b2);
    }

    mag_clear(am);
    mag_clear(bm);
#undef a
#undef b
#undef x
#undef y
}
Пример #20
0
void
acb_hypgeom_bessel_i_asymp(acb_t res, const acb_t nu, const acb_t z, long prec)
{
    acb_t A1, A2, C, U1, U2, s, t, u;
    int is_real, is_imag;

    acb_init(A1);
    acb_init(A2);
    acb_init(C);
    acb_init(U1);
    acb_init(U2);
    acb_init(s);
    acb_init(t);
    acb_init(u);

    is_imag = 0;
    is_real = acb_is_real(nu) && acb_is_real(z)
        && (acb_is_int(nu) || arb_is_positive(acb_realref(z)));

    if (!is_real && arb_is_zero(acb_realref(z)) && acb_is_int(nu))
    {
        acb_mul_2exp_si(t, nu, -1);

        if (acb_is_int(t))
            is_real = 1;
        else
            is_imag = 1;
    }

    acb_hypgeom_bessel_i_asymp_prefactors(A1, A2, C, nu, z, prec);

    /* todo: if Ap ~ 2^a and Am = 2^b and U1 ~ U2 ~ 1, change precision? */

    if (!acb_is_finite(A1) || !acb_is_finite(A2) || !acb_is_finite(C))
    {
        acb_indeterminate(res);
    }
    else
    {
        /* s = 1/2 + nu */
        acb_one(s);
        acb_mul_2exp_si(s, s, -1);
        acb_add(s, s, nu, prec);

        /* t = 1 + 2 nu */
        acb_mul_2exp_si(t, nu, 1);
        acb_add_ui(t, t, 1, prec);

        acb_mul_2exp_si(u, z, 1);
        acb_hypgeom_u_asymp(U1, s, t, u, -1, prec);
        acb_neg(u, u);
        acb_hypgeom_u_asymp(U2, s, t, u, -1, prec);

        acb_mul(res, A1, U1, prec);
        acb_addmul(res, A2, U2, prec);
        acb_mul(res, res, C, prec);

        if (is_real)
            arb_zero(acb_imagref(res));
        if (is_imag)
            arb_zero(acb_realref(res));
    }

    acb_clear(A1);
    acb_clear(A2);
    acb_clear(C);
    acb_clear(U1);
    acb_clear(U2);
    acb_clear(s);
    acb_clear(t);
    acb_clear(u);
}
Пример #21
0
void
_arb_poly_pow_ui_trunc_binexp(arb_ptr res,
    arb_srcptr f, slong flen, ulong exp, slong len, slong prec)
{
    arb_ptr v, R, S, T;
    slong rlen;
    ulong bit;

    if (exp <= 1)
    {
        if (exp == 0)
            arb_one(res);
        else if (exp == 1)
            _arb_vec_set_round(res, f, len, prec);
        return;
    }

    /* (f * x^r)^m = x^(rm) * f^m */
    while (flen > 1 && arb_is_zero(f))
    {
        if (((ulong) len) > exp)
        {
            _arb_vec_zero(res, exp);
            len -= exp;
            res += exp;
        }
        else
        {
            _arb_vec_zero(res, len);
            return;
        }

        f++;
        flen--;
    }

    if (exp == 2)
    {
        _arb_poly_mullow(res, f, flen, f, flen, len, prec);
        return;
    }

    if (flen == 1)
    {
        arb_pow_ui(res, f, exp, prec);
        return;
    }

    v = _arb_vec_init(len);
    bit = UWORD(1) << (FLINT_BIT_COUNT(exp) - 2);
    
    if (n_zerobits(exp) % 2)
    {
        R = res;
        S = v;
    }
    else
    {
        R = v;
        S = res;
    }

    MUL(R, rlen, f, flen, f, flen, len, prec);

    if (bit & exp)
    {
        MUL(S, rlen, R, rlen, f, flen, len, prec);
        T = R;
        R = S;
        S = T;
    }
    
    while (bit >>= 1)
    {
        if (bit & exp)
        {
            MUL(S, rlen, R, rlen, R, rlen, len, prec);
            MUL(R, rlen, S, rlen, f, flen, len, prec);
        }
        else
        {
            MUL(S, rlen, R, rlen, R, rlen, len, prec);
            T = R;
            R = S;
            S = T;
        }
    }
    
    _arb_vec_clear(v, len);
}
Пример #22
0
/* derivatives: |8/sqrt(pi) sin(2z^2)|, |8/sqrt(pi) cos(2z^2)| <= 5 exp(4|xy|) */
void
acb_hypgeom_fresnel_erf_error(acb_t res1, acb_t res2, const acb_t z, slong prec)
{
    mag_t re;
    mag_t im;
    acb_t zmid;

    mag_init(re);
    mag_init(im);
    acb_init(zmid);

    if (arf_cmpabs_ui(arb_midref(acb_realref(z)), 1000) < 0 &&
        arf_cmpabs_ui(arb_midref(acb_imagref(z)), 1000) < 0)
    {
        arb_get_mag(re, acb_realref(z));
        arb_get_mag(im, acb_imagref(z));
        mag_mul(re, re, im);
        mag_mul_2exp_si(re, re, 2);
        mag_exp(re, re);
        mag_mul_ui(re, re, 5);
    }
    else
    {
        arb_t t;
        arb_init(t);
        arb_mul(t, acb_realref(z), acb_imagref(z), prec);
        arb_abs(t, t);
        arb_mul_2exp_si(t, t, 2);
        arb_exp(t, t, prec);
        arb_get_mag(re, t);
        mag_mul_ui(re, re, 5);
        arb_clear(t);
    }

    mag_hypot(im, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z)));
    mag_mul(re, re, im);

    if (arb_is_zero(acb_imagref(z)))
    {
        mag_set_ui(im, 8);  /* For real x, |S(x)| < 4, |C(x)| < 4. */
        mag_min(re, re, im);
        mag_zero(im);
    }
    else if (arb_is_zero(acb_realref(z)))
    {
        mag_set_ui(im, 8);
        mag_min(im, re, im);
        mag_zero(re);
    }
    else
    {
        mag_set(im, re);
    }

    arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z)));
    arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z)));

    acb_hypgeom_fresnel_erf(res1, res2, zmid, prec);

    if (res1 != NULL)
    {
        arb_add_error_mag(acb_realref(res1), re);
        arb_add_error_mag(acb_imagref(res1), im);
    }

    if (res2 != NULL)
    {
        arb_add_error_mag(acb_realref(res2), re);
        arb_add_error_mag(acb_imagref(res2), im);
    }

    mag_clear(re);
    mag_clear(im);
    acb_clear(zmid);
}
Пример #23
0
void
acb_hypgeom_fresnel_erf(acb_t res1, acb_t res2, const acb_t z, slong prec)
{
    acb_t t, u, v, w1, w2;

    acb_init(t);
    acb_init(v);
    acb_init(w1);

    if (arb_is_zero(acb_imagref(z)))
    {
        acb_mul_onei(t, z);
        acb_add(w1, z, t, 2 * prec);
        acb_hypgeom_erf(t, w1, prec + 4);
        acb_mul_2exp_si(t, t, 1);

        acb_mul_onei(v, t);
        acb_add(t, t, v, prec);

        if (res1 != NULL) acb_set_arb(res1, acb_realref(t));
        if (res2 != NULL) acb_set_arb(res2, acb_imagref(t));
    }
    else if (arb_is_zero(acb_realref(z)))
    {
        acb_mul_onei(t, z);
        acb_sub(w1, t, z, 2 * prec);
        acb_hypgeom_erf(t, w1, prec + 4);
        acb_mul_2exp_si(t, t, 1);

        acb_mul_onei(v, t);
        acb_add(t, t, v, prec);

        if (res1 != NULL) acb_set_arb(res1, acb_realref(t));
        if (res1 != NULL) acb_mul_onei(res1, res1);
        if (res2 != NULL) acb_set_arb(res2, acb_imagref(t));
        if (res2 != NULL) acb_div_onei(res2, res2);
    }
    else
    {
        acb_init(u);
        acb_init(w2);

        /* w1 = (1+i)z, w2 = (1-i)z */
        acb_mul_onei(t, z);
        acb_add(w1, z, t, 2 * prec);
        acb_sub(w2, z, t, 2 * prec);

        acb_hypgeom_erf(t, w1, prec + 4);
        acb_hypgeom_erf(u, w2, prec + 4);

        /* S = (1+i) (t - ui) = (1+i) t + (1-i) u */
        /* C = (1-i) (t + ui) = (1-i) t + (1+i) u */

        acb_mul_onei(v, t);
        if (res1 != NULL) acb_add(res1, t, v, prec);
        if (res2 != NULL) acb_sub(res2, t, v, prec);

        acb_mul_onei(v, u);
        if (res1 != NULL) acb_add(res1, res1, u, prec);
        if (res1 != NULL) acb_sub(res1, res1, v, prec);
        if (res2 != NULL) acb_add(res2, res2, u, prec);
        if (res2 != NULL) acb_add(res2, res2, v, prec);

        acb_clear(u);
        acb_clear(w2);
    }

    acb_clear(t);
    acb_clear(v);
    acb_clear(w1);
}
Пример #24
0
Файл: chi.c Проект: isuruf/arb
void
acb_hypgeom_chi_asymp(acb_t res, const acb_t z, slong prec)
{
    acb_t t, u, v, one;

    acb_init(t);
    acb_init(u);
    acb_init(v);
    acb_init(one);

    acb_one(one);

    /* u = U(1,1,z) */
    acb_hypgeom_u_asymp(u, one, one, z, -1, prec);
    /* v = e^(-z) */
    acb_neg(v, z);
    acb_exp(v, v, prec);
    acb_mul(t, u, v, prec);

    if (arb_is_zero(acb_realref(z)))
    {
        arb_div(acb_realref(t), acb_imagref(t), acb_imagref(z), prec);
        arb_zero(acb_imagref(t));
        acb_neg(t, t);
    }
    else
    {
        /* u = U(1,1,-z) */
        acb_neg(u, z);
        acb_hypgeom_u_asymp(u, one, one, u, -1, prec);
        acb_inv(v, v, prec);
        acb_submul(t, u, v, prec);

        acb_div(t, t, z, prec);
        acb_mul_2exp_si(t, t, -1);
        acb_neg(t, t);
    }

    if (acb_is_real(z))
    {
        if (arb_is_positive(acb_realref(z)))
        {
            arb_zero(acb_imagref(t));
        }
        else if (arb_is_negative(acb_realref(z)))
        {
            arb_const_pi(acb_imagref(t), prec);
        }
        else
        {
            /* add [-pi,pi]/2 i */
            acb_const_pi(u, prec);
            arb_zero(acb_imagref(t));
            arb_add_error(acb_imagref(t), acb_realref(u));
        }
    }
    else
    {
        /* -pi/2 if positive real or in lower half plane
           pi/2 if negative real or in upper half plane */
        if (arb_is_negative(acb_imagref(z)))
        {
            acb_const_pi(u, prec);
            acb_mul_2exp_si(u, u, -1);
            arb_sub(acb_imagref(t), acb_imagref(t), acb_realref(u), prec);
        }
        else if (arb_is_positive(acb_imagref(z)))
        {
            acb_const_pi(u, prec);
            acb_mul_2exp_si(u, u, -1);
            arb_add(acb_imagref(t), acb_imagref(t), acb_realref(u), prec);
        }
        else
        {
            /* add [-pi,pi]/2 i */
            acb_const_pi(u, prec);
            acb_mul_2exp_si(u, u, -1);
            arb_add_error(acb_imagref(t), acb_realref(u));
        }
    }

    acb_swap(res, t);

    acb_clear(t);
    acb_clear(u);
    acb_clear(v);
    acb_clear(one);
}
Пример #25
0
void
acb_modular_theta_const_sum(acb_t theta2, acb_t theta3, acb_t theta4,
    const acb_t q, long prec)
{
    mag_t qmag, err;
    double log2q_approx;
    int is_real, is_real_or_imag;
    long N;

    mag_init(qmag);
    mag_init(err);

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

    is_real = arb_is_zero(acb_imagref(q));
    is_real_or_imag = is_real || arb_is_zero(acb_realref(q));

    if (log2q_approx >= 0.0)
    {
        N = 1;
        mag_inf(err);
    }
    else
    {
        N = 0;

        while (0.05 * N * N < prec)
        {
            if (log2q_approx * ((N+2)*(N+2)/4) < -prec - 2)
                break;
            N++;
        }
        N = (N+2)*(N+2)/4;

        mag_geom_series(err, qmag, N);
        mag_mul_2exp_si(err, err, 1); /* each term is taken twice */

        if (mag_is_inf(err))
            N = 1;
    }

    if (N < 1800)
        acb_modular_theta_const_sum_basecase(theta2, theta3, theta4, q, N, prec);
    else
        acb_modular_theta_const_sum_rs(theta2, theta3, theta4, q, N, prec);

    if (is_real_or_imag)
        arb_add_error_mag(acb_realref(theta2), err);
    else
        acb_add_error_mag(theta2, err);

    if (is_real)
    {
        arb_add_error_mag(acb_realref(theta3), err);
        arb_add_error_mag(acb_realref(theta4), err);
    }
    else
    {
        acb_add_error_mag(theta3, err);
        acb_add_error_mag(theta4, err);
    }

    mag_clear(qmag);
    mag_clear(err);
}
Пример #26
0
void
_arb_poly_exp_series(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec)
{
    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        arb_exp(f, h, prec);
        _arb_vec_zero(f + 1, n - 1);
    }
    else if (n == 2)
    {
        arb_exp(f, h, prec);
        arb_mul(f + 1, f, h + 1, prec);  /* safe since hlen >= 2 */
    }
    else if (_arb_vec_is_zero(h + 1, hlen - 2)) /* h = a + bx^d */
    {
        slong i, j, d = hlen - 1;
        arb_t t;
        arb_init(t);
        arb_set(t, h + d);
        arb_exp(f, h, prec);
        for (i = 1, j = d; j < n; j += d, i++)
        {
            arb_mul(f + j, f + j - d, t, prec);
            arb_div_ui(f + j, f + j, i, prec);
            _arb_vec_zero(f + j - d + 1, hlen - 2);
        }
        _arb_vec_zero(f + j - d + 1, n - (j - d + 1));
        arb_clear(t);
    }
    else if (hlen <= arb_poly_newton_exp_cutoff)
    {
        _arb_poly_exp_series_basecase(f, h, hlen, n, prec);
    }
    else
    {
        arb_ptr g, t;
        arb_t u;
        int fix;

        g = _arb_vec_init((n + 1) / 2);
        fix = (hlen < n || h == f || !arb_is_zero(h));

        if (fix)
        {
            t = _arb_vec_init(n);
            _arb_vec_set(t + 1, h + 1, hlen - 1);
        }
        else
            t = (arb_ptr) h;

        arb_init(u);
        arb_exp(u, h, prec);

        _arb_poly_exp_series_newton(f, g, t, n, prec, 0, arb_poly_newton_exp_cutoff);

        if (!arb_is_one(u))
            _arb_vec_scalar_mul(f, f, n, u, prec);

        _arb_vec_clear(g, (n + 1) / 2);
        if (fix)
            _arb_vec_clear(t, n);
        arb_clear(u);
    }
}