Exemplo n.º 1
0
void
fmprb_mul_main_naive(fmprb_t z, const fmprb_t x, const fmprb_t y, slong prec)
{
    if (fmpr_is_pos_inf(fmprb_radref(x)) || fmpr_is_pos_inf(fmprb_radref(y)))
    {
        fmpr_mul(fmprb_midref(z), fmprb_midref(x), fmprb_midref(y), prec, FMPR_RND_DOWN);
        fmpr_pos_inf(fmprb_radref(z));
    }
    else
    {
        fmpr_t t, u;
        slong r;

        fmpr_init(t);
        fmpr_init(u);

        /* (x+a)*(y+b) = x*y + x*b + y*a + a*b*/

        fmpr_mul(t, fmprb_midref(x), fmprb_radref(y), FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_abs(t, t);

        fmpr_mul(u, fmprb_midref(y), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_abs(u, u);

        fmpr_add(t, t, u, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_addmul(t, fmprb_radref(x), fmprb_radref(y), FMPRB_RAD_PREC, FMPR_RND_UP);

        r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), fmprb_midref(y), prec, FMPR_RND_DOWN);
        fmpr_add_error_result(fmprb_radref(z), t,
            fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP);

        fmpr_clear(t);
        fmpr_clear(u);
    }
}
Exemplo n.º 2
0
void
fmprb_mul_fmpr_naive(fmprb_t z, const fmprb_t x, const fmpr_t y, slong prec)
{
    /* (x+a) * y = x*y + y*a */
    if (fmpr_is_pos_inf(fmprb_radref(x)))
    {
        fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN);
        fmpr_pos_inf(fmprb_radref(z));
    }
    else if (fmpr_is_zero(fmprb_radref(x)))
    {
        slong r;

        r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN);
        fmpr_set_error_result(fmprb_radref(z), fmprb_midref(z), r);
    }
    else
    {
        slong r;

        fmpr_mul(fmprb_radref(z), fmprb_radref(x), y, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_abs(fmprb_radref(z), fmprb_radref(z));

        r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN);
        fmpr_add_error_result(fmprb_radref(z), fmprb_radref(z),
            fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP);
    }
}
Exemplo n.º 3
0
Arquivo: sqrt.c Projeto: isuruf/arb
void
fmprb_sqrt(fmprb_t z, const fmprb_t x, slong prec)
{
    slong r;

    if (fmprb_contains_negative(x))
    {
        fmpr_nan(fmprb_midref(z));
        fmpr_pos_inf(fmprb_radref(z));
        return;
    }

    if (fmprb_is_exact(x))
    {
        r = fmpr_sqrt(fmprb_midref(z), fmprb_midref(x), prec, FMPR_RND_DOWN);
        fmpr_set_error_result(fmprb_radref(z), fmprb_midref(z), r);
    }
    else
    {
        fmpr_t err;
        fmpr_init(err);
        fmpr_sub(err, fmprb_midref(x), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_DOWN);
        fmpr_rsqrt(err, err, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_mul(err, fmprb_radref(x), err, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_mul_2exp_si(err, err, -1);

        r = fmpr_sqrt(fmprb_midref(z), fmprb_midref(x), prec, FMPR_RND_DOWN);
        fmpr_add_error_result(fmprb_radref(z), err, fmprb_midref(z), r,
            FMPRB_RAD_PREC, FMPR_RND_UP);

        fmpr_clear(err);
    }

    fmprb_adjust(z);
}
Exemplo n.º 4
0
void
gamma_taylor_bound_remainder(fmpr_t err, const fmpr_t z, long n)
{
    fmpr_t t, u;

    gamma_taylor_bound_extend_cache(n + 1);

    fmpr_init(t);
    fmpr_init(u);

    /* denominator: 1 - r(n+1) * z, rounded down */
    fmpr_mul(t, gamma_taylor_bound_ratio_cache + n + 1,
        z, FMPRB_RAD_PREC, FMPR_RND_UP);
    fmpr_one(u);
    fmpr_sub(u, u, t, FMPRB_RAD_PREC, FMPR_RND_DOWN);

    if (fmpr_sgn(u) <= 0)
    {
        fmpr_pos_inf(err);
    }
    else
    {
        fmpr_pow_sloppy_ui(t, z, n, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_mul_2exp_si(t, t, gamma_taylor_bound_mag_cache[n + 1]);
        fmpr_div(err, t, u, FMPRB_RAD_PREC, FMPR_RND_UP);
    }

    fmpr_clear(t);
    fmpr_clear(u);
}
Exemplo n.º 5
0
static __inline__ void
fmpcb_inv_mid(fmpcb_t z, const fmpcb_t x, long prec)
{
    fmpr_t t;
    fmpr_init(t);

#define a fmprb_midref(fmpcb_realref(x))
#define b fmprb_midref(fmpcb_imagref(x))
#define e fmprb_midref(fmpcb_realref(z))
#define f fmprb_midref(fmpcb_imagref(z))

    fmpr_mul(t, a, a, prec, FMPR_RND_DOWN);
    fmpr_addmul(t, b, b, prec, FMPR_RND_DOWN);

    fmpr_div(e, a, t, prec, FMPR_RND_DOWN);
    fmpr_div(f, b, t, prec, FMPR_RND_DOWN);

    fmpr_neg(f, f);

#undef a
#undef b
#undef e
#undef f

    fmpr_clear(t);
}
Exemplo n.º 6
0
void
fmpr_pow_sloppy_fmpz(fmpr_t y, const fmpr_t b, const fmpz_t e,
    long prec, fmpr_rnd_t rnd)
{
    long i, wp, bits;

    if (fmpz_is_zero(e))
    {
        fmpr_set_ui(y, 1UL);
        return;
    }

    if (fmpz_sgn(e) < 0)
    {
        fmpz_t f;
        fmpz_init(f);
        fmpz_neg(f, e);
        fmpr_pow_sloppy_fmpz(y, b, f, prec + 2,
            (rnd == FMPR_RND_FLOOR || rnd == FMPR_RND_DOWN)
            ? FMPR_RND_UP : FMPR_RND_DOWN);
        fmpr_ui_div(y, 1UL, y, prec, rnd);
        fmpz_clear(f);
    }

    if (y == b)
    {
        fmpr_t t;
        fmpr_init(t);
        fmpr_set(t, b);
        fmpr_pow_sloppy_fmpz(y, t, e, prec, rnd);
        fmpr_clear(t);
        return;
    }

    fmpr_set(y, b);

    bits = fmpz_bits(e);
    wp = FMPR_PREC_ADD(prec, bits);

    for (i = bits - 2; i >= 0; i--)
    {
        fmpr_mul(y, y, y, wp, rnd);
        if (fmpz_tstbit(e, i))
            fmpr_mul(y, y, b, wp, rnd);
    }
}
Exemplo n.º 7
0
static slong
fmpr_mul_si_naive(fmpr_t z, const fmpr_t x, slong y, slong prec, fmpr_rnd_t rnd)
{
    fmpr_t t; slong r;
    fmpr_init(t);
    fmpr_set_si(t, y);
    r = fmpr_mul(z, x, t, prec, rnd);
    fmpr_clear(t);
    return r;
}
Exemplo n.º 8
0
slong
fmpr_submul(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd)
{
    fmpr_t t;
    slong r;
    fmpr_init(t);
    fmpr_mul(t, x, y, FMPR_PREC_EXACT, FMPR_RND_DOWN);
    r = fmpr_sub(z, z, t, prec, rnd);
    fmpr_clear(t);
    return r;
}
Exemplo n.º 9
0
/* Absolute value of rising factorial (could speed up once complex gamma is available). */
void
fmpcb_rfac_abs_ubound2(fmpr_t bound, const fmpcb_t s, ulong n, long prec)
{
    fmpr_t term, t;
    ulong k;

    /* M(k) = (a+k)^2 + b^2
       M(0) = a^2 + b^2
       M(k+1) = M(k) + 2*a + (2*k+1)
    */
    fmpr_init(t);
    fmpr_init(term);

    fmpr_one(bound);

    /* M(0) = a^2 + b^2 */
    fmprb_get_abs_ubound_fmpr(t, fmpcb_realref(s), prec);
    fmpr_mul(term, t, t, prec, FMPR_RND_UP);
    fmprb_get_abs_ubound_fmpr(t, fmpcb_imagref(s), prec);
    fmpr_mul(t, t, t, prec, FMPR_RND_UP);
    fmpr_add(term, term, t, prec, FMPR_RND_UP);

    /* we add t = 2*a to each term. note that this can be signed;
       we always want the most positive value */
    fmpr_add(t, fmprb_midref(fmpcb_realref(s)),
        fmprb_radref(fmpcb_realref(s)), prec, FMPR_RND_CEIL);
    fmpr_mul_2exp_si(t, t, 1);

    for (k = 0; k < n; k++)
    {
        fmpr_mul(bound, bound, term, prec, FMPR_RND_UP);
        fmpr_add_ui(term, term, 2 * k + 1, prec, FMPR_RND_UP);
        fmpr_add(term, term, t, prec, FMPR_RND_UP);
    }

    fmpr_sqrt(bound, bound, prec, FMPR_RND_UP);

    fmpr_clear(t);
    fmpr_clear(term);
}
Exemplo n.º 10
0
static __inline__ void
fmpcb_mul_mid(fmpcb_t z, const fmpcb_t x, const fmpcb_t y, long prec)
{
#define a fmprb_midref(fmpcb_realref(x))
#define b fmprb_midref(fmpcb_imagref(x))
#define c fmprb_midref(fmpcb_realref(y))
#define d fmprb_midref(fmpcb_imagref(y))
#define e fmprb_midref(fmpcb_realref(z))
#define f fmprb_midref(fmpcb_imagref(z))

    fmpr_t t, u, v;

    fmpr_init(t);
    fmpr_init(u);
    fmpr_init(v);

    fmpr_add(t, a, b, prec, FMPR_RND_DOWN);
    fmpr_add(u, c, d, prec, FMPR_RND_DOWN);
    fmpr_mul(v, t, u, prec, FMPR_RND_DOWN);

    fmpr_mul(t, a, c, prec, FMPR_RND_DOWN);
    fmpr_mul(u, b, d, prec, FMPR_RND_DOWN);

    fmpr_sub(e, t, u, prec, FMPR_RND_DOWN);
    fmpr_sub(f, v, t, prec, FMPR_RND_DOWN);
    fmpr_sub(f, f, u, prec, FMPR_RND_DOWN);

    fmpr_clear(t);
    fmpr_clear(u);
    fmpr_clear(v);

#undef a
#undef b
#undef c
#undef d
#undef e
#undef f
}
Exemplo n.º 11
0
Arquivo: sum.c Projeto: bluescarni/arb
void
fmprb_hypgeom_infsum(fmprb_t P, fmprb_t Q, hypgeom_t hyp, long target_prec, long prec)
{
    mag_t err, z;
    long n;

    mag_init(err);
    mag_init(z);

    mag_set_fmpz(z, hyp->P->coeffs + hyp->P->length - 1);
    mag_div_fmpz(z, z, hyp->Q->coeffs + hyp->Q->length - 1);

    if (!hyp->have_precomputed)
    {
        hypgeom_precompute(hyp);
        hyp->have_precomputed = 1;
    }

    n = hypgeom_bound(err, hyp->r, hyp->boundC, hyp->boundD,
        hyp->boundK, hyp->MK, z, target_prec);

    fmprb_hypgeom_sum(P, Q, hyp, n, prec);

    if (fmpr_sgn(fmprb_midref(Q)) < 0)
    {
        fmprb_neg(P, P);
        fmprb_neg(Q, Q);
    }

    /* We have p/q = s + err i.e. (p + q*err)/q = s */
    {
        fmpr_t u, v;
        fmpr_init(u);
        fmpr_init(v);
        mag_get_fmpr(v, err);
        fmpr_add(u, fmprb_midref(Q), fmprb_radref(Q), FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_mul(u, u, v, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmprb_add_error_fmpr(P, u);
        fmpr_clear(u);
        fmpr_clear(v);
    }

    mag_clear(z);
    mag_clear(err);
}
Exemplo n.º 12
0
Arquivo: det.c Projeto: certik/arb
void
fmprb_mat_det_inplace(fmprb_t det, fmprb_mat_t A, long prec)
{
    long i, n, sign, rank;

    n = fmprb_mat_nrows(A);
    rank = fmprb_mat_gauss_partial(A, prec);
    sign = (rank < 0) ? -1 : 1;
    rank = FLINT_ABS(rank);

    fmprb_set_si(det, sign);
    for (i = 0; i < rank; i++)
        fmprb_mul(det, det, fmprb_mat_entry(A, i, i), prec);

    /* bound unreduced part using Hadamard's inequality */
    if (rank < n)
    {
        fmpr_t t;
        fmprb_t d;

        fmpr_init(t);
        fmprb_init(d);

        fmpr_one(fmprb_radref(d));

        for (i = rank; i < n; i++)
        {
            fmprb_vec_get_fmpr_2norm_squared_bound(t, A->rows[i] + rank, 
                n - rank, FMPRB_RAD_PREC);
            fmpr_mul(fmprb_radref(d), fmprb_radref(d), t, FMPRB_RAD_PREC, FMPR_RND_UP);
        }

        fmpr_sqrt(fmprb_radref(d), fmprb_radref(d), FMPRB_RAD_PREC, FMPR_RND_UP);
        fmprb_mul(det, det, d, prec);

        fmprb_clear(d);
        fmpr_clear(t);
    }
}
Exemplo n.º 13
0
void _fmprb_poly_mullow_ztrunc(fmprb_ptr C,
    fmprb_srcptr A, long lenA,
    fmprb_srcptr B, long lenB, long n, long prec)
{
    fmpz * Acoeffs, * Bcoeffs, * Ccoeffs;
    fmpz_t Aexp, Bexp, Cexp;
    fmpr_t Aerr, Berr, Anorm, Bnorm, err;
    long i;
    int squaring;

    lenA = FLINT_MIN(lenA, n);
    lenB = FLINT_MIN(lenB, n);

    squaring = (A == B) && (lenA == lenB);

    /* TODO: make the code below work correctly with out this workaround */
    if (_fmprb_vec_rad_has_inf_nan(A, lenA) ||
        (!squaring && _fmprb_vec_rad_has_inf_nan(B, lenB)))
    {
        _fmprb_vec_indeterminate(C, n);
        return;
    }

    fmpz_init(Aexp);
    fmpz_init(Bexp);
    fmpz_init(Cexp);

    Acoeffs = _fmpz_vec_init(lenA);
    Bcoeffs = _fmpz_vec_init(lenB);
    Ccoeffs = _fmpz_vec_init(n);

    fmpr_init(Aerr);
    fmpr_init(Berr);
    fmpr_init(Anorm);
    fmpr_init(Bnorm);
    fmpr_init(err);

    _fmprb_poly_get_fmpz_poly_2exp(Aerr, Aexp, Acoeffs, A, lenA, prec);

    if (squaring)
    {
        _fmpz_poly_sqrlow(Ccoeffs, Acoeffs, lenA, n);
        fmpz_add(Cexp, Aexp, Aexp);

        /* cross-multiply error bounds: (A+r)(B+s) = A^2 + 2Ar + r^2 */
        _fmpr_fmpz_vec_max_norm(Anorm, Acoeffs, lenA, FMPRB_RAD_PREC);
        fmpr_mul_2exp_fmpz(Anorm, Anorm, Aexp);

        fmpr_mul(err, Anorm, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_mul_2exp_si(err, err, 1);
        fmpr_addmul(err, Aerr, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP);
    }
    else
    {
        _fmprb_poly_get_fmpz_poly_2exp(Berr, Bexp, Bcoeffs, B, lenB, prec);

        /* main multiplication */
        if (lenA >= lenB)
            _fmpz_poly_mullow(Ccoeffs, Acoeffs, lenA, Bcoeffs, lenB, n);
        else
            _fmpz_poly_mullow(Ccoeffs, Bcoeffs, lenB, Acoeffs, lenA, n);

        fmpz_add(Cexp, Aexp, Bexp);

        /* cross-multiply error bounds: (A+r)(B+s) = AB + As + Br + rs */
        _fmpr_fmpz_vec_max_norm(Anorm, Acoeffs, lenA, FMPRB_RAD_PREC);
        fmpr_mul_2exp_fmpz(Anorm, Anorm, Aexp);

        _fmpr_fmpz_vec_max_norm(Bnorm, Bcoeffs, lenB, FMPRB_RAD_PREC);
        fmpr_mul_2exp_fmpz(Bnorm, Bnorm, Bexp);

        fmpr_mul(err, Aerr, Berr, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_addmul(err, Anorm, Berr, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_addmul(err, Bnorm, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP);
    }

    for (i = 0; i < n; i++)
    {
        fmprb_set_round_fmpz_2exp(C + i, Ccoeffs + i, Cexp, prec);

        /* there are at most (i+1) error terms for coefficient i */
        /* TODO: make this tight */
        fmpr_addmul_ui(fmprb_radref(C + i), err, i + 1,
            FMPRB_RAD_PREC, FMPR_RND_UP);
    }

    fmpr_clear(Aerr);
    fmpr_clear(Berr);
    fmpr_clear(Anorm);
    fmpr_clear(Bnorm);
    fmpr_clear(err);

    _fmpz_vec_clear(Acoeffs, lenA);
    _fmpz_vec_clear(Bcoeffs, lenB);
    _fmpz_vec_clear(Ccoeffs, n);

    fmpz_clear(Aexp);
    fmpz_clear(Bexp);
    fmpz_clear(Cexp);
}
Exemplo n.º 14
0
Arquivo: t-mul.c Projeto: jdemeyer/arb
int main()
{
    long iter, iter2;
    flint_rand_t state;

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

    flint_randinit(state);

    for (iter = 0; iter < 10000; iter++)
    {
        fmpr_t x, y, z, v;
        long prec, r1, r2;
        fmpr_rnd_t rnd;

        fmpr_init(x);
        fmpr_init(y);
        fmpr_init(z);
        fmpr_init(v);

        for (iter2 = 0; iter2 < 100; iter2++)
        {
            fmpr_randtest_special(x, state, 2000, 200);
            fmpr_randtest_special(y, state, 2000, 200);
            prec = 2 + n_randint(state, 2000);

            switch (n_randint(state, 4))
            {
            case 0:
                rnd = FMPR_RND_DOWN;
                break;
            case 1:
                rnd = FMPR_RND_UP;
                break;
            case 2:
                rnd = FMPR_RND_FLOOR;
                break;
            default:
                rnd = FMPR_RND_CEIL;
                break;
            }

            switch (n_randint(state, 5))
            {
            case 0:
                r1 = fmpr_mul(z, x, y, prec, rnd);
                r2 = fmpr_mul_naive(v, x, y, prec, rnd);
                if (!fmpr_equal(z, v) || r1 != r2 || !fmpr_check_ulp(z, r1, prec))
                {
                    printf("FAIL!\n");
                    printf("x = ");
                    fmpr_print(x);
                    printf("\n\n");
                    printf("y = ");
                    fmpr_print(y);
                    printf("\n\n");
                    printf("z = ");
                    fmpr_print(z);
                    printf("\n\n");
                    printf("v = ");
                    fmpr_print(v);
                    printf("\n\n");
                    printf("r1 = %ld, r2 = %ld\n", r1, r2);
                    abort();
                }
                break;

            case 1:
                r1 = fmpr_mul(z, x, x, prec, rnd);
                r2 = fmpr_mul_naive(v, x, x, prec, rnd);
                if (!fmpr_equal(z, v) || r1 != r2 || !fmpr_check_ulp(z, r1, prec))
                {
                    printf("FAIL (aliasing 1)!\n");
                    printf("x = ");
                    fmpr_print(x);
                    printf("\n\n");
                    printf("z = ");
                    fmpr_print(z);
                    printf("\n\n");
                    printf("v = ");
                    fmpr_print(v);
                    printf("\n\n");
                    printf("r1 = %ld, r2 = %ld\n", r1, r2);
                    abort();
                }
                break;

            case 2:
                r2 = fmpr_mul_naive(v, x, x, prec, rnd);
                r1 = fmpr_mul(x, x, x, prec, rnd);
                if (!fmpr_equal(v, x) || r1 != r2 || !fmpr_check_ulp(x, r1, prec))
                {
                    printf("FAIL (aliasing 2)!\n");
                    printf("x = ");
                    fmpr_print(x);
                    printf("\n\n");
                    printf("z = ");
                    fmpr_print(z);
                    printf("\n\n");
                    printf("v = ");
                    fmpr_print(v);
                    printf("\n\n");
                    printf("r1 = %ld, r2 = %ld\n", r1, r2);
                    abort();
                }
                break;

            case 3:
                r2 = fmpr_mul_naive(v, x, y, prec, rnd);
                r1 = fmpr_mul(x, x, y, prec, rnd);
                if (!fmpr_equal(x, v) || r1 != r2 || !fmpr_check_ulp(x, r1, prec))
                {
                    printf("FAIL (aliasing 3)!\n");
                    printf("x = ");
                    fmpr_print(x);
                    printf("\n\n");
                    printf("y = ");
                    fmpr_print(y);
                    printf("\n\n");
                    printf("v = ");
                    fmpr_print(v);
                    printf("\n\n");
                    printf("r1 = %ld, r2 = %ld\n", r1, r2);
                    abort();
                }
                break;

            default:
                r2 = fmpr_mul_naive(v, x, y, prec, rnd);
                r1 = fmpr_mul(x, y, x, prec, rnd);
                if (!fmpr_equal(x, v) || r1 != r2 || !fmpr_check_ulp(x, r1, prec))
                {
                    printf("FAIL (aliasing 4)!\n");
                    printf("x = ");
                    fmpr_print(x);
                    printf("\n\n");
                    printf("y = ");
                    fmpr_print(y);
                    printf("\n\n");
                    printf("v = ");
                    fmpr_print(v);
                    printf("\n\n");
                    printf("r1 = %ld, r2 = %ld\n", r1, r2);
                    abort();
                }
                break;
            }
        }

        fmpr_clear(x);
        fmpr_clear(y);
        fmpr_clear(z);
        fmpr_clear(v);
    }

    flint_randclear(state);
    flint_cleanup();
    printf("PASS\n");
    return EXIT_SUCCESS;
}
Exemplo n.º 15
0
int main()
{
    slong iter;
    flint_rand_t state;

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

    flint_randinit(state);

    for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++)
    {
        slong bits;
        ulong k;
        fmpr_t x, z, w;
        mpfr_t X, Z;

        bits = 2 + n_randint(state, 200);
        k = 1 + n_randint(state, 20);

        fmpr_init(x);
        fmpr_init(z);
        fmpr_init(w);

        mpfr_init2(X, k * (bits + 100));
        mpfr_init2(Z, bits);

        fmpr_randtest_special(x, state, bits + n_randint(state, 100), 10);
        fmpr_abs(x, x);
        fmpr_randtest_special(z, state, bits + n_randint(state, 100), 10);

        /* occasionally produce perfect powers */
        if (n_randint(state, 4) == 0)
            fmpr_mul(x, x, x, k * bits, FMPR_RND_DOWN);

        fmpr_get_mpfr(X, x, MPFR_RNDN);

        switch (n_randint(state, 4))
        {
            case 0:
                mpfr_root(Z, X, k, MPFR_RNDZ);
                fmpr_root(z, x, k, bits, FMPR_RND_DOWN);
                break;
            case 1:
                mpfr_root(Z, X, k, MPFR_RNDA);
                fmpr_root(z, x, k, bits, FMPR_RND_UP);
                break;
            case 2:
                mpfr_root(Z, X, k, MPFR_RNDD);
                fmpr_root(z, x, k, bits, FMPR_RND_FLOOR);
                break;
            case 3:
                mpfr_root(Z, X, k, MPFR_RNDU);
                fmpr_root(z, x, k, bits, FMPR_RND_CEIL);
                break;
        }

        fmpr_set_mpfr(w, Z);

        if (!fmpr_equal(z, w))
        {
            flint_printf("FAIL\n\n");
            flint_printf("bits = %wd, k = %wu\n", bits, k);
            flint_printf("x = "); fmpr_print(x); flint_printf("\n\n");
            flint_printf("z = "); fmpr_print(z); flint_printf("\n\n");
            flint_printf("w = "); fmpr_print(w); flint_printf("\n\n");
            abort();
        }

        fmpr_clear(x);
        fmpr_clear(z);
        fmpr_clear(w);

        mpfr_clear(X);
        mpfr_clear(Z);
    }

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