Ejemplo n.º 1
0
Archivo: sub.c Proyecto: isuruf/arb
int
arf_sub_special(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd)
{
    if (arf_is_zero(x))
    {
        if (arf_is_zero(y))
        {
            arf_zero(z);
            return 0;
        }
        else
            return arf_neg_round(z, y, prec, rnd);
    }
    else if (arf_is_zero(y))
    {
        return arf_set_round(z, x, prec, rnd);
    }
    else if (arf_is_nan(x) || arf_is_nan(y)
        || (arf_is_pos_inf(x) && arf_is_pos_inf(y))
        || (arf_is_neg_inf(x) && arf_is_neg_inf(y)))
    {
        arf_nan(z);
        return 0;
    }
    else if (arf_is_special(x))
    {
        arf_set(z, x);
        return 0;
    }
    else
    {
        arf_neg(z, y);
        return 0;
    }
}
Ejemplo n.º 2
0
void arf_twobytwo_diag(arf_t u1, arf_t u2, const arf_t a, const arf_t b, const arf_t d, slong prec) {
    // Compute the orthogonal matrix that diagonalizes
    //
    //    A = [a b]
    //        [b d]
    //
    // This matrix will have the form
    //
    //    U = [cos x , -sin x]
    //        [sin x, cos x]
    //
    // where the diagonal matrix is U^t A U.
    // We set u1 = cos x, u2 = -sin x.

    if(arf_is_zero(b)) {
        arf_set_ui(u1, 1);
        arf_set_ui(u2, 0);
        return;
    }
    arf_t x; arf_init(x);

    arf_mul(u1, b, b, prec, ARF_RND_NEAR);            // u1 = b^2
    arf_sub(u2, a, d, prec, ARF_RND_NEAR);            // u2 = a - d
    arf_mul_2exp_si(u2, u2, -1);                      // u2 = (a - d)/2
    arf_mul(u2, u2, u2, prec, ARF_RND_NEAR);          // u2 = ( (a - d)/2 )^2
    arf_add(u1, u1, u2, prec, ARF_RND_NEAR);          // u1 = b^2 + ( (a-d)/2 )^2
    arf_sqrt(u1, u1, prec, ARF_RND_NEAR);             // u1 = sqrt(above)

    arf_mul_2exp_si(u1, u1, 1);                       // u1 = 2 (sqrt (above) )
    arf_add(u1, u1, d, prec, ARF_RND_NEAR);           // u1 += d
    arf_sub(u1, u1, a, prec, ARF_RND_NEAR);           // u1 -= a
    arf_mul_2exp_si(u1, u1, -1);                      // u1 = (d - a)/2 + sqrt(b^2 + ( (a-d)/2 )^2)

    arf_mul(x, u1, u1, prec, ARF_RND_NEAR);
    arf_addmul(x, b, b, prec, ARF_RND_NEAR);          // x = u1^2 + b^2
    arf_sqrt(x, x, prec, ARF_RND_NEAR);               // x = sqrt(u1^2 + b^2)
    arf_div(u2, u1, x, prec, ARF_RND_NEAR);
    arf_div(u1, b, x, prec, ARF_RND_NEAR);
    arf_neg(u1, u1);

    arf_clear(x);
}
void
_acb_poly_reciprocal_majorant(arb_ptr res, acb_srcptr vec, long len, long prec)
{
    long i;

    for (i = 0; i < len; i++)
    {
        if (i == 0)
        {
            acb_get_abs_lbound_arf(arb_midref(res + i), vec + i, prec);
            mag_zero(arb_radref(res + i));
        }
        else
        {
            acb_get_abs_ubound_arf(arb_midref(res + i), vec + i, prec);
            arf_neg(arb_midref(res + i), arb_midref(res + i));
            mag_zero(arb_radref(res + i));
        }
    }
}
Ejemplo n.º 4
0
int main()
{
    slong iter;
    flint_rand_t state;

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

    flint_randinit(state);

    for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++)
    {
        fmpq_t x, y;
        psl2z_t g;
        arf_t one_minus_eps, tol;
        acb_t z, w, w2;
        arb_t t;
        slong prec;

        fmpq_init(x);
        fmpq_init(y);

        psl2z_init(g);
        acb_init(z);
        acb_init(w);
        acb_init(w2);
        arf_init(one_minus_eps);
        arf_init(tol);
        arb_init(t);

        /* pick an exact point in the upper half plane */
        fmpq_randtest(x, state, 1 + n_randint(state, 500));
        do {
            fmpq_randtest(y, state, 1 + n_randint(state, 500));
        } while (fmpz_sgn(fmpq_numref(y)) <= 0);

        /* pick a tolerance */
        arf_set_ui_2exp_si(tol, 1, -(slong) n_randint(state, 500));

        /* now increase the precision until convergence */
        for (prec = 32; ; prec *= 2)
        {
            if (prec > 16384)
            {
                flint_printf("FAIL (no convergence)\n");
                flint_printf("x = "); fmpq_print(x); flint_printf("\n\n");
                flint_printf("y = "); fmpq_print(y); flint_printf("\n\n");
                flint_printf("z = "); acb_printd(z, 50); flint_printf("\n\n");
                flint_printf("w = "); acb_printd(w, 50); flint_printf("\n\n");
                flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n");
                flint_printf("g = "); psl2z_print(g); flint_printf("\n\n");
                abort();
            }

            arb_set_fmpq(acb_realref(z), x, prec);
            arb_set_fmpq(acb_imagref(z), y, prec);

            arf_set_ui_2exp_si(one_minus_eps, 1, -prec / 4);
            arf_sub_ui(one_minus_eps, one_minus_eps, 1, prec, ARF_RND_DOWN);
            arf_neg(one_minus_eps, one_minus_eps);

            acb_modular_fundamental_domain_approx(w, g, z, one_minus_eps, prec);
            acb_modular_transform(w2, g, z, prec);

            if (!psl2z_is_correct(g) || !acb_overlaps(w, w2))
            {
                flint_printf("FAIL (incorrect transformation)\n");
                flint_printf("x = "); fmpq_print(x); flint_printf("\n\n");
                flint_printf("y = "); fmpq_print(y); flint_printf("\n\n");
                flint_printf("z = "); acb_printd(z, 50); flint_printf("\n\n");
                flint_printf("w = "); acb_printd(w, 50); flint_printf("\n\n");
                flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n");
                flint_printf("g = "); psl2z_print(g); flint_printf("\n\n");
                abort();
            }

            /* success */
            if (acb_modular_is_in_fundamental_domain(w, tol, prec))
                break;
        }

        /* check that g^(-1) * w contains x+yi */
        psl2z_inv(g, g);
        acb_modular_transform(w2, g, w, 2 + n_randint(state, 1000));
        if (!arb_contains_fmpq(acb_realref(w2), x) ||
            !arb_contains_fmpq(acb_imagref(w2), y))
        {
            flint_printf("FAIL (inverse containment)\n");
            flint_printf("x = "); fmpq_print(x); flint_printf("\n\n");
            flint_printf("y = "); fmpq_print(y); flint_printf("\n\n");
            flint_printf("z = "); acb_printd(z, 50); flint_printf("\n\n");
            flint_printf("w = "); acb_printd(w, 50); flint_printf("\n\n");
            flint_printf("w2 = "); acb_printd(w2, 50); flint_printf("\n\n");
            flint_printf("g = "); psl2z_print(g); flint_printf("\n\n");
            abort();
        }

        fmpq_clear(x);
        fmpq_clear(y);

        psl2z_clear(g);
        acb_clear(z);
        acb_clear(w);
        acb_clear(w2);
        arf_clear(one_minus_eps);
        arf_clear(tol);
        arb_clear(t);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
Ejemplo n.º 5
0
int arb_mat_jacobi(arb_mat_t D, arb_mat_t P, const arb_mat_t A, slong prec) {
    //
    // Given a d x d real symmetric matrix A, compute an orthogonal matrix
    // P and a diagonal D such that A = P D P^t = P D P^(-1).
    //
    // D should have already been initialized as a d x 1 matrix, and Pp
    // should have already been initialized as a d x d matrix.
    //
    // If the eigenvalues can be certified as unique, then a nonzero int is
    // returned, and the eigenvectors should have reasonable error bounds. If
    // the eigenvalues cannot be certified as unique, then some of the
    // eigenvectors will have infinite error radius.

#define B(i,j) arb_mat_entry(B, i, j)
#define D(i) arb_mat_entry(D, i, 0)
#define P(i,j) arb_mat_entry(P, i, j)
    int dim = arb_mat_nrows(A);
    if(dim == 1) {
        arb_mat_set(D, A);
        arb_mat_one(P);
        return 0;
    }
    arb_mat_t B;
    arb_mat_init(B, dim, dim);

    arf_t * B1 = (arf_t*)malloc(dim * sizeof(arf_t));
    arf_t * B2 = (arf_t*)malloc(dim * sizeof(arf_t));
    arf_t * row_max = (arf_t*)malloc((dim - 1) * sizeof(arf_t));
    int * row_max_indices = (int*)malloc((dim - 1) * sizeof(int));

    for(int k = 0; k < dim; k++) {
        arf_init(B1[k]);
        arf_init(B2[k]);
    }
    for(int k = 0; k < dim - 1; k++) {
        arf_init(row_max[k]);
    }

    arf_t x1, x2;
    arf_init(x1);
    arf_init(x2);

    arf_t Gii, Gij, Gji, Gjj;
    arf_init(Gii);
    arf_init(Gij);
    arf_init(Gji);
    arf_init(Gjj);

    arb_mat_set(B, A);
    arb_mat_one(P);

    for(int i = 0; i < dim - 1; i++) {
        for(int j = i + 1; j < dim; j++) {
            arf_abs(x1, arb_midref(B(i,j)));
            if(arf_cmp(row_max[i], x1) < 0) {
                arf_set(row_max[i], x1);
                row_max_indices[i] = j;
            }
        }
    }


    int finished = 0;

    while(!finished) {
        arf_zero(x1);
        int i = 0;
        int j = 0;
        for(int k = 0; k < dim - 1; k++) {
            if(arf_cmp(x1, row_max[k]) < 0) {
                arf_set(x1, row_max[k]);
                i = k;
            }
        }
        j = row_max_indices[i];

        slong bound = arf_abs_bound_lt_2exp_si(x1);
        if(bound < -prec * .9) {
            finished = 1;
            break;
        }
        else {
            //printf("%ld\n", arf_abs_bound_lt_2exp_si(x1));
            //arb_mat_printd(B, 10);
            //printf("\n");
        }

        arf_twobytwo_diag(Gii, Gij, arb_midref(B(i,i)), arb_midref(B(i,j)), arb_midref(B(j,j)), 2*prec);
        arf_neg(Gji, Gij);
        arf_set(Gjj, Gii);

        //printf("%d %d\n", i, j);
        //arf_printd(Gii, 100);
        //printf(" ");
        //arf_printd(Gij, 100);
        //printf("\n");
        if(arf_is_zero(Gij)) {  // If this happens, we're
            finished = 1;       // not going to do any better
            break;              // without increasing the precision.
        }

        for(int k = 0; k < dim; k++) {
            arf_mul(B1[k], Gii, arb_midref(B(i,k)), prec, ARF_RND_NEAR);
            arf_addmul(B1[k], Gji, arb_midref(B(j,k)), prec, ARF_RND_NEAR);

            arf_mul(B2[k], Gij, arb_midref(B(i,k)), prec, ARF_RND_NEAR);
            arf_addmul(B2[k], Gjj, arb_midref(B(j,k)), prec, ARF_RND_NEAR);
        }
        for(int k = 0; k < dim; k++) {
            arf_set(arb_midref(B(i,k)), B1[k]);
            arf_set(arb_midref(B(j,k)), B2[k]);
        }
        for(int k = 0; k < dim; k++) {
            arf_mul(B1[k], Gii, arb_midref(B(k,i)), prec, ARF_RND_NEAR);
            arf_addmul(B1[k], Gji, arb_midref(B(k,j)), prec, ARF_RND_NEAR);

            arf_mul(B2[k], Gij, arb_midref(B(k,i)), prec, ARF_RND_NEAR);
            arf_addmul(B2[k], Gjj, arb_midref(B(k,j)), prec, ARF_RND_NEAR);
        }
        for(int k = 0; k < dim; k++) {
            arf_set(arb_midref(B(k,i)), B1[k]);
            arf_set(arb_midref(B(k,j)), B2[k]);
        }

        for(int k = 0; k < dim; k++) {
            arf_mul(B1[k], Gii, arb_midref(P(k,i)), prec, ARF_RND_NEAR);
            arf_addmul(B1[k], Gji, arb_midref(P(k,j)), prec, ARF_RND_NEAR);

            arf_mul(B2[k], Gij, arb_midref(P(k,i)), prec, ARF_RND_NEAR);
            arf_addmul(B2[k], Gjj, arb_midref(P(k,j)), prec, ARF_RND_NEAR);
        }
        for(int k = 0; k < dim; k++) {
            arf_set(arb_midref(P(k,i)), B1[k]);
            arf_set(arb_midref(P(k,j)), B2[k]);
        }

        if(i < dim - 1)
            arf_set_ui(row_max[i], 0);
        if(j < dim - 1)
            arf_set_ui(row_max[j], 0);

        // Update the max in any row where the maximum
        // was in a column that changed.
        for(int k = 0; k < dim - 1; k++) {
            if(row_max_indices[k] == j || row_max_indices[k] == i) {
                arf_abs(row_max[k], arb_midref(B(k,k+1)));
                row_max_indices[k] = k+1;
                for(int l = k+2; l < dim; l++) {
                    arf_abs(x1, arb_midref(B(k,l)));
                    if(arf_cmp(row_max[k], x1) < 0) {
                        arf_set(row_max[k], x1);
                        row_max_indices[k] = l;
                    }
                }
            }
        }

        // Update the max in the ith row.
        for(int k = i + 1; k < dim; k++) {
            arf_abs(x1, arb_midref(B(i, k)));
            if(arf_cmp(row_max[i], x1) < 0) {
                arf_set(row_max[i], x1);
                row_max_indices[i] = k;
            }
        }

        // Update the max in the jth row.
        for(int k = j + 1; k < dim; k++) {
            arf_abs(x1, arb_midref(B(j, k)));
            if(arf_cmp(row_max[j], x1) < 0) {
                arf_set(row_max[j], x1);
                row_max_indices[j] = k;
            }
        }

        // Go through column i to see if any of
        // the new entries are larger than the
        // max of their row.
        for(int k = 0; k < i; k++) {
            if(k == dim) continue;
            arf_abs(x1, arb_midref(B(k, i)));
            if(arf_cmp(row_max[k], x1) < 0) {
                arf_set(row_max[k], x1);
                row_max_indices[k] = i;
            }
        }

        // And then column j.
        for(int k = 0; k < j; k++) {
            if(k == dim) continue;
            arf_abs(x1, arb_midref(B(k, j)));
            if(arf_cmp(row_max[k], x1) < 0) {
                arf_set(row_max[k], x1);
                row_max_indices[k] = j;
            }
        }
    }

    for(int k = 0; k < dim; k++) {
        arb_set(D(k), B(k,k));
        arb_set_exact(D(k));
    }

    // At this point we've done that diagonalization and all that remains is
    // to certify the correctness and compute error bounds.

    arb_mat_t e;

    arb_t error_norms[dim];
    for(int k = 0; k < dim; k++) arb_init(error_norms[k]);

    arb_mat_init(e, dim, 1);

    arb_t z1, z2;
    arb_init(z1);
    arb_init(z2);
    for(int j = 0; j < dim; j++) {
        arb_mat_set(B, A);
        for(int k = 0; k < dim; k++) {
            arb_sub(B(k, k), B(k, k), D(j), prec);
        }
        for(int k = 0; k < dim; k++) {
            arb_set(arb_mat_entry(e, k, 0), P(k, j));
        }
        arb_mat_L2norm(z2, e, prec);
        arb_mat_mul(e, B, e, prec);
        arb_mat_L2norm(error_norms[j], e, prec);

        arb_div(z2, error_norms[j], z2, prec); // and now z1 is an upper bound for the
                                               // error in the eigenvalue
        arb_add_error(D(j), z2);
    }

    int unique_eigenvalues = 1;
    for(int j = 0; j < dim; j++) {
        if(j == 0) {
            arb_sub(z1, D(j), D(1), prec);
        }
        else {
            arb_sub(z1, D(j), D(0), prec);
        }
        arb_get_abs_lbound_arf(x1, z1, prec);
        for(int k = 1; k < dim; k++) {
            if(k == j) continue;
            arb_sub(z1, D(j), D(k), prec);
            arb_get_abs_lbound_arf(x2, z1, prec);
            if(arf_cmp(x2, x1) < 0) {
                arf_set(x1, x2);
            }
        }
        if(arf_is_zero(x1)) {
            unique_eigenvalues = 0;
        }
        arb_div_arf(z1, error_norms[j], x1, prec);
        for(int k = 0; k < dim; k++) {
            arb_add_error(P(k, j), z1);
        }
    }

    arb_mat_clear(e);
    arb_clear(z1);
    arb_clear(z2);
    for(int k = 0; k < dim; k++) arb_clear(error_norms[k]);

    arf_clear(x1);
    arf_clear(x2);
    arb_mat_clear(B);
    for(int k = 0; k < dim; k++) {
        arf_clear(B1[k]);
        arf_clear(B2[k]);
    }
    for(int k = 0; k < dim - 1; k++) {
        arf_clear(row_max[k]);
    }
    arf_clear(Gii);
    arf_clear(Gij);
    arf_clear(Gji);
    arf_clear(Gjj);
    free(B1);
    free(B2);
    free(row_max);
    free(row_max_indices);

    if(unique_eigenvalues) return 0;
    else return 1;
#undef B
#undef D
#undef P
}
Ejemplo n.º 6
0
Archivo: t-floor.c Proyecto: isuruf/arb
int main()
{
    slong iter;
    flint_rand_t state;

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

    flint_randinit(state);

    for (iter = 0; iter < 10000; iter++)
    {
        arf_t x, y;
        int result;

        arf_init(x);
        arf_init(y);

        arf_randtest_special(x, state, 2000, 100);
        arf_randtest_special(y, state, 2000, 100);

        arf_floor(y, x);

        result = 1;

        if (arf_is_int(x) || !arf_is_finite(x))
        {
            result = arf_equal(y, x);
        }
        else if (!arf_is_int(y))
        {
            result = 0;
        }
        else if (arf_cmp(y, x) >= 0)
        {
            result = 0;
        }
        else
        {
            arf_t s, t[3];

            /* check floor(x) - x + 1 > 0 */

            arf_init(s);
            arf_init(t[0]);
            arf_init(t[1]);
            arf_init(t[2]);

            arf_set(t[0], y);
            arf_neg(t[1], x);
            arf_one(t[2]);

            arf_sum(s, (arf_ptr) t, 3, 32, ARF_RND_DOWN);

            result = arf_sgn(s) > 0;

            arf_clear(s);
            arf_clear(t[0]);
            arf_clear(t[1]);
            arf_clear(t[2]);
        }

        if (!result)
        {
            flint_printf("FAIL!\n");
            flint_printf("x = "); arf_print(x); flint_printf("\n\n");
            flint_printf("y = "); arf_print(y); flint_printf("\n\n");
            abort();
        }

        arf_floor(x, x);

        if (!arf_equal(x, y))
        {
            flint_printf("FAIL (aliasing)!\n");
            flint_printf("x = "); arf_print(x); flint_printf("\n\n");
            flint_printf("y = "); arf_print(y); flint_printf("\n\n");
            abort();
        }

        arf_clear(x);
        arf_clear(y);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
Ejemplo n.º 7
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
}