Beispiel #1
0
void
acb_hypgeom_airy_asymp2(acb_t ai, acb_t aip, acb_t bi, acb_t bip,
    const acb_t z, slong n, slong prec)
{
    /* avoid singularity in asymptotic expansion near 0 */
    if (acb_rel_accuracy_bits(z) > 3)
        acb_hypgeom_airy_asymp(ai, aip, bi, bip, z, n, prec);
    else
        acb_hypgeom_airy_prop(ai, aip, bi, bip, z, n, 1, prec);
}
Beispiel #2
0
void
acb_dirichlet_zeta_rs(acb_t res, const acb_t s, slong K, slong prec)
{
    if (acb_is_exact(s))
    {
        acb_dirichlet_zeta_rs_mid(res, s, K, prec);
    }
    else
    {
        acb_t t;
        mag_t rad, err, err2;
        slong acc;

        acc = acb_rel_accuracy_bits(s);
        acc = FLINT_MAX(acc, 0);
        acc = FLINT_MIN(acc, prec);
        prec = FLINT_MIN(prec, acc + 20);

        acb_init(t);
        mag_init(rad);
        mag_init(err);
        mag_init(err2);

        /* rad = rad(s) */
        mag_hypot(rad, arb_radref(acb_realref(s)), arb_radref(acb_imagref(s)));

        /* bound |zeta'(s)| */
        acb_dirichlet_zeta_deriv_bound(err, err2, s);

        /* error <= |zeta'(s)| * rad(s) */
        mag_mul(err, err, rad);

        /* evaluate at midpoint */
        acb_get_mid(t, s);
        acb_dirichlet_zeta_rs_mid(res, t, K, prec);

        acb_add_error_mag(res, err);

        acb_clear(t);
        mag_clear(rad);
        mag_clear(err);
        mag_clear(err2);
    }
}
Beispiel #3
0
int
f_lambertw(acb_ptr res, const acb_t z, void * param, slong order, slong prec)
{
    acb_t t;

    if (order > 1)
        flint_abort();  /* Would be needed for Taylor method. */

    acb_init(t);

    prec = FLINT_MIN(prec, acb_rel_accuracy_bits(z) + 10);

    if (order != 0)
    {
        /* check for branch cut */
        arb_const_e(acb_realref(t), prec);
        acb_inv(t, t, prec);
        acb_add(t, t, z, prec);

        if (arb_contains_zero(acb_imagref(t)) &&
            arb_contains_nonpositive(acb_realref(t)))
        {
            acb_indeterminate(t);
        }
    }

    if (acb_is_finite(t))
    {
        fmpz_t k;
        fmpz_init(k);
        acb_lambertw(res, z, k, 0, prec);
        fmpz_clear(k);
    }
    else
    {
        acb_indeterminate(res);
    }

    acb_clear(t);

    return 0;
}
Beispiel #4
0
void
acb_hypgeom_erf_1f1(acb_t res, const acb_t z, slong prec,
    slong wp, int more_imaginary)
{
    if (acb_rel_accuracy_bits(z) >= wp)
    {
        if (more_imaginary)
            acb_hypgeom_erf_1f1a(res, z, wp);
        else
            acb_hypgeom_erf_1f1b(res, z, wp);
    }
    else
    {
        acb_t zmid;
        mag_t re_err, im_err;

        acb_init(zmid);
        mag_init(re_err);
        mag_init(im_err);

        acb_hypgeom_erf_propagated_error(re_err, im_err, z);
        arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z)));
        arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z)));

        if (more_imaginary)
            acb_hypgeom_erf_1f1a(res, zmid, wp);
        else
            acb_hypgeom_erf_1f1b(res, zmid, wp);

        arb_add_error_mag(acb_realref(res), re_err);
        arb_add_error_mag(acb_imagref(res), im_err);

        acb_clear(zmid);
        mag_clear(re_err);
        mag_clear(im_err);
    }

    acb_set_round(res, res, prec);
}
Beispiel #5
0
int main()
{
    slong iter;
    flint_rand_t state;

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

    flint_randinit(state);

    /* test aliasing of c and a */
    for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++)
    {
        arb_t x;
        acb_t z;
        slong a1, a2;

        arb_init(x);
        acb_init(z);

        arb_randtest_special(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 200));
        acb_set_arb(z, x);

        a1 = arb_rel_accuracy_bits(x);
        a2 = acb_rel_accuracy_bits(z);

        if (a1 != a2)
        {
            flint_printf("FAIL: acb != arb\n\n");
            flint_printf("x = "); arb_print(x); flint_printf("\n\n");
            flint_printf("z = "); acb_print(z); flint_printf("\n\n");
            flint_printf("a1 = %wd, a2 = %wd\n\n", a1, a2);
            abort();
        }

        acb_randtest_special(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 200));

        a1 = acb_rel_accuracy_bits(z);

        if (n_randint(state, 2))
            arf_swap(arb_midref(acb_realref(z)), arb_midref(acb_imagref(z)));

        if (n_randint(state, 2))
            mag_swap(arb_radref(acb_realref(z)), arb_radref(acb_imagref(z)));

        a2 = acb_rel_accuracy_bits(z);

        if (a1 != a2)
        {
            flint_printf("FAIL: swapping\n\n");
            flint_printf("z = "); acb_print(z); flint_printf("\n\n");
            flint_printf("a1 = %wd, a2 = %wd\n\n", a1, a2);
            abort();
        }

        acb_randtest_special(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 200));

        if (arf_cmpabs(arb_midref(acb_realref(z)), arb_midref(acb_imagref(z))) >= 0)
            arf_set(arb_midref(x), arb_midref(acb_realref(z)));
        else
            arf_set(arb_midref(x), arb_midref(acb_imagref(z)));

        if (mag_cmp(arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))) >= 0)
            mag_set(arb_radref(x), arb_radref(acb_realref(z)));
        else
            mag_set(arb_radref(x), arb_radref(acb_imagref(z)));

        a1 = acb_rel_accuracy_bits(z);
        a2 = arb_rel_accuracy_bits(x);

        if (a1 != a2)
        {
            flint_printf("FAIL: acb != arb (2)\n\n");
            flint_printf("x = "); arb_print(x); flint_printf("\n\n");
            flint_printf("z = "); acb_print(z); flint_printf("\n\n");
            flint_printf("a1 = %wd, a2 = %wd\n\n", a1, a2);
            abort();
        }

        arb_clear(x);
        acb_clear(z);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
    int function, i, numtests;
    slong prec, goal;
    double t, total, logtotal;

    acb_t a, b, c, z, r, s;

    acb_init(a);
    acb_init(b);
    acb_init(c);
    acb_init(z);
    acb_init(r);
    acb_init(s);

    /*    J(0,pi x)   I(0,pi x)   K(0,pi x)          */

    for (function = 0; function < 3; function++)
    {
        total = 0.0;
        logtotal = 0.0;

        if (function < 2)
            numtests = 40;
        else
            numtests = 30;

        for (i = 0; i < numtests; i++)
        {
//            printf("%2d ", i + 1); fflush(stdout);

            TIMEIT_START
            prec = 96;

            for (;;)
            {
                if (function == 0)
                {
                    acb_set_d_d(a, input_1f1[i][0], input_1f1[i][1]);
                    acb_set_d_d(b, input_1f1[i][2], input_1f1[i][3]);
                    acb_set_d_d(z, input_1f1[i][4], input_1f1[i][5]);
                    acb_hypgeom_m(r, a, b, z, 0, prec);
                }
                else if (function == 1)
                {
                    acb_set_d_d(a, input_1f1[i][0], input_1f1[i][1]);
                    acb_set_d_d(b, input_1f1[i][2], input_1f1[i][3]);
                    acb_set_d_d(z, input_1f1[i][4], input_1f1[i][5]);
                    acb_hypgeom_u(r, a, b, z, prec);
                }
                else if (function == 2)
                {
                    acb_set_d_d(a, input_2f1[i][0], input_2f1[i][1]);
                    acb_set_d_d(b, input_2f1[i][2], input_2f1[i][3]);
                    acb_set_d_d(c, input_2f1[i][4], input_2f1[i][5]);
                    acb_set_d_d(z, input_2f1[i][6], input_2f1[i][7]);
                    acb_hypgeom_2f1(r, a, b, c, z, 0, prec);
                }
                else
                {
                    acb_set_d_d(a, input_2f1[i][0], input_2f1[i][1]);
                    acb_set_d_d(b, input_2f1[i][2], input_2f1[i][3]);
                    acb_set_d_d(c, input_2f1[i][4], input_2f1[i][5]);
                    acb_set_d_d(z, input_2f1[i][6], input_2f1[i][7]);
                    acb_mul_2exp_si(z, z, 1);
                    acb_sub_ui(z, z, 1, prec);
                    acb_neg(z, z);
                    acb_hypgeom_legendre_q(r, a, c, z, 0, prec);
                }

                if (function == 3)
                {
                    if (acb_rel_accuracy_bits(r) >= goal)
                        break;
                }
                else
                {
                    if (arb_can_round_arf(acb_realref(r), goal, ARF_RND_NEAR) &&
                        arb_can_round_arf(acb_imagref(r), goal, ARF_RND_NEAR))
                        break;
                }

                prec *= 2;
            }

            TIMEIT_STOP_VAL(t)

            total += t;
            logtotal += log(t);

#if 1
            printf("%8g, ", t);
#else
            printf("%8ld    %8g    ", prec, t);
            _acb_print(r, 25);
            printf("\n");
#endif
        }

        printf("---------------------------------------------------------------\n");
        printf("Mean %g s; geometric mean %g\n", total, exp(logtotal / numtests));
        printf("---------------------------------------------------------------\n");
    }

    acb_clear(a);
    acb_clear(b);
    acb_clear(c);
    acb_clear(z);
    acb_clear(r);
    acb_clear(s);
}
Beispiel #7
0
void
acb_hypgeom_m_choose(int * asymp, int * kummer, slong * wp,
    const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec)
{
    double x, y, t, cancellation;
    double input_accuracy, direct_accuracy, asymp_accuracy;
    slong m = WORD_MAX;
    slong n = WORD_MAX;

    if (acb_is_int(a) &&
            arf_cmpabs_2exp_si(arb_midref(acb_realref(a)), 30) < 0)
    {
        m = arf_get_si(arb_midref(acb_realref(a)), ARF_RND_DOWN);
    }

    if (acb_is_int(b) &&
            arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 30) < 0)
    {
        n = arf_get_si(arb_midref(acb_realref(b)), ARF_RND_DOWN);
    }

    *asymp = 0;
    *kummer = 0;
    *wp = prec;

    /* The 1F1 series terminates. */
    /* TODO: for large m, estimate extra precision here. */
    if (m <= 0 && m < n && m > -10 * prec && (n > 0 || !regularized))
    {
        *asymp = 0;
        return;
    }

    /* The 1F1 series terminates with the Kummer transform. */
    /* TODO: for large m, estimate extra precision here. */
    if (m >= 1 && n >= 1 && m < 0.1 * prec && n < 0.1 * prec && n <= m)
    {
        *asymp = 0;
        *kummer = 1;
        return;
    }

    input_accuracy = acb_rel_accuracy_bits(z);
    t = acb_rel_accuracy_bits(a);
    input_accuracy = FLINT_MIN(input_accuracy, t);
    t = acb_rel_accuracy_bits(b);
    input_accuracy = FLINT_MIN(input_accuracy, t);
    input_accuracy = FLINT_MAX(input_accuracy, 0.0);

    /* From here we ignore the values of a, b. Taking them into account is
       a possible future improvement... */

    /* Tiny |z|. */
    if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 2) < 0 &&
         arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 2) < 0))
    {
        *asymp = 0;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec));
        return;
    }

    /* Huge |z|. */
    if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 64) > 0 ||
         arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 64) > 0))
    {
        *asymp = 1;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec));
        return;
    }

    x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN);
    y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN);

    asymp_accuracy = sqrt(x * x + y * y) * 1.44269504088896 - 5.0;

    /* The Kummer transformation gives less cancellation with the 1F1 series. */
    if (x < 0.0)
    {
        *kummer = 1;
        x = -x;
    }

    if (asymp_accuracy >= prec)
    {
        *asymp = 1;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec));
        return;
    }

    cancellation = hypotmx(x, y) * 1.44269504088896;

    direct_accuracy = input_accuracy - cancellation;

    if (direct_accuracy > asymp_accuracy)
    {
        *asymp = 0;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec + cancellation));
    }
    else
    {
        *asymp = 1;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec));
    }
}
int main()
{
    slong iter;
    flint_rand_t state;

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

    flint_randinit(state);

    for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++)
    {
        acb_t r1, r2, x, y;
        fmpz_t a, b, c;
        slong prec;

        fmpz_init(a);
        fmpz_init(b);
        fmpz_init(c);

        acb_init(r1);
        acb_init(r2);
        acb_init(x);
        acb_init(y);

        prec = 2 + n_randint(state, 1000);

        fmpz_randtest_not_zero(a, state, 1 + n_randint(state, 1000));
        fmpz_randtest(b, state, 1 + n_randint(state, 1000));
        fmpz_randtest(c, state, 1 + n_randint(state, 1000));

        acb_randtest(r1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));
        acb_randtest(r2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));

        acb_quadratic_roots_fmpz(r1, r2, a, b, c, prec);

        acb_mul(x, r1, r1, prec);
        acb_mul_fmpz(x, x, a, prec);
        acb_addmul_fmpz(x, r1, b, prec);
        acb_add_fmpz(x, x, c, prec);

        acb_mul(y, r2, r2, prec);
        acb_mul_fmpz(y, y, a, prec);
        acb_addmul_fmpz(y, r2, b, prec);
        acb_add_fmpz(y, y, c, prec);

        if (!acb_contains_zero(x) || !acb_contains_zero(y) ||
            acb_rel_accuracy_bits(r1) < prec - 4 ||
            acb_rel_accuracy_bits(r2) < prec - 4)
        {
            flint_printf("FAIL: containment / accuracy\n\n");
            flint_printf("prec = %wd\n", prec);
            flint_printf("a = "); fmpz_print(a); flint_printf("\n\n");
            flint_printf("b = "); fmpz_print(b); flint_printf("\n\n");
            flint_printf("c = "); fmpz_print(c); flint_printf("\n\n");
            flint_printf("r1 = "); acb_printd(r1, 30); flint_printf("\n\n");
            flint_printf("r2 = "); acb_printd(r2, 30); flint_printf("\n\n");
            abort();
        }

        fmpz_clear(a);
        fmpz_clear(b);
        fmpz_clear(c);

        acb_clear(r1);
        acb_clear(r2);
        acb_clear(x);
        acb_clear(y);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
