예제 #1
0
파일: exp_tail.c 프로젝트: bluescarni/arb
void
mag_exp_tail(mag_t z, const mag_t x, ulong N)
{
    if (N == 0 || mag_is_inf(x))
    {
        mag_exp(z, x);
    }
    else if (mag_is_zero(x))
    {
        mag_zero(z);
    }
    else
    {
        mag_t t;
        mag_init(t);
        mag_set_ui_2exp_si(t, N, -1);

        /* bound by geometric series when N >= 2*x  <=> N/2 >= x */
        if (mag_cmp(t, x) >= 0)
        {
            /* 2 c^N / N! */
            mag_pow_ui(t, x, N);
            mag_rfac_ui(z, N);
            mag_mul(z, z, t);
            mag_mul_2exp_si(z, z, 1);
        }
        else
        {
            mag_exp(z, x);
        }

        mag_clear(t);
    }
}
예제 #2
0
파일: geom_series.c 프로젝트: isuruf/arb
void
mag_geom_series(mag_t res, const mag_t x, ulong n)
{
    if (mag_is_zero(x))
    {
        if (n == 0)
            mag_one(res);
        else
            mag_zero(res);
    }
    else if (mag_is_inf(x))
    {
        mag_inf(res);
    }
    else
    {
        mag_t t;
        mag_init(t);
        mag_one(t);
        mag_sub_lower(t, t, x);

        if (mag_is_zero(t))
        {
            mag_inf(res);
        }
        else
        {
            mag_pow_ui(res, x, n);
            mag_div(res, res, t);
        }

        mag_clear(t);
    }
}
예제 #3
0
파일: div.c 프로젝트: bluescarni/arb
void
arb_div(arb_t z, const arb_t x, const arb_t y, long prec)
{
    mag_t zr, xm, ym, yl, yw;
    int inexact;

    if (arb_is_exact(y))
    {
        arb_div_arf(z, x, arb_midref(y), prec);
    }
    else if (mag_is_inf(arb_radref(x)) || mag_is_inf(arb_radref(y)))
    {
        arf_div(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND);
        mag_inf(arb_radref(z));
    }
    else
    {
        mag_init_set_arf(xm, arb_midref(x));
        mag_init_set_arf(ym, arb_midref(y));
        mag_init(zr);
        mag_init(yl);
        mag_init(yw);

        /* (|x|*yrad + |y|*xrad)/(y*(|y|-yrad)) */
        mag_mul(zr, xm, arb_radref(y));
        mag_addmul(zr, ym, arb_radref(x));
        arb_get_mag_lower(yw, y);

        arf_get_mag_lower(yl, arb_midref(y));
        mag_mul_lower(yl, yl, yw);

        mag_div(zr, zr, yl);

        inexact = arf_div(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND);

        if (inexact)
            arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec);
        else
            mag_swap(arb_radref(z), zr);

        mag_clear(xm);
        mag_clear(ym);
        mag_clear(zr);
        mag_clear(yl);
        mag_clear(yw);
    }
}
예제 #4
0
void
mag_expinv(mag_t res, const mag_t x)
{
    if (mag_is_zero(x))
    {
        mag_one(res);
    }
    else if (mag_is_inf(x))
    {
        mag_zero(res);
    }
    else if (fmpz_sgn(MAG_EXPREF(x)) <= 0)
    {
        mag_one(res);
    }
    else if (fmpz_cmp_ui(MAG_EXPREF(x), 2 * MAG_BITS) > 0)
    {
        fmpz_t t;
        fmpz_init(t);

        /* If x > 2^60, exp(-x) < 2^(-2^60 / log(2))  */
        /* -1/log(2) < -369/256 */
        fmpz_set_si(t, -369);
        fmpz_mul_2exp(t, t, 2 * MAG_BITS - 8);

        mag_one(res);
        mag_mul_2exp_fmpz(res, res, t);

        fmpz_clear(t);
    }
    else
    {
        fmpz_t t;
        slong e = MAG_EXP(x);

        fmpz_init(t);
        fmpz_set_ui(t, MAG_MAN(x));

        if (e >= MAG_BITS)
            fmpz_mul_2exp(t, t, e - MAG_BITS);
        else
            fmpz_tdiv_q_2exp(t, t, MAG_BITS - e);

        /* upper bound for 1/e */
        mag_set_ui_2exp_si(res, 395007543, -30);

        mag_pow_fmpz(res, res, t);
        fmpz_clear(t);
    }
}
예제 #5
0
static void
arb_infimum(arf_t res, const arb_t x)
{
    if (arf_is_nan(arb_midref(x)))
    {
        arf_nan(res);
    }
    else if (mag_is_inf(arb_radref(x)))
    {
        arf_neg_inf(res);
    }
    else
    {
        arf_set_mag(res, arb_radref(x));
        arf_sub(res, arb_midref(x), res, ARF_PREC_EXACT, ARF_RND_FLOOR);
    }
}
예제 #6
0
static void
arb_supremum(arf_t res, const arb_t x)
{
    if (arf_is_nan(arb_midref(x)))
    {
        arf_nan(res);
    }
    else if (mag_is_inf(arb_radref(x)))
    {
        arf_pos_inf(res);
    }
    else
    {
        arf_set_mag(res, arb_radref(x));
        arf_add(res, res, arb_midref(x), ARF_PREC_EXACT, ARF_RND_CEIL);
    }
}
예제 #7
0
파일: div.c 프로젝트: bluescarni/arb
void
arb_div_arf(arb_t z, const arb_t x, const arf_t y, long prec)
{
    mag_t zr, ym;
    int inexact;

    if (arf_is_zero(y))
    {
        arb_zero_pm_inf(z);
    }
    else if (arb_is_exact(x))
    {
        inexact = arf_div(arb_midref(z), arb_midref(x), y, prec, ARB_RND);

        if (inexact)
            arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec);
        else
            mag_zero(arb_radref(z));
    }
    else if (mag_is_inf(arb_radref(x)))
    {
        arf_div(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
        mag_inf(arb_radref(z));
    }
    else
    {
        mag_init(ym);
        mag_init(zr);

        arf_get_mag_lower(ym, y);
        mag_div(zr, arb_radref(x), ym);

        inexact = arf_div(arb_midref(z), arb_midref(x), y, prec, ARB_RND);

        if (inexact)
            arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec);
        else
            mag_swap(arb_radref(z), zr);

        mag_clear(ym);
        mag_clear(zr);
    }
}
예제 #8
0
파일: get_d.c 프로젝트: bluescarni/arb
double
mag_get_d(const mag_t z)
{
    if (mag_is_zero(z))
    {
        return 0.0;
    }
    else if (mag_is_inf(z))
    {
        return D_INF;
    }
    else if (MAG_EXP(z) < -1000 || MAG_EXP(z) > 1000)
    {
        if (fmpz_sgn(MAG_EXPREF(z)) < 0)
            return ldexp(1.0, -1000);
        else
            return D_INF;
    }
    else
    {
        return ldexp(MAG_MAN(z), MAG_EXP(z) - MAG_BITS);
    }
}
예제 #9
0
파일: pow_ui.c 프로젝트: bluescarni/arb
void
mag_pow_ui_lower(mag_t z, const mag_t x, ulong e)
{
    if (e <= 2)
    {
        if (e == 0)
            mag_one(z);
        else if (e == 1)
            mag_set(z, x);
        else
            mag_mul_lower(z, x, x);
    }
    else if (mag_is_inf(x))
    {
        mag_inf(z);
    }
    else
    {
        mag_t y;
        int i, bits;

        mag_init_set(y, x);

        bits = FLINT_BIT_COUNT(e);

        for (i = bits - 2; i >= 0; i--)
        {
            mag_mul_lower(y, y, y);
            if (e & (1UL << i))
                mag_mul_lower(y, y, x);
        }

        mag_swap(z, y);
        mag_clear(y);
    }
}
예제 #10
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);
}
예제 #11
0
void
acb_hypgeom_2f1_continuation(acb_t res, acb_t res1,
    const acb_t a, const acb_t b, const acb_t c, const acb_t y,
    const acb_t z, const acb_t f0, const acb_t f1, long prec)
{
    mag_t A, nu, N, w, err, err1, R, T, goal;
    acb_t x;
    long j, k;

    mag_init(A);
    mag_init(nu);
    mag_init(N);
    mag_init(err);
    mag_init(err1);
    mag_init(w);
    mag_init(R);
    mag_init(T);
    mag_init(goal);
    acb_init(x);

    bound(A, nu, N, a, b, c, y, f0, f1);

    acb_sub(x, z, y, prec);

    /* |T(k)| <= A * binomial(N+k, k) * nu^k * |x|^k */
    acb_get_mag(w, x);
    mag_mul(w, w, nu); /* w = nu |x| */
    mag_mul_2exp_si(goal, A, -prec-2);

    /* bound for T(0) */
    mag_set(T, A);
    mag_inf(R);

    for (k = 1; k < 100 * prec; k++)
    {
        /* T(k) = T(k) * R(k), R(k) = (N+k)/k * w = (1 + N/k) w */
        mag_div_ui(R, N, k);
        mag_add_ui(R, R, 1);
        mag_mul(R, R, w);

        /* T(k) */
        mag_mul(T, T, R);

        if (mag_cmp(T, goal) <= 0 && mag_cmp_2exp_si(R, 0) < 0)
            break;
    }

    /* T(k) [1 + R + R^2 + R^3 + ...] */
    mag_geom_series(err, R, 0);
    mag_mul(err, T, err);

    /* Now compute T, R for the derivative */
    /* Coefficients are A * (k+1) * binomial(N+k+1, k+1) */
    mag_add_ui(T, N, 1);
    mag_mul(T, T, A);
    mag_inf(R);

    for (j = 1; j <= k; j++)
    {
        mag_add_ui(R, N, k + 1);
        mag_div_ui(R, R, k);
        mag_mul(R, R, w);
        mag_mul(T, T, R);
    }

    mag_geom_series(err1, R, 0);
    mag_mul(err1, T, err1);

    if (mag_is_inf(err))
    {
        acb_indeterminate(res);
        acb_indeterminate(res1);
    }
    else
    {
        evaluate_sum(res, res1, a, b, c, y, x, f0, f1, k, prec);

        acb_add_error_mag(res, err);
        acb_add_error_mag(res1, err1);
    }

    mag_clear(A);
    mag_clear(nu);
    mag_clear(N);
    mag_clear(err);
    mag_clear(err1);
    mag_clear(w);
    mag_clear(R);
    mag_clear(T);
    mag_clear(goal);
    acb_clear(x);
}