Esempio n. 1
0
File: erf.c Progetto: isuruf/arb
void
acb_hypgeom_erf(acb_t res, const acb_t z, slong prec)
{
    double x, y, absz2, logz;
    slong prec2;

    if (!acb_is_finite(z))
    {
        acb_indeterminate(res);
        return;
    }

    if (acb_is_zero(z))
    {
        acb_zero(res);
        return;
    }

    if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 0) < 0 &&
            arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0))
    {
        acb_hypgeom_erf_1f1a(res, z, prec);
        return;
    }

    if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 64) > 0 ||
            arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 64) > 0))
    {
        acb_hypgeom_erf_asymp(res, z, prec, 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);

    absz2 = x * x + y * y;
    logz = 0.5 * log(absz2);

    if (logz - absz2 < -(prec + 8) * 0.69314718055994530942)
    {
        /* If the asymptotic term is small, we can
           compute with reduced precision */
        prec2 = FLINT_MIN(prec + 4 + (y*y - x*x - logz) * 1.4426950408889634074, (double) prec);
        prec2 = FLINT_MAX(8, prec2);
        prec2 = FLINT_MIN(prec2, prec);

        acb_hypgeom_erf_asymp(res, z, prec, prec2);
    }
    else if (arf_cmpabs(arb_midref(acb_imagref(z)), arb_midref(acb_realref(z))) > 0)
    {
        acb_hypgeom_erf_1f1a(res, z, prec);
    }
    else
    {
        acb_hypgeom_erf_1f1b(res, z, prec);
    }
}
Esempio n. 2
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);
}