Beispiel #9
0
int main()
{
    slong iter;
    flint_rand_t state;

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

    flint_randinit(state);

    /* special accuracy test case */
    {
        acb_poly_t a;
        acb_t c;

        acb_init(c);
        acb_poly_init(a);

        arb_set_str(acb_realref(c), "-20.25", 53);
        arb_set_str(acb_imagref(c), "1e1000", 53);

        acb_poly_set_coeff_acb(a, 0, c);
        acb_poly_set_coeff_si(a, 1, 1);

        acb_poly_lgamma_series(a, a, 3, 53);

        if (acb_rel_accuracy_bits(a->coeffs) < 40 ||
            acb_rel_accuracy_bits(a->coeffs + 1) < 40 ||
            acb_rel_accuracy_bits(a->coeffs + 2) < 40)
        {
            flint_printf("FAIL: accuracy (reflection formula)\n\n");
            acb_poly_printd(a, 15); flint_printf("\n\n");
            abort();
        }

        acb_poly_clear(a);
        acb_clear(c);
    }

    for (iter = 0; iter < 500 * arb_test_multiplier(); iter++)
    {
        slong m, n1, n2, rbits1, rbits2, rbits3;
        acb_poly_t a, b, c, d;

        rbits1 = 2 + n_randint(state, 200);
        rbits2 = 2 + n_randint(state, 200);
        rbits3 = 2 + n_randint(state, 200);

        m = 1 + n_randint(state, 30);
        n1 = 1 + n_randint(state, 30);
        n2 = 1 + n_randint(state, 30);

        acb_poly_init(a);
        acb_poly_init(b);
        acb_poly_init(c);
        acb_poly_init(d);

        acb_poly_randtest(a, state, m, rbits1, 10);
        acb_poly_randtest(b, state, m, rbits1, 10);
        acb_poly_randtest(c, state, m, rbits1, 10);

        acb_poly_lgamma_series(b, a, n1, rbits2);
        acb_poly_lgamma_series(c, a, n2, rbits3);

        acb_poly_set(d, b);
        acb_poly_truncate(d, FLINT_MIN(n1, n2));
        acb_poly_truncate(c, FLINT_MIN(n1, n2));

        if (!acb_poly_overlaps(c, d))
        {
            flint_printf("FAIL\n\n");
            flint_printf("n1 = %wd, n2 = %wd, bits2 = %wd, bits3 = %wd\n", n1, n2, rbits2, rbits3);

            flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n");
            flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n");
            flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n");

            abort();
        }

        /* check loggamma(a) + log(a) = loggamma(a+1) */
        acb_poly_log_series(c, a, n1, rbits2);
        acb_poly_add(c, b, c, rbits2);

        acb_poly_set(d, a);
        acb_add_ui(d->coeffs, d->coeffs, 1, rbits2);
        acb_poly_lgamma_series(d, d, n1, rbits2);

        if (!acb_poly_overlaps(c, d))
        {
            flint_printf("FAIL (functional equation)\n\n");

            flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n");
            flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n");
            flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n");
            flint_printf("d = "); acb_poly_printd(d, 15); flint_printf("\n\n");

            abort();
        }

        acb_poly_lgamma_series(a, a, n1, rbits2);
        if (!acb_poly_overlaps(a, b))
        {
            flint_printf("FAIL (aliasing)\n\n");
            abort();
        }

        acb_poly_clear(a);
        acb_poly_clear(b);
        acb_poly_clear(c);
        acb_poly_clear(d);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
Beispiel #10
0
void
_acb_lambertw(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, int flags, slong prec)
{
    slong goal, ebits, ebits2, ls, lt;
    const fmpz * expo;

    /* Estimated accuracy goal. */
    /* todo: account for exponent bits and bits in k. */
    goal = acb_rel_accuracy_bits(z);
    goal = FLINT_MAX(goal, 10);
    goal = FLINT_MIN(goal, prec);

    /* Handle tiny z directly. For k >= 2, |c_k| <= 4^k / 16. */
    if (fmpz_is_zero(k)
        && arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -goal / 2) < 0
        && arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -goal / 2) < 0)
    {
        mag_t err;
        mag_init(err);
        acb_get_mag(err, z);
        mag_mul_2exp_si(err, err, 2);
        acb_set(res, z);
        acb_submul(res, res, res, prec);
        mag_geom_series(err, err, 3);
        mag_mul_2exp_si(err, err, -4);
        acb_add_error_mag(res, err);
        mag_clear(err);
        return;
    }

    if (arf_cmpabs(arb_midref(acb_realref(z)), arb_midref(acb_imagref(z))) >= 0)
        expo = ARF_EXPREF(arb_midref(acb_realref(z)));
    else
        expo = ARF_EXPREF(arb_midref(acb_imagref(z)));

    ebits = fmpz_bits(expo);

    /* ebits ~= log2(|log(z) + 2 pi i k|) */
    /* ebits2 ~= log2(log(log(z))) */
    ebits = FLINT_MAX(ebits, fmpz_bits(k));
    ebits = FLINT_MAX(ebits, 1) - 1;
    ebits2 = FLINT_BIT_COUNT(ebits);
    ebits2 = FLINT_MAX(ebits2, 1) - 1;

    /* We gain accuracy from the exponent when W ~ log - log log */
    if (fmpz_sgn(expo) > 0 || (fmpz_sgn(expo) < 0 && !fmpz_is_zero(k)))
    {
        goal += ebits - ebits2;
        goal = FLINT_MAX(goal, 10);
        goal = FLINT_MIN(goal, prec);

        /* The asymptotic series with truncation L, M gives us about 
           t - max(2+lt+L*(2+ls), M*(2+lt)) bits of accuracy where
           ls = -ebits, lt = ebits2 - ebits. */
        ls = 2 - ebits;
        lt = 2 + ebits2 - ebits;

        if (ebits - FLINT_MAX(lt + 1*ls, 1*lt) > goal)
        {
            acb_lambertw_asymp(res, z, k, 1, 1, goal);
            acb_set_round(res, res, prec);
            return;
        }
        else if (ebits - FLINT_MAX(lt + 3*ls, 5*lt) > goal)
        {
            acb_lambertw_asymp(res, z, k, 3, 5, goal);
            acb_set_round(res, res, prec);
            return;
        }
    }

    /* Extremely close to the branch point at -1/e, use the series expansion directly. */
    if (acb_lambertw_try_near_branch_point(res, z, ez1, k, flags, goal))
    {
        acb_set_round(res, res, prec);
        return;
    }

    /* compute union of both sides */
    if (acb_lambertw_branch_crossing(z, ez1, k))
    {
        acb_t za, zb, eza1, ezb1;
        fmpz_t kk;

        acb_init(za);
        acb_init(zb);
        acb_init(eza1);
        acb_init(ezb1);
        fmpz_init(kk);

        fmpz_neg(kk, k);

        acb_set(za, z);
        acb_conj(zb, z);
        arb_nonnegative_part(acb_imagref(za), acb_imagref(za));
        arb_nonnegative_part(acb_imagref(zb), acb_imagref(zb));

        acb_set(eza1, ez1);
        acb_conj(ezb1, ez1);
        arb_nonnegative_part(acb_imagref(eza1), acb_imagref(eza1));
        arb_nonnegative_part(acb_imagref(ezb1), acb_imagref(ezb1));

        /* Check series expansion again, because now there is no crossing. */
        if (!acb_lambertw_try_near_branch_point(res, za, eza1, k, flags, goal))
            acb_lambertw_cleared_cut_fix_small(za, za, eza1, k, flags, goal);

        if (!acb_lambertw_try_near_branch_point(res, zb, ezb1, kk, flags, goal))
            acb_lambertw_cleared_cut_fix_small(zb, zb, ezb1, kk, flags, goal);

        acb_conj(zb, zb);
        acb_union(res, za, zb, prec);

        acb_clear(za);
        acb_clear(zb);
        acb_clear(eza1);
        acb_clear(ezb1);
        fmpz_clear(kk);
    }
    else
    {
        acb_lambertw_cleared_cut_fix_small(res, z, ez1, k, flags, goal);
        acb_set_round(res, res, prec);
    }
}
Beispiel #11
0
/* note: z should be exact here */
void acb_lambertw_main(acb_t res, const acb_t z,
                const acb_t ez1, const fmpz_t k, int flags, slong prec)
{
    acb_t w, t, oldw, ew;
    mag_t err;
    slong i, wp, accuracy, ebits, kbits, mbits, wp_initial, extraprec;
    int have_ew;

    acb_init(t);
    acb_init(w);
    acb_init(oldw);
    acb_init(ew);
    mag_init(err);

    /* We need higher precision for large k, large exponents, or very close
       to the branch point at -1/e. todo: we should be recomputing
       ez1 to higher precision when close... */
    acb_get_mag(err, z);
    if (fmpz_is_zero(k) && mag_cmp_2exp_si(err, 0) < 0)
        ebits = 0;
    else
        ebits = fmpz_bits(MAG_EXPREF(err));

    if (fmpz_is_zero(k) || (fmpz_is_one(k) && arb_is_negative(acb_imagref(z)))
                        || (fmpz_equal_si(k, -1) && arb_is_nonnegative(acb_imagref(z))))
    {
        acb_get_mag(err, ez1);
        mbits = -MAG_EXP(err);
        mbits = FLINT_MAX(mbits, 0);
        mbits = FLINT_MIN(mbits, prec);
    }
    else
    {
        mbits = 0;
    }

    kbits = fmpz_bits(k);

    extraprec = FLINT_MAX(ebits, kbits);
    extraprec = FLINT_MAX(extraprec, mbits);

    wp = wp_initial = 40 + extraprec;

    accuracy = acb_lambertw_initial(w, z, ez1, k, wp_initial);
    mag_zero(arb_radref(acb_realref(w)));
    mag_zero(arb_radref(acb_imagref(w)));

    /* We should be able to compute e^w for the final certification
       during the Halley iteration. */
    have_ew = 0;

    for (i = 0; i < 5 + FLINT_BIT_COUNT(prec + extraprec); i++)
    {
        /* todo: should we restart? */
        if (!acb_is_finite(w))
            break;

        wp = FLINT_MIN(3 * accuracy, 1.1 * prec + 10);
        wp = FLINT_MAX(wp, 40);
        wp += extraprec;

        acb_set(oldw, w);
        acb_lambertw_halley_step(t, ew, z, w, wp);

        /* estimate the error (conservatively) */
        acb_sub(w, w, t, wp);
        acb_get_mag(err, w);
        acb_set(w, t);
        acb_add_error_mag(t, err);
        accuracy = acb_rel_accuracy_bits(t);

        if (accuracy > 2 * extraprec)
            accuracy *= 2.9;  /* less conservatively */

        accuracy = FLINT_MIN(accuracy, wp);
        accuracy = FLINT_MAX(accuracy, 0);

        if (accuracy > prec + extraprec)
        {
            /* e^w = e^oldw * e^(w-oldw) */
            acb_sub(t, w, oldw, wp);
            acb_exp(t, t, wp);
            acb_mul(ew, ew, t, wp);
            have_ew = 1;
            break;
        }

        mag_zero(arb_radref(acb_realref(w)));
        mag_zero(arb_radref(acb_imagref(w)));
    }

    wp = FLINT_MIN(3 * accuracy, 1.1 * prec + 10);
    wp = FLINT_MAX(wp, 40);
    wp += extraprec;

    if (acb_lambertw_check_branch(w, k, wp))
    {
        acb_t u, r, eu1;
        mag_t err, rad;

        acb_init(u);
        acb_init(r);
        acb_init(eu1);

        mag_init(err);
        mag_init(rad);

        if (have_ew)
            acb_set(t, ew);
        else
            acb_exp(t, w, wp);
        /* t = w e^w */
        acb_mul(t, t, w, wp);

        acb_sub(r, t, z, wp);

        /* Bound W' on the straight line path between t and z */
        acb_union(u, t, z, wp);

        arb_const_e(acb_realref(eu1), wp);
        arb_zero(acb_imagref(eu1));
        acb_mul(eu1, eu1, u, wp);
        acb_add_ui(eu1, eu1, 1, wp);

        if (acb_lambertw_branch_crossing(u, eu1, k))
        {
            mag_inf(err);
        }
        else
        {
            acb_lambertw_bound_deriv(err, u, eu1, k);
            acb_get_mag(rad, r);
            mag_mul(err, err, rad);
        }

        acb_add_error_mag(w, err);

        acb_set(res, w);

        acb_clear(u);
        acb_clear(r);
        acb_clear(eu1);
        mag_clear(err);
        mag_clear(rad);
    }
    else
    {
        acb_indeterminate(res);
    }

    acb_clear(t);
    acb_clear(w);
    acb_clear(oldw);
    acb_clear(ew);
    mag_clear(err);
}