Пример #1
0
int
mag_close(const mag_t am, const mag_t bm)
{
    arf_t t, a, b;
    int res1, res2;

    arf_init(t);
    arf_init(a);
    arf_init(b);

    arf_set_mag(a, am);
    arf_set_mag(b, bm);

    arf_mul_ui(t, b, 257, MAG_BITS, ARF_RND_UP);
    arf_mul_2exp_si(t, t, -8);
    res1 = arf_cmp(a, t) <= 0;

    arf_mul_ui(t, a, 257, MAG_BITS, ARF_RND_UP);
    arf_mul_2exp_si(t, t, -8);
    res2 = arf_cmp(b, t) <= 0;

    arf_clear(t);
    arf_clear(a);
    arf_clear(b);

    return res1 && res2;
}
Пример #2
0
static __inline__ void
arb_nonnegative_part(arb_t z, const arb_t x, long prec)
{
    if (arb_contains_negative(x))
    {
        arf_t t;
        arf_init(t);

        arf_set_mag(t, arb_radref(x));
        arf_add(arb_midref(z), arb_midref(x), t, MAG_BITS, ARF_RND_CEIL);

        if (arf_sgn(arb_midref(z)) <= 0)
        {
            mag_zero(arb_radref(z));
        }
        else
        {
            arf_mul_2exp_si(arb_midref(z), arb_midref(z), -1);
            arf_get_mag(arb_radref(z), arb_midref(z));

            /* XXX: needed since arf_get_mag is inexact */
            arf_set_mag(arb_midref(z), arb_radref(z));
        }

        arf_clear(t);
    }
    else
    {
        arb_set(z, x);
    }
}
Пример #3
0
slong
_acb_get_rad_mag(const acb_t z)
{
    slong rm, im;

    /* TODO: write mag function */
    arf_t t;
    arf_init(t);

    arf_set_mag(t, arb_radref(acb_realref(z)));
    rm = arf_abs_bound_lt_2exp_si(t);

    arf_set_mag(t, arb_radref(acb_imagref(z)));
    im = arf_abs_bound_lt_2exp_si(t);

    arf_clear(t);

    return FLINT_MAX(rm, im);
}
Пример #4
0
int main()
{
    slong iter;
    flint_rand_t state;

    flint_printf("get_mag....");
    fflush(stdout);
    flint_randinit(state);

    for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++)
    {
        acb_t a;
        arf_t m2, x, y, s;
        mag_t m;

        acb_init(a);
        mag_init(m);
        arf_init(m2);
        arf_init(x);
        arf_init(y);
        arf_init(s);

        acb_randtest_special(a, state, 200, 10);
        acb_get_mag(m, a);
        MAG_CHECK_BITS(m)

        /* check m^2 >= x^2 + y^2 */
        arf_set_mag(m2, m);
        arf_mul(m2, m2, m2, ARF_PREC_EXACT, ARF_RND_DOWN);

        arb_get_abs_ubound_arf(x, acb_realref(a), ARF_PREC_EXACT);
        arb_get_abs_ubound_arf(y, acb_imagref(a), ARF_PREC_EXACT);
        arf_sosq(s, x, y, ARF_PREC_EXACT, ARF_RND_DOWN);

        if (arf_cmp(m2, s) < 0)
        {
            flint_printf("FAIL:\n\n");
            flint_printf("a = "); acb_print(a); flint_printf("\n\n");
            flint_printf("m = "); mag_print(m); flint_printf("\n\n");
            flint_abort();
        }

        acb_clear(a);
        mag_clear(m);
        arf_clear(m2);
        arf_clear(x);
        arf_clear(y);
        arf_clear(s);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
Пример #5
0
void fprintarb(FILE *fp,const arb_t x) {
    static int init;
    static arf_t a;

    if (!init) {
        arf_init(a);
        init = 1;
    }

    fprintarf(fp,arb_midref(x));
    fprintf(fp," ");
    arf_set_mag(a,arb_radref(x));
    fprintarf(fp,a);
}
Пример #6
0
int
_arb_poly_newton_step(arb_t xnew, arb_srcptr poly, long len,
    const arb_t x,
    const arb_t convergence_interval,
    const arf_t convergence_factor, long prec)
{
    arf_t err;
    arb_t t, u, v;
    int result;

    arf_init(err);
    arb_init(t);
    arb_init(u);
    arb_init(v);

    arf_set_mag(err, arb_radref(x));
    arf_mul(err, err, err, MAG_BITS, ARF_RND_UP);
    arf_mul(err, err, convergence_factor, MAG_BITS, ARF_RND_UP);

    arf_set(arb_midref(t), arb_midref(x));
    mag_zero(arb_radref(t));

    _arb_poly_evaluate2(u, v, poly, len, t, prec);

    arb_div(u, u, v, prec);
    arb_sub(u, t, u, prec);

    arb_add_error_arf(u, err);

    if (arb_contains(convergence_interval, u) &&
        (mag_cmp(arb_radref(u), arb_radref(x)) < 0))
    {
        arb_swap(xnew, u);
        result = 1;
    }
    else
    {
        arb_set(xnew, x);
        result = 0;
    }

    arb_clear(t);
    arb_clear(u);
    arb_clear(v);
    arf_clear(err);

    return result;
}
Пример #7
0
void
acb_lambertw_cleared_cut_fix_small(acb_t res, const acb_t z,
    const acb_t ez1, const fmpz_t k, int flags, slong prec)
{
    acb_t zz, zmid, zmide1;
    arf_t eps;

    acb_init(zz);
    acb_init(zmid);
    acb_init(zmide1);
    arf_init(eps);

    arf_mul_2exp_si(eps, arb_midref(acb_realref(z)), -prec);
    acb_set(zz, z);

    if (arf_sgn(arb_midref(acb_realref(zz))) < 0 &&
        (!fmpz_is_zero(k) || arf_sgn(arb_midref(acb_realref(ez1))) < 0) &&
        arf_cmpabs(arb_midref(acb_imagref(zz)), eps) < 0)
    {
        /* now the value must be in [0,2eps] */
        arf_get_mag(arb_radref(acb_imagref(zz)), eps);
        arf_set_mag(arb_midref(acb_imagref(zz)), arb_radref(acb_imagref(zz)));

        if (arf_sgn(arb_midref(acb_imagref(z))) >= 0)
        {
            acb_lambertw_cleared_cut(res, zz, k, flags, prec);
        }
        else
        {
            fmpz_t kk;
            fmpz_init(kk);
            fmpz_neg(kk, k);
            acb_lambertw_cleared_cut(res, zz, kk, flags, prec);
            acb_conj(res, res);
            fmpz_clear(kk);
        }
    }
    else
    {
        acb_lambertw_cleared_cut(res, zz, k, flags, prec);
    }

    acb_clear(zz);
    acb_clear(zmid);
    acb_clear(zmide1);
    arf_clear(eps);
}
Пример #8
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);
    }
}
Пример #9
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);
    }
}
Пример #10
0
slong
hypgeom_root_bound(const mag_t z, int r)
{
    if (r == 0)
    {
        return 0;
    }
    else
    {
        arf_t t;
        slong v;
        arf_init(t);
        arf_set_mag(t, z);
        arf_root(t, t, r, MAG_BITS, ARF_RND_UP);
        arf_add_ui(t, t, 1, MAG_BITS, ARF_RND_UP);
        v = arf_get_si(t, ARF_RND_UP);
        arf_clear(t);
        return v;
    }
}
Пример #11
0
void
arb_sqrtpos(arb_t z, const arb_t x, long prec)
{
    if (!arb_is_finite(x))
    {
        if (mag_is_zero(arb_radref(x)) && arf_is_pos_inf(arb_midref(x)))
            arb_pos_inf(z);
        else
            arb_zero_pm_inf(z);
    }
    else if (arb_contains_nonpositive(x))
    {
        arf_t t;

        arf_init(t);

        arf_set_mag(t, arb_radref(x));
        arf_add(t, arb_midref(x), t, MAG_BITS, ARF_RND_CEIL);

        if (arf_sgn(t) <= 0)
        {
            arb_zero(z);
        }
        else
        {
            arf_sqrt(t, t, MAG_BITS, ARF_RND_CEIL);
            arf_mul_2exp_si(t, t, -1);
            arf_set(arb_midref(z), t);
            arf_get_mag(arb_radref(z), t);
        }

        arf_clear(t);
    }
    else
    {
        arb_sqrt(z, x, prec);
    }

    arb_nonnegative_part(z, z, prec);
}
Пример #12
0
static void
bound_rfac(arb_ptr F, const acb_t s, ulong n, slong len, slong wp)
{
    if (len == 1)
    {
        acb_rising_ui_get_mag(arb_radref(F), s, n);
        arf_set_mag(arb_midref(F), arb_radref(F));
        mag_zero(arb_radref(F + 0));
    }
    else
    {
        arb_struct sx[2];
        arb_init(sx + 0);
        arb_init(sx + 1);
        acb_abs(sx + 0, s, wp);
        arb_one(sx + 1);
        _arb_vec_zero(F, len);
        _arb_poly_rising_ui_series(F, sx, 2, n, len, wp);
        arb_clear(sx + 0);
        arb_clear(sx + 1);
    }
}
int
acb_calc_integrate_taylor(acb_t res,
    acb_calc_func_t func, void * param,
    const acb_t a, const acb_t b,
    const arf_t inner_radius,
    const arf_t outer_radius,
    long accuracy_goal, long prec)
{
    long num_steps, step, N, bp;
    int result;

    acb_t delta, m, x, y1, y2, sum;
    acb_ptr taylor_poly;
    arf_t err;

    acb_init(delta);
    acb_init(m);
    acb_init(x);
    acb_init(y1);
    acb_init(y2);
    acb_init(sum);
    arf_init(err);

    acb_sub(delta, b, a, prec);

    /* precision used for bounds calculations */
    bp = MAG_BITS;

    /* compute the number of steps */
    {
        arf_t t;
        arf_init(t);
        acb_get_abs_ubound_arf(t, delta, bp);
        arf_div(t, t, inner_radius, bp, ARF_RND_UP);
        arf_mul_2exp_si(t, t, -1);
        num_steps = (long) (arf_get_d(t, ARF_RND_UP) + 1.0);
        /* make sure it's not something absurd */
        num_steps = FLINT_MIN(num_steps, 10 * prec);
        num_steps = FLINT_MAX(num_steps, 1);
        arf_clear(t);
    }

    result = ARB_CALC_SUCCESS;

    acb_zero(sum);

    for (step = 0; step < num_steps; step++)
    {
        /* midpoint of subinterval */
        acb_mul_ui(m, delta, 2 * step + 1, prec);
        acb_div_ui(m, m, 2 * num_steps, prec);
        acb_add(m, m, a, prec);

        if (arb_calc_verbose)
        {
            printf("integration point %ld/%ld: ", 2 * step + 1, 2 * num_steps);
            acb_printd(m, 15); printf("\n");
        }

        /* evaluate at +/- x */
        /* TODO: exactify m, and include error in x? */
        acb_div_ui(x, delta, 2 * num_steps, prec);

        /* compute bounds and number of terms to use */
        {
            arb_t cbound, xbound, rbound;
            arf_t C, D, R, X, T;
            double DD, TT, NN;

            arb_init(cbound);
            arb_init(xbound);
            arb_init(rbound);
            arf_init(C);
            arf_init(D);
            arf_init(R);
            arf_init(X);
            arf_init(T);

            /* R is the outer radius */
            arf_set(R, outer_radius);

            /* X = upper bound for |x| */
            acb_get_abs_ubound_arf(X, x, bp);
            arb_set_arf(xbound, X);

            /* Compute C(m,R). Important subtlety: due to rounding when
               computing m, we will in general be farther than R away from
               the integration path. But since acb_calc_cauchy_bound
               actually integrates over the area traced by a complex
               interval, it will catch any extra singularities (giving
               an infinite bound). */
            arb_set_arf(rbound, outer_radius);
            acb_calc_cauchy_bound(cbound, func, param, m, rbound, 8, bp);
            arf_set_mag(C, arb_radref(cbound));
            arf_add(C, arb_midref(cbound), C, bp, ARF_RND_UP);

            /* Sanity check: we need C < inf and R > X */
            if (arf_is_finite(C) && arf_cmp(R, X) > 0)
            {
                /* Compute upper bound for D = C * R * X / (R - X) */
                arf_mul(D, C, R, bp, ARF_RND_UP);
                arf_mul(D, D, X, bp, ARF_RND_UP);
                arf_sub(T, R, X, bp, ARF_RND_DOWN);
                arf_div(D, D, T, bp, ARF_RND_UP);

                /* Compute upper bound for T = (X / R) */
                arf_div(T, X, R, bp, ARF_RND_UP);

                /* Choose N */
                /* TODO: use arf arithmetic to avoid overflow */
                /* TODO: use relative accuracy (look at |f(m)|?) */
                DD = arf_get_d(D, ARF_RND_UP);
                TT = arf_get_d(T, ARF_RND_UP);
                NN = -(accuracy_goal * 0.69314718055994530942 + log(DD)) / log(TT);
                N = NN + 0.5;
                N = FLINT_MIN(N, 100 * prec);
                N = FLINT_MAX(N, 1);

                /* Tail bound: D / (N + 1) * T^N */
                {
                    mag_t TT;
                    mag_init(TT);
                    arf_get_mag(TT, T);
                    mag_pow_ui(TT, TT, N);
                    arf_set_mag(T, TT);
                    mag_clear(TT);
                }
                arf_mul(D, D, T, bp, ARF_RND_UP);
                arf_div_ui(err, D, N + 1, bp, ARF_RND_UP);
            }
            else
            {
                N = 1;
                arf_pos_inf(err);
                result = ARB_CALC_NO_CONVERGENCE;
            }

            if (arb_calc_verbose)
            {
                printf("N = %ld; bound: ", N); arf_printd(err, 15); printf("\n");
                printf("R: "); arf_printd(R, 15); printf("\n");
                printf("C: "); arf_printd(C, 15); printf("\n");
                printf("X: "); arf_printd(X, 15); printf("\n");
            }

            arb_clear(cbound);
            arb_clear(xbound);
            arb_clear(rbound);
            arf_clear(C);
            arf_clear(D);
            arf_clear(R);
            arf_clear(X);
            arf_clear(T);
        }

        /* evaluate Taylor polynomial */
        taylor_poly = _acb_vec_init(N + 1);
        func(taylor_poly, m, param, N, prec);
        _acb_poly_integral(taylor_poly, taylor_poly, N + 1, prec);
        _acb_poly_evaluate(y2, taylor_poly, N + 1, x, prec);
        acb_neg(x, x);
        _acb_poly_evaluate(y1, taylor_poly, N + 1, x, prec);
        acb_neg(x, x);

        /* add truncation error */
        arb_add_error_arf(acb_realref(y1), err);
        arb_add_error_arf(acb_imagref(y1), err);
        arb_add_error_arf(acb_realref(y2), err);
        arb_add_error_arf(acb_imagref(y2), err);

        acb_add(sum, sum, y2, prec);
        acb_sub(sum, sum, y1, prec);

        if (arb_calc_verbose)
        {
            printf("values:  ");
            acb_printd(y1, 15); printf("  ");
            acb_printd(y2, 15); printf("\n");
        }

        _acb_vec_clear(taylor_poly, N + 1);

        if (result == ARB_CALC_NO_CONVERGENCE)
            break;
    }

    acb_set(res, sum);

    acb_clear(delta);
    acb_clear(m);
    acb_clear(x);
    acb_clear(y1);
    acb_clear(y2);
    acb_clear(sum);
    arf_clear(err);

    return result;
}
Пример #14
0
void
arb_mul_naive(arb_t z, const arb_t x, const arb_t y, slong prec)
{
    arf_t zm_exact, zm_rounded, zr, t, u;

    arf_init(zm_exact);
    arf_init(zm_rounded);
    arf_init(zr);
    arf_init(t);
    arf_init(u);

    arf_mul(zm_exact, arb_midref(x), arb_midref(y), ARF_PREC_EXACT, ARF_RND_DOWN);
    arf_set_round(zm_rounded, zm_exact, prec, ARB_RND);

    /* rounding error */
    if (arf_equal(zm_exact, zm_rounded))
    {
        arf_zero(zr);
    }
    else
    {
        fmpz_t e;
        fmpz_init(e);

        /* more accurate, but not what we are testing
        arf_sub(zr, zm_exact, zm_rounded, MAG_BITS, ARF_RND_UP);
        arf_abs(zr, zr); */

        fmpz_sub_ui(e, ARF_EXPREF(zm_rounded), prec);
        arf_one(zr);
        arf_mul_2exp_fmpz(zr, zr, e);
        fmpz_clear(e);
    }

    /* propagated error */
    if (!arb_is_exact(x))
    {
        arf_set_mag(t, arb_radref(x));
        arf_abs(u, arb_midref(y));
        arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP);
    }

    if (!arb_is_exact(y))
    {
        arf_set_mag(t, arb_radref(y));
        arf_abs(u, arb_midref(x));
        arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP);
    }

    if (!arb_is_exact(x) && !arb_is_exact(y))
    {
        arf_set_mag(t, arb_radref(x));
        arf_set_mag(u, arb_radref(y));
        arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP);
    }

    arf_set(arb_midref(z), zm_rounded);
    arf_get_mag(arb_radref(z), zr);

    arf_clear(zm_exact);
    arf_clear(zm_rounded);
    arf_clear(zr);
    arf_clear(t);
    arf_clear(u);
}
Пример #15
0
void
bernoulli_rev_init(bernoulli_rev_t iter, ulong nmax)
{
    long j;
    fmpz_t t;
    arb_t x;
    arf_t u;
    int round1, round2;
    long wp;

    nmax -= (nmax % 2);
    iter->n = nmax;

    iter->alloc = 0;
    if (nmax < BERNOULLI_REV_MIN)
        return;

    iter->prec = wp = bernoulli_global_prec(nmax);

    iter->max_power = bernoulli_zeta_terms(nmax, iter->prec);
    iter->alloc = iter->max_power + 1;
    iter->powers = _fmpz_vec_init(iter->alloc);
    fmpz_init(iter->pow_error);
    arb_init(iter->prefactor);
    arb_init(iter->two_pi_squared);

    arb_init(x);
    fmpz_init(t);
    arf_init(u);

    /* precompute powers */
    for (j = 3; j <= iter->max_power; j += 2)
    {
        arb_ui_pow_ui(x, j, nmax, bernoulli_power_prec(j, nmax, wp));
        arb_inv(x, x, bernoulli_power_prec(j, nmax, wp));
        round1 = arf_get_fmpz_fixed_si(t, arb_midref(x), -wp);
        fmpz_set(iter->powers + j, t);

        /* error: the radius, plus two roundings */
        arf_set_mag(u, arb_radref(x));
        round2 = arf_get_fmpz_fixed_si(t, u, -wp);
        fmpz_add_ui(t, t, (round1 != 0) + (round2 != 0));
        if (fmpz_cmp(iter->pow_error, t) < 0)
            fmpz_set(iter->pow_error, t);
    }

    /* precompute (2pi)^2 and 2*(n!)/(2pi)^n */
    arb_fac_ui(iter->prefactor, nmax, wp);
    arb_mul_2exp_si(iter->prefactor, iter->prefactor, 1);

    arb_const_pi(x, wp);
    arb_mul_2exp_si(x, x, 1);
    arb_mul(iter->two_pi_squared, x, x, wp);

    arb_pow_ui(x, iter->two_pi_squared, nmax / 2, wp);
    arb_div(iter->prefactor, iter->prefactor, x, wp);

    fmpz_clear(t);
    arb_clear(x);
    arf_clear(u);
}
Пример #16
0
int main(int argc, char *argv[])
{
    slong i, len, prec, num_threads;
    char * out_file;
    arb_ptr z;

    if (argc < 2)
    {
        flint_printf("keiper_li n [-prec prec] [-threads num_threads] [-out out_file]\n");
        return 1;
    }

    len = atol(argv[1]) + 1;
    prec = 1.1 * len + 50;
    num_threads = 1;
    out_file = NULL;

    for (i = 1; i < argc; i++)
    {
        if (!strcmp(argv[i], "-prec"))
            prec = atol(argv[i+1]);
        else if (!strcmp(argv[i], "-threads"))
            num_threads = atol(argv[i+1]);
        else if (!strcmp(argv[i], "-out"))
            out_file = argv[i+1];
    }

    flint_set_num_threads(num_threads);

    z = _arb_vec_init(len);

    keiper_li_series(z, len, prec);

    for (i = 0; i < len; i++)
    {
        if (i <= 10 || len - i <= 10)
        {
            flint_printf("%wd: ", i); arb_printd(z + i, 50); flint_printf("\n");
        }
    }

    SHOW_MEMORY_USAGE

    if (out_file != NULL)
    {
        fmpz_t man, exp;
        arf_t t;

        FILE * fp = fopen(out_file, "w");

        fmpz_init(man);
        fmpz_init(exp);
        arf_init(t);

        for (i = 0; i < len; i++)
        {
            arf_get_fmpz_2exp(man, exp, arb_midref(z + i));

            flint_fprintf(fp, "%wd ", i);
            fmpz_fprint(fp, man);
            flint_fprintf(fp, " ");
            fmpz_fprint(fp, exp);
            flint_fprintf(fp, " ");

            arf_set_mag(t, arb_radref(z + i));
            arf_get_fmpz_2exp(man, exp, t);

            fmpz_fprint(fp, man);
            flint_fprintf(fp, " ");
            fmpz_fprint(fp, exp);
            flint_fprintf(fp, "\n");
        }

        fclose(fp);

        fmpz_clear(man);
        fmpz_clear(exp);
        arf_clear(t);
    }

    _arb_vec_clear(z, len);
    flint_cleanup();
    return 0;
}
Пример #17
0
int main()
{
    long iter;
    flint_rand_t state;

    printf("add_error....");
    fflush(stdout);

    flint_randinit(state);

    for (iter = 0; iter < 10000; iter++)
    {
        arb_t a, b, c;
        arf_t m, r;

        arb_init(a);
        arb_init(b);
        arb_init(c);
        arf_init(m);
        arf_init(r);

        arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10);
        arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10);
        arb_randtest_special(c, state, 1 + n_randint(state, 2000), 10);
        arf_randtest_special(m, state, 1 + n_randint(state, 2000), 10);
        arf_randtest_special(r, state, 1 + n_randint(state, 2000), 10);

        /* c = a plus error bounds */
        arb_set(c, a);
        arf_set(arb_midref(b), m);
        arf_get_mag(arb_radref(b), r);
        arb_add_error(c, b);

        /* b = a + random point */
        arb_set(b, a);

        if (n_randint(state, 2))
            arf_add(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN);
        else
            arf_sub(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN);

        if (n_randint(state, 2))
            arf_add(arb_midref(b), arb_midref(b), r, ARF_PREC_EXACT, ARF_RND_DOWN);
        else
            arf_sub(arb_midref(b), arb_midref(b), r, ARF_PREC_EXACT, ARF_RND_DOWN);

        /* should this be done differently? */
        if (arf_is_nan(arb_midref(b)))
            arf_zero(arb_midref(b));

        if (!arb_contains(c, b))
        {
            printf("FAIL (arb_add_error)\n\n");
            printf("a = "); arb_printn(a, 50, 0); printf("\n\n");
            printf("b = "); arb_printn(b, 50, 0); printf("\n\n");
            printf("c = "); arb_printn(c, 50, 0); printf("\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        arb_clear(c);
        arf_clear(m);
        arf_clear(r);
    }

    for (iter = 0; iter < 10000; iter++)
    {
        arb_t a, b, c;
        arf_t m;

        arb_init(a);
        arb_init(b);
        arb_init(c);
        arf_init(m);

        arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10);
        arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10);
        arb_randtest_special(c, state, 1 + n_randint(state, 2000), 10);
        arf_randtest_special(m, state, 1 + n_randint(state, 2000), 10);

        /* c = a plus error bounds */
        arb_set(c, a);
        arb_add_error_arf(c, m);

        /* b = a + random point */
        arb_set(b, a);

        if (n_randint(state, 2))
            arf_add(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN);
        else
            arf_sub(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN);

        /* should this be done differently? */
        if (arf_is_nan(arb_midref(b)))
            arf_zero(arb_midref(b));

        if (!arb_contains(c, b))
        {
            printf("FAIL (arb_add_error_arf)\n\n");
            printf("a = "); arb_printn(a, 50, 0); printf("\n\n");
            printf("b = "); arb_printn(b, 50, 0); printf("\n\n");
            printf("c = "); arb_printn(c, 50, 0); printf("\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        arb_clear(c);
        arf_clear(m);
    }

    for (iter = 0; iter < 10000; iter++)
    {
        arb_t a, b, c;
        arf_t t;
        mag_t r;

        arb_init(a);
        arb_init(b);
        arb_init(c);
        mag_init(r);
        arf_init(t);

        arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10);
        arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10);
        mag_randtest(r, state, 10);

        /* c = a plus error bounds */
        arb_set(c, a);
        arb_add_error_mag(c, r);

        /* b = a + random point */
        arb_set(b, a);
        arf_set_mag(t, r);
        if (n_randint(state, 2))
            arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN);
        else
            arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN);

        /* should this be done differently? */
        if (arf_is_nan(arb_midref(b)))
            arf_zero(arb_midref(b));

        if (!arb_contains(c, b))
        {
            printf("FAIL (arb_add_error_mag)\n\n");
            printf("a = "); arb_printn(a, 50, 0); printf("\n\n");
            printf("b = "); arb_printn(b, 50, 0); printf("\n\n");
            printf("c = "); arb_printn(c, 50, 0); printf("\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        arb_clear(c);
        mag_clear(r);
        arf_clear(t);
    }

    for (iter = 0; iter < 10000; iter++)
    {
        arb_t a, b, c;
        arf_t t;
        long e;

        arb_init(a);
        arb_init(b);
        arb_init(c);
        arf_init(t);

        arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10);
        arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10);
        e = n_randint(state, 10) - 10;

        /* c = a plus error bounds */
        arb_set(c, a);
        arb_add_error_2exp_si(c, e);

        /* b = a + random point */
        arb_set(b, a);
        arf_one(t);
        arf_mul_2exp_si(t, t, e);
        if (n_randint(state, 2))
            arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN);
        else
            arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN);

        /* should this be done differently? */
        if (arf_is_nan(arb_midref(b)))
            arf_zero(arb_midref(b));

        if (!arb_contains(c, b))
        {
            printf("FAIL (arb_add_error_2exp_si)\n\n");
            printf("a = "); arb_printn(a, 50, 0); printf("\n\n");
            printf("b = "); arb_printn(b, 50, 0); printf("\n\n");
            printf("c = "); arb_printn(c, 50, 0); printf("\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        arb_clear(c);
        arf_clear(t);
    }

    for (iter = 0; iter < 10000; iter++)
    {
        arb_t a, b, c;
        arf_t t;
        fmpz_t e;

        arb_init(a);
        arb_init(b);
        arb_init(c);
        arf_init(t);
        fmpz_init(e);

        arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10);
        arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10);
        fmpz_randtest(e, state, 10);

        /* c = a plus error bounds */
        arb_set(c, a);
        arb_add_error_2exp_fmpz(c, e);

        /* b = a + random point */
        arb_set(b, a);
        arf_one(t);
        arf_mul_2exp_fmpz(t, t, e);
        if (n_randint(state, 2))
            arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN);
        else
            arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN);

        /* should this be done differently? */
        if (arf_is_nan(arb_midref(b)))
            arf_zero(arb_midref(b));

        if (!arb_contains(c, b))
        {
            printf("FAIL (arb_add_error_2exp_fmpz)\n\n");
            printf("a = "); arb_printn(a, 50, 0); printf("\n\n");
            printf("b = "); arb_printn(b, 50, 0); printf("\n\n");
            printf("c = "); arb_printn(c, 50, 0); printf("\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        arb_clear(c);
        arf_clear(t);
        fmpz_clear(e);
    }

    flint_randclear(state);
    flint_cleanup();
    printf("PASS\n");
    return EXIT_SUCCESS;
}