Exemple #1
0
/* bound (1 + 1/m)^n, m > 0, n >= 0 */
void
mag_binpow_uiui(mag_t b, ulong m, ulong n)
{
    mag_t t;

    if (m == 0)
    {
        mag_inf(b);
        return;
    }

    mag_init(t);

    /* bound by exp(n/m) <= 1 + (n/m) + (n/m)^2 */
    if (m > n)
    {
        mag_set_ui(t, n);   /* x = n/m */
        mag_div_ui(t, t, m);

        mag_mul(b, t, t);   /* x^2 */
        mag_add(b, b, t);   /* x */
        mag_one(t);
        mag_add(b, b, t);   /* 1 */
    }
    else
    {
        mag_one(b);
        mag_div_ui(b, b, m);
        mag_one(t);
        mag_add(t, t, b);
        mag_pow_ui(b, t, n);
    }

    mag_clear(t);
}
Exemple #2
0
void
arb_root_ui_algebraic(arb_t res, const arb_t x, ulong k, slong prec)
{
    mag_t r, msubr, m1k, t;

    if (arb_is_exact(x))
    {
        arb_root_arf(res, arb_midref(x), k, prec);
        return;
    }

    if (!arb_is_nonnegative(x))
    {
        arb_indeterminate(res);
        return;
    }

    mag_init(r);
    mag_init(msubr);
    mag_init(m1k);
    mag_init(t);

    /* x = [m-r, m+r] */
    mag_set(r, arb_radref(x));
    /* m - r */
    arb_get_mag_lower(msubr, x);

    /* m^(1/k) */
    arb_root_arf(res, arb_midref(x), k, prec);

    /* bound for m^(1/k) */
    arb_get_mag(m1k, res);

    /* C = min(1, log(1+r/(m-r))/k) */
    mag_div(t, r, msubr);
    mag_log1p(t, t);
    mag_div_ui(t, t, k);
    if (mag_cmp_2exp_si(t, 0) > 0)
        mag_one(t);

    /* C m^(1/k) */
    mag_mul(t, m1k, t);
    mag_add(arb_radref(res), arb_radref(res), t);

    mag_clear(r);
    mag_clear(msubr);
    mag_clear(m1k);
    mag_clear(t);
}
Exemple #3
0
void
mag_root(mag_t y, const mag_t x, ulong n)
{
    if (n == 0)
    {
        mag_inf(y);
    }
    else if (n == 1 || mag_is_special(x))
    {
        mag_set(y, x);
    }
    else if (n == 2)
    {
        mag_sqrt(y, x);
    }
    else if (n == 4)
    {
        mag_sqrt(y, x);
        mag_sqrt(y, y);
    }
    else
    {
        fmpz_t e, f;

        fmpz_init_set_ui(e, MAG_BITS);
        fmpz_init(f);

        /* We evaluate exp(log(1+2^(kn)x)/n) 2^-k where k is chosen
           so that 2^(kn) x ~= 2^30. TODO: this rewriting is probably
           unnecessary with the new exp/log functions. */
        fmpz_sub(e, e, MAG_EXPREF(x));
        fmpz_cdiv_q_ui(e, e, n);
        fmpz_mul_ui(f, e, n);
        mag_mul_2exp_fmpz(y, x, f);
        mag_log1p(y, y);
        mag_div_ui(y, y, n);
        mag_exp(y, y);
        fmpz_neg(e, e);
        mag_mul_2exp_fmpz(y, y, e);

        fmpz_clear(e);
        fmpz_clear(f);
    }
}
void
_arb_sin_cos_generic(arb_t s, arb_t c, const arf_t x, const mag_t xrad, slong prec)
{
    int want_sin, want_cos;
    slong maglim;

    want_sin = (s != NULL);
    want_cos = (c != NULL);

    if (arf_is_zero(x) && mag_is_zero(xrad))
    {
        if (want_sin) arb_zero(s);
        if (want_cos) arb_one(c);
        return;
    }

    if (!arf_is_finite(x) || !mag_is_finite(xrad))
    {
        if (arf_is_nan(x))
        {
            if (want_sin) arb_indeterminate(s);
            if (want_cos) arb_indeterminate(c);
        }
        else
        {
            if (want_sin) arb_zero_pm_one(s);
            if (want_cos) arb_zero_pm_one(c);
        }
        return;
    }

    maglim = FLINT_MAX(65536, 4 * prec);

    if (mag_cmp_2exp_si(xrad, -16) > 0 || arf_cmpabs_2exp_si(x, maglim) > 0)
    {
        _arb_sin_cos_wide(s, c, x, xrad, prec);
        return;
    }

    if (arf_cmpabs_2exp_si(x, -(prec/2) - 2) <= 0)
    {
        mag_t t, u, v;
        mag_init(t);
        mag_init(u);
        mag_init(v);

        arf_get_mag(t, x);
        mag_add(t, t, xrad);
        mag_mul(u, t, t);

        /* |sin(z)-z| <= z^3/6 */
        if (want_sin)
        {
            arf_set(arb_midref(s), x);
            mag_set(arb_radref(s), xrad);
            arb_set_round(s, s, prec);
            mag_mul(v, u, t);
            mag_div_ui(v, v, 6);
            arb_add_error_mag(s, v);
        }

        /* |cos(z)-1| <= z^2/2 */
        if (want_cos)
        {
            arf_one(arb_midref(c));
            mag_mul_2exp_si(arb_radref(c), u, -1);
        }

        mag_clear(t);
        mag_clear(u);
        mag_clear(v);
        return;
    }

    if (mag_is_zero(xrad))
    {
        arb_sin_cos_arf_generic(s, c, x, prec);
    }
    else
    {
        mag_t t;
        slong exp, radexp;

        mag_init_set(t, xrad);

        exp = arf_abs_bound_lt_2exp_si(x);
        radexp = MAG_EXP(xrad);
        if (radexp < MAG_MIN_LAGOM_EXP || radexp > MAG_MAX_LAGOM_EXP)
            radexp = MAG_MIN_LAGOM_EXP;

        if (want_cos && exp < -2)
            prec = FLINT_MIN(prec, 20 - FLINT_MAX(exp, radexp) - radexp);
        else
            prec = FLINT_MIN(prec, 20 - radexp);

        arb_sin_cos_arf_generic(s, c, x, prec);

        /* todo: could use quadratic bound */
        if (want_sin) mag_add(arb_radref(s), arb_radref(s), t);
        if (want_cos) mag_add(arb_radref(c), arb_radref(c), t);

        mag_clear(t);
    }
}
int main()
{
    slong iter;
    flint_rand_t state;

    flint_printf("root_bound_fujiwara....");
    fflush(stdout);

    flint_randinit(state);

    for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++)
    {
        arb_poly_t a;
        arb_ptr roots;
        arb_t t;
        mag_t mag1, mag2;
        slong i, deg, prec;

        prec = 10 + n_randint(state, 400);
        deg = n_randint(state, 10);

        arb_init(t);
        arb_poly_init(a);
        mag_init(mag1);
        mag_init(mag2);
        roots = _arb_vec_init(deg);

        for (i = 0; i < deg; i++)
            arb_randtest(roots + i, state, prec, 1 + n_randint(state, 20));

        arb_poly_product_roots(a, roots, deg, prec);
        arb_randtest(t, state, prec, 1 + n_randint(state, 20));
        arb_poly_scalar_mul(a, a, t, prec);

        arb_poly_root_bound_fujiwara(mag1, a);

        for (i = 0; i < deg; i++)
        {
            arb_get_mag(mag2, roots + i);

            /* arb_get_mag gives an upper bound which due to rounding
               could be larger than mag1, so we pick a slightly
               smaller number */
            mag_mul_ui(mag2, mag2, 10000);
            mag_div_ui(mag2, mag2, 10001);

            if (mag_cmp(mag2, mag1) > 0)
            {
                flint_printf("FAIL\n");
                flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n");
                flint_printf("root = "); arb_printd(roots + i, 15); flint_printf("\n\n");
                flint_printf("mag1 = "); mag_printd(mag1, 10); flint_printf("\n\n");
                flint_printf("mag2 = "); mag_printd(mag2, 10); flint_printf("\n\n");
                abort();
            }
        }

        _arb_vec_clear(roots, deg);
        arb_clear(t);
        arb_poly_clear(a);
        mag_clear(mag1);
        mag_clear(mag2);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
Exemple #6
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);
}