Пример #1
0
void
acb_log_sin_pi(acb_t res, const acb_t z, slong prec)
{
    if (!acb_is_finite(z))
    {
        acb_indeterminate(res);
        return;
    }

    if (arb_is_positive(acb_imagref(z)) ||
        (arb_is_zero(acb_imagref(z)) && arb_is_negative(acb_realref(z))))
    {
        acb_log_sin_pi_half(res, z, prec, 1);
    }
    else if (arb_is_negative(acb_imagref(z)) ||
        (arb_is_zero(acb_imagref(z)) && arb_is_positive(acb_realref(z))))
    {
        acb_log_sin_pi_half(res, z, prec, 0);
    }
    else
    {
        acb_t t;
        acb_init(t);
        acb_log_sin_pi_half(t, z, prec, 1);
        acb_log_sin_pi_half(res, z, prec, 0);
        arb_union(acb_realref(res), acb_realref(res), acb_realref(t), prec);
        arb_union(acb_imagref(res), acb_imagref(res), acb_imagref(t), prec);
        acb_clear(t);
    }
}
Пример #2
0
void
acb_hypgeom_bessel_i_asymp_prefactors(acb_t A, acb_t B, acb_t C,
    const acb_t nu, const acb_t z, long prec)
{
    acb_t t, u;

    acb_init(t);
    acb_init(u);

    /* C = (2 pi z)^(-1/2) */
    acb_const_pi(C, prec);
    acb_mul_2exp_si(C, C, 1);
    acb_mul(C, C, z, prec);
    acb_rsqrt(C, C, prec);

    if (arb_is_positive(acb_imagref(z)) ||
        (arb_is_zero(acb_imagref(z)) && arb_is_negative(acb_realref(z))))
    {
        acb_exp_pi_i(t, nu, prec);
        acb_mul_onei(t, t);
    }
    else if (arb_is_negative(acb_imagref(z)) ||
        (arb_is_zero(acb_imagref(z)) && arb_is_positive(acb_realref(z))))
    {
        acb_neg(t, nu);
        acb_exp_pi_i(t, t, prec);
        acb_mul_onei(t, t);
        acb_neg(t, t);
    }
    else
    {
        acb_exp_pi_i(t, nu, prec);
        acb_mul_onei(t, t);
        acb_neg(u, nu);
        acb_exp_pi_i(u, u, prec);
        acb_mul_onei(u, u);
        acb_neg(u, u);

        arb_union(acb_realref(t), acb_realref(t), acb_realref(u), prec);
        arb_union(acb_imagref(t), acb_imagref(t), acb_imagref(u), prec);
    }

    acb_exp_invexp(B, A, z, prec);
    acb_mul(A, A, t, prec);

    acb_clear(t);
    acb_clear(u);
}
Пример #3
0
static __inline__ int
arb_sgn2(arb_t a)
{
    if (arb_is_positive(a)) return 1;
    else if (arb_is_negative(a)) return -1;
    return 0;
}
Пример #4
0
void
acb_real_min(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec)
{
    arb_t t;

    if (!acb_is_finite(x) || !acb_is_finite(y))
    {
        acb_indeterminate(res);
        return;
    }

    arb_init(t);
    arb_sub(t, acb_realref(x), acb_realref(y), prec);

    if (arb_is_positive(t))
        acb_set_round(res, y, prec);
    else if (arb_is_negative(t))
        acb_set_round(res, x, prec);
    else if (!analytic)
        acb_union(res, x, y, prec);
    else
        acb_indeterminate(res);

    arb_clear(t);
}
Пример #5
0
/* Extremely close to the branch point at -1/e, use the series expansion directly. */
int
acb_lambertw_try_near_branch_point(acb_t res, const acb_t z,
    const acb_t ez1, const fmpz_t k, int flags, slong prec)
{
    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))))
    {
        if (acb_contains_zero(ez1) ||
            (arf_cmpabs_2exp_si(arb_midref(acb_realref(ez1)), -prec / 4.5 - 6) < 0 &&
             arf_cmpabs_2exp_si(arb_midref(acb_imagref(ez1)), -prec / 4.5 - 6) < 0))
        {
            acb_t t;
            acb_init(t);
            acb_mul_2exp_si(t, ez1, 1);
            acb_sqrt(t, t, prec);
            if (!fmpz_is_zero(k))
                acb_neg(t, t);
            acb_lambertw_branchpoint_series(res, t, 1, prec);
            acb_clear(t);
            return 1;
        }
    }

    return 0;
}
Пример #6
0
/* 0 means that it *could* be zero; otherwise +/- 1 */
static __inline__ int
_arb_sign(const arb_t t)
{
    if (arb_is_positive(t))
        return 1;
    else if (arb_is_negative(t))
        return -1;
    else
        return 0;
}
Пример #7
0
static void
phase(acb_t res, const arb_t re, const arb_t im)
{
    if (arb_is_nonnegative(re) || arb_is_negative(im))
    {
        acb_one(res);
    }
    else if (arb_is_negative(re) && arb_is_nonnegative(im))
    {
        acb_set_si(res, -3);
    }
    else
    {
        arb_zero(acb_imagref(res));
        /* -1 +/- 2 */
        arf_set_si(arb_midref(acb_realref(res)), -1);
        mag_one(arb_radref(acb_realref(res)));
        mag_mul_2exp_si(arb_radref(acb_realref(res)), arb_radref(acb_realref(res)), 1);
    }
}
Пример #8
0
void
acb_lambertw(acb_t res, const acb_t z, const fmpz_t k, int flags, slong prec)
{
    acb_t ez1;

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

    if (flags == ACB_LAMBERTW_LEFT)
    {
        acb_lambertw_left(res, z, k, prec);
        return;
    }

    if (flags == ACB_LAMBERTW_MIDDLE)
    {
        acb_lambertw_middle(res, z, prec);
        return;
    }

    if (acb_contains_zero(z) && !fmpz_is_zero(k))
    {
        acb_indeterminate(res);
        return;
    }

    acb_init(ez1);

    /* precompute z*e + 1 */
    arb_const_e(acb_realref(ez1), prec);
    acb_mul(ez1, ez1, z, prec);
    acb_add_ui(ez1, ez1, 1, prec);

    /* Compute standard branches */

    /* use real code when possible */
    if (acb_is_real(z) && arb_is_positive(acb_realref(ez1)) &&
        (fmpz_is_zero(k) ||
        (fmpz_equal_si(k, -1) && arb_is_negative(acb_realref(z)))))
    {
        arb_lambertw(acb_realref(res), acb_realref(z), !fmpz_is_zero(k), prec);
        arb_zero(acb_imagref(res));
    }
    else
    {
        _acb_lambertw(res, z, ez1, k, flags, prec);
    }

    acb_clear(ez1);
}
Пример #9
0
void
acb_hypgeom_bessel_j_0f1(acb_t res, const acb_t nu, const acb_t z, long prec)
{
    acb_struct b[2];
    acb_t w, c, t;

    if (acb_is_int(nu) && arb_is_negative(acb_realref(nu)))
    {
        acb_init(t);
        acb_neg(t, nu);

        acb_hypgeom_bessel_j_0f1(res, t, z, prec);

        acb_mul_2exp_si(t, t, -1);
        if (!acb_is_int(t))
            acb_neg(res, res);

        acb_clear(t);
        return;
    }

    acb_init(b + 0);
    acb_init(b + 1);
    acb_init(w);
    acb_init(c);
    acb_init(t);

    acb_add_ui(b + 0, nu, 1, prec);
    acb_one(b + 1);

    /* (z/2)^nu / gamma(nu+1) */
    acb_mul_2exp_si(c, z, -1);
    acb_pow(c, c, nu, prec);
    acb_rgamma(t, b + 0, prec);
    acb_mul(c, t, c, prec);

    /* -z^2/4 */
    acb_mul(w, z, z, prec);
    acb_mul_2exp_si(w, w, -2);
    acb_neg(w, w);

    acb_hypgeom_pfq_direct(t, NULL, 0, b, 2, w, -1, prec);

    acb_mul(res, t, c, prec);

    acb_clear(b + 0);
    acb_clear(b + 1);
    acb_clear(w);
    acb_clear(c);
    acb_clear(t);
}
Пример #10
0
int main()
{
    int iter;
    FLINT_TEST_INIT(state);

    test_field1(state);
    test_field2(state);

    for (iter = 0; iter < 100; iter++)
    {
        renf_t nf;
        renf_elem_t a;
        fmpz_t f;
        arb_t e;

        fmpz_init(f);
        arb_init(e);
        renf_randtest(nf, state,
                          2 + n_randint(state, 20),   /* length */
                          8 + n_randint(state, 2408), /* prec   */
                          10 + n_randint(state, 10)   /* bits   */
                          );
        renf_elem_init(a, nf);
        renf_elem_randtest(a, state, 30 + n_randint(state, 10), nf);

        renf_elem_ceil(f, a, nf);

        arb_sub_fmpz(e, a->emb, f, 1024);
        if (arb_is_positive(e))
        {
            printf("FAIL:\n");
            abort();
        }
        arb_add_ui(e, e, 1, 1024);
        if (arb_is_negative(e))
        {
            printf("FAIL:\n");
            abort();
        }

        renf_elem_clear(a, nf);
        renf_clear(nf);
        fmpz_clear(f);
        arb_clear(e);
    }

    FLINT_TEST_CLEANUP(state);

    return 0;
}
Пример #11
0
/* assumes no aliasing */
slong
acb_lambertw_initial(acb_t res, const acb_t z, const acb_t ez1, const fmpz_t k, slong prec)
{
    /* Handle z very close to 0 on the principal branch. */
    if (fmpz_is_zero(k) && 
            (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -20) <= 0 &&
             arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -20) <= 0))
    {
        acb_set(res, z);
        acb_submul(res, res, res, prec);
        return 40;  /* could be tightened... */
    }

    /* For moderate input not close to the branch point, compute a double
       approximation as the initial value. */
    if (fmpz_is_zero(k) &&
        arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 400) < 0 &&
        arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 400) < 0 &&
          (arf_cmp_d(arb_midref(acb_realref(z)), -0.37) < 0 ||
           arf_cmp_d(arb_midref(acb_realref(z)), -0.36) > 0 ||
           arf_cmpabs_d(arb_midref(acb_imagref(z)), 0.01) > 0))
    {
        acb_lambertw_principal_d(res, z);
        return 48;
    }

    /* Check if we are close to the branch point at -1/e. */
    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))))
        && ((arf_cmpabs_2exp_si(arb_midref(acb_realref(ez1)), -2) <= 0 &&
             arf_cmpabs_2exp_si(arb_midref(acb_imagref(ez1)), -2) <= 0)))
    {
        acb_t t;
        acb_init(t);
        acb_mul_2exp_si(t, ez1, 1);
        mag_zero(arb_radref(acb_realref(t)));
        mag_zero(arb_radref(acb_imagref(t)));
        acb_mul_ui(t, t, 3, prec);
        acb_sqrt(t, t, prec);
        if (!fmpz_is_zero(k))
            acb_neg(t, t);
        acb_lambertw_branchpoint_series(res, t, 0, prec);
        acb_clear(t);
        return 1;  /* todo: estimate */
    }

    acb_lambertw_initial_asymp(res, z, k, prec);
    return 1;  /* todo: estimate */
}
Пример #12
0
static int
check_block(arb_calc_func_t func, void * param, const arf_interval_t block,
    int asign, int bsign, slong prec)
{
    arb_struct t[2];
    arb_t x;
    int result;

    arb_init(t + 0);
    arb_init(t + 1);
    arb_init(x);

    arf_interval_get_arb(x, block, prec);
    func(t, x, param, 1, prec);

    result = BLOCK_UNKNOWN;

    if (arb_is_positive(t) || arb_is_negative(t))
    {
        result = BLOCK_NO_ZERO;
    }
    else
    {
        if ((asign < 0 && bsign > 0) || (asign > 0 && bsign < 0))
        {
            func(t, x, param, 2, prec);

            if (arb_is_finite(t + 1) && !arb_contains_zero(t + 1))
            {
                result = BLOCK_ISOLATED_ZERO;
            }
        }
    }

    arb_clear(t + 0);
    arb_clear(t + 1);
    arb_clear(x);

    return result;
}
Пример #13
0
static void
_acb_print(const acb_t z, slong n)
{
    arb_printn(acb_realref(z), n, ARB_STR_NO_RADIUS);

    if (!arb_is_zero(acb_imagref(z)))
    {
        if (arb_is_negative(acb_imagref(z)))
        {
            arb_t t;
            arb_init(t);
            arb_neg(t, acb_imagref(z));
            printf(" - ");
            arb_printn(t, n, ARB_STR_NO_RADIUS);
        }
        else
        {
            printf(" + ");
            arb_printn(acb_imagref(z), n, ARB_STR_NO_RADIUS);
        }
        printf("i");
    }
}
Пример #14
0
int
_acb_poly_validate_real_roots(acb_srcptr roots, acb_srcptr poly, long len, long prec)
{
    long i, deg, num_real;
    arb_ptr real;
    int result;

    deg = len - 1;
    num_real = 0;
    result = 1;

    if (deg <= 1)
        return 1;

    real = _arb_vec_init(deg);

    /* pick out the candidate real roots */
    for (i = 0; i < deg; i++)
    {
        if (arb_contains_zero(acb_imagref(roots + i)))
        {
            arb_set(real + num_real, acb_realref(roots + i));
            num_real++;
        }
    }

    /* number of real roots must be even if the polynomial is even,
       and odd if the polynomial is odd (unless there are repeated roots...
       in which case the input is invalid) */
    if ((num_real % 2) != (deg % 2))
    {
        result = 0;
    }
    else if (num_real > 0)
    {
        int sign_neg_inf, sign_pos_inf, prev_sign;

        acb_t t;
        acb_init(t);

        /* by assumption that the roots are real and isolated, the lead
           coefficient really must be known to be either positive or negative */
        sign_pos_inf = arb_is_positive(acb_realref(poly + deg)) ? 1 : -1;
        sign_neg_inf = (deg % 2) ? -sign_pos_inf : sign_pos_inf;

        /* now we check that there's a sign change between each root */
        _arb_vec_sort_mid(real, num_real);

        prev_sign = sign_neg_inf;

        for (i = 0; i < num_real - 1; i++)
        {
            /* set t to the midpoint between the midpoints */
            arb_zero(acb_imagref(t));
            arf_add(arb_midref(acb_realref(t)),
                arb_midref(real + i), arb_midref(real + i + 1), prec, ARF_RND_DOWN);
            arf_mul_2exp_si(arb_midref(acb_realref(t)), arb_midref(acb_realref(t)), -1);
            mag_zero(arb_radref(acb_realref(t)));

            /* check that this point really is between both intervals (one interval
               could be much wider than the other */
            if (arb_lt(real + i, acb_realref(t)) && arb_lt(acb_realref(t), real + i + 1))
            {
                /* check sign change */
                _acb_poly_evaluate(t, poly, len, t, prec);

                if (prev_sign == 1)
                    result = arb_is_negative(acb_realref(t));
                else
                    result = arb_is_positive(acb_realref(t));

                if (!result)
                    break;

                prev_sign = -prev_sign;
            }
            else
            {
                result = 0;
                break;
            }
        }

        acb_clear(t);
    }

    _arb_vec_clear(real, deg);

    return result;
}
Пример #15
0
Файл: ci.c Проект: isuruf/arb
void
acb_hypgeom_ci_asymp(acb_t res, const acb_t z, slong prec)
{
    acb_t t, u, w, v, one;

    acb_init(t);
    acb_init(u);
    acb_init(w);
    acb_init(v);
    acb_init(one);

    acb_one(one);
    acb_mul_onei(w, z);

    /* u = U(1,1,iz) */
    acb_hypgeom_u_asymp(u, one, one, w, -1, prec);
    /* v = e^(-iz) */
    acb_neg(v, w);
    acb_exp(v, v, prec);
    acb_mul(t, u, v, prec);

    if (acb_is_real(z))
    {
        arb_div(acb_realref(t), acb_imagref(t), acb_realref(z), prec);
        arb_zero(acb_imagref(t));
        acb_neg(t, t);
    }
    else
    {
        /* u = U(1,1,-iz) */
        acb_neg(w, w);
        acb_hypgeom_u_asymp(u, one, one, w, -1, prec);
        acb_inv(v, v, prec);
        acb_submul(t, u, v, prec);

        acb_div(t, t, w, prec);
        acb_mul_2exp_si(t, t, -1);
    }

    if (arb_is_zero(acb_realref(z)))
    {
        if (arb_is_positive(acb_imagref(z)))
        {
            arb_const_pi(acb_imagref(t), prec);
            arb_mul_2exp_si(acb_imagref(t), acb_imagref(t), -1);
        }
        else if (arb_is_negative(acb_imagref(z)))
        {
            arb_const_pi(acb_imagref(t), prec);
            arb_mul_2exp_si(acb_imagref(t), acb_imagref(t), -1);
            arb_neg(acb_imagref(t), acb_imagref(t));
        }
        else
        {
            acb_const_pi(u, prec);
            acb_mul_2exp_si(u, u, -1);
            arb_zero(acb_imagref(t));
            arb_add_error(acb_imagref(t), acb_realref(u));
        }
    }
    else
    {
        /* 0 if positive or positive imaginary
           pi if upper left quadrant (including negative real axis)
           -pi if lower left quadrant (including negative imaginary axis) */
        if (arb_is_positive(acb_realref(z)))
        {
            /* do nothing */
        }
        else if (arb_is_negative(acb_realref(z)) && arb_is_nonnegative(acb_imagref(z)))
        {
            acb_const_pi(u, prec);
            arb_add(acb_imagref(t), acb_imagref(t), acb_realref(u), prec);
        }
        else if (arb_is_nonpositive(acb_realref(z)) && arb_is_negative(acb_imagref(z)))
        {
            acb_const_pi(u, prec);
            arb_sub(acb_imagref(t), acb_imagref(t), acb_realref(u), prec);
        }
        else
        {
            /* add [-pi,pi] */
            acb_const_pi(u, prec);
            arb_add_error(acb_imagref(t), acb_realref(u));
        }
    }

    acb_swap(res, t);

    acb_clear(t);
    acb_clear(u);
    acb_clear(w);
    acb_clear(v);
    acb_clear(one);
}
Пример #16
0
Файл: chi.c Проект: isuruf/arb
void
acb_hypgeom_chi_asymp(acb_t res, const acb_t z, slong prec)
{
    acb_t t, u, v, one;

    acb_init(t);
    acb_init(u);
    acb_init(v);
    acb_init(one);

    acb_one(one);

    /* u = U(1,1,z) */
    acb_hypgeom_u_asymp(u, one, one, z, -1, prec);
    /* v = e^(-z) */
    acb_neg(v, z);
    acb_exp(v, v, prec);
    acb_mul(t, u, v, prec);

    if (arb_is_zero(acb_realref(z)))
    {
        arb_div(acb_realref(t), acb_imagref(t), acb_imagref(z), prec);
        arb_zero(acb_imagref(t));
        acb_neg(t, t);
    }
    else
    {
        /* u = U(1,1,-z) */
        acb_neg(u, z);
        acb_hypgeom_u_asymp(u, one, one, u, -1, prec);
        acb_inv(v, v, prec);
        acb_submul(t, u, v, prec);

        acb_div(t, t, z, prec);
        acb_mul_2exp_si(t, t, -1);
        acb_neg(t, t);
    }

    if (acb_is_real(z))
    {
        if (arb_is_positive(acb_realref(z)))
        {
            arb_zero(acb_imagref(t));
        }
        else if (arb_is_negative(acb_realref(z)))
        {
            arb_const_pi(acb_imagref(t), prec);
        }
        else
        {
            /* add [-pi,pi]/2 i */
            acb_const_pi(u, prec);
            arb_zero(acb_imagref(t));
            arb_add_error(acb_imagref(t), acb_realref(u));
        }
    }
    else
    {
        /* -pi/2 if positive real or in lower half plane
           pi/2 if negative real or in upper half plane */
        if (arb_is_negative(acb_imagref(z)))
        {
            acb_const_pi(u, prec);
            acb_mul_2exp_si(u, u, -1);
            arb_sub(acb_imagref(t), acb_imagref(t), acb_realref(u), prec);
        }
        else if (arb_is_positive(acb_imagref(z)))
        {
            acb_const_pi(u, prec);
            acb_mul_2exp_si(u, u, -1);
            arb_add(acb_imagref(t), acb_imagref(t), acb_realref(u), prec);
        }
        else
        {
            /* add [-pi,pi]/2 i */
            acb_const_pi(u, prec);
            acb_mul_2exp_si(u, u, -1);
            arb_add_error(acb_imagref(t), acb_realref(u));
        }
    }

    acb_swap(res, t);

    acb_clear(t);
    acb_clear(u);
    acb_clear(v);
    acb_clear(one);
}
Пример #17
0
int main()
{
    slong iter;
    flint_rand_t state;

    flint_printf("2f1_continuation....");
    fflush(stdout);

    flint_randinit(state);

    for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
    {
        acb_t a, b, c, z1, z2, f1, f2, g1, g2, h1, h2, aa, bb, cc;
        mag_t d0, d1, dt;

        slong prec;
        int regularized, ebits;

        acb_init(a); acb_init(b); acb_init(c);
        acb_init(aa); acb_init(bb); acb_init(cc);
        acb_init(z1); acb_init(z2);
        acb_init(f1); acb_init(f2);
        acb_init(g1); acb_init(g2);
        acb_init(h1); acb_init(h2);
        mag_init(d0); mag_init(d1); mag_init(dt);

        prec = 2 + n_randint(state, 300);
        ebits = 10;
        regularized = n_randint(state, 2);

        acb_randtest_param(a, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2));
        acb_randtest_param(b, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2));
        acb_randtest_param(c, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits / 2));
        acb_randtest(h1, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits));
        acb_randtest(h2, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits));

        do {
            int left, upper, lower;

            acb_randtest_param(z1, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits));
            acb_randtest_param(z2, state, 1 + n_randint(state, 400), 1 + n_randint(state, ebits));

            /* we test both convergent and non-convergent cases, but
               try to be more efficient by generating more convergent cases */
            if (n_randint(state, 2))
            {
                acb_sub_ui(aa, z1, 1, prec);
                acb_get_mag(d0, z1);
                acb_get_mag(d1, aa);
                acb_get_mag(dt, z2);

                if (mag_cmp(dt, d0) >= 0 || mag_cmp(dt, d1) >= 0)
                    continue;
            }

            acb_add(z2, z1, z2, prec);

            /* for the test, don't cross the branch cut */
            acb_sub_ui(aa, z1, 1, prec);
            acb_sub_ui(bb, z2, 1, prec);

            left = arb_is_negative(acb_realref(aa)) && arb_is_negative(acb_realref(bb));
            upper = arb_is_positive(acb_imagref(aa)) && arb_is_positive(acb_imagref(bb));
            lower = arb_is_nonpositive(acb_imagref(aa)) && arb_is_nonpositive(acb_imagref(bb));

            if (left || upper || lower)
                break;
        } while (1);

        acb_add_ui(aa, a, 1, prec);
        acb_add_ui(bb, b, 1, prec);
        acb_add_ui(cc, c, 1, prec);

        acb_hypgeom_2f1(f1, a, b, c, z1, regularized, prec);
        acb_hypgeom_2f1(f2, aa, bb, cc, z1, regularized, prec);
        acb_mul(f2, f2, a, prec);
        acb_mul(f2, f2, b, prec);
        if (!regularized)
            acb_div(f2, f2, c, prec);

        acb_hypgeom_2f1_continuation(h1, h2, a, b, c, z1, z2, f1, f2, prec);

        if (acb_is_finite(h1) || acb_is_finite(h2))
        {
            acb_hypgeom_2f1(g1, a, b, c, z2, regularized, prec);
            acb_hypgeom_2f1(g2, aa, bb, cc, z2, regularized, prec);
            acb_mul(g2, g2, a, prec);
            acb_mul(g2, g2, b, prec);
            if (!regularized)
                acb_div(g2, g2, c, prec);

            if (!acb_overlaps(g1, h1) || !acb_overlaps(g2, h2))
            {
                flint_printf("FAIL: consistency\n\n");
                flint_printf("regularized = %d, prec = %wd\n\n", regularized, prec);
                flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n");
                flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n");
                flint_printf("c = "); acb_printd(c, 30); flint_printf("\n\n");
                flint_printf("z1 = "); acb_printd(z1, 30); flint_printf("\n\n");
                flint_printf("z2 = "); acb_printd(z2, 30); flint_printf("\n\n");
                flint_printf("F(a,b,c,z1) and F'(a,b,c,z1):\n");
                flint_printf("f1 = "); acb_printd(f1, 30); flint_printf("\n\n");
                flint_printf("f2 = "); acb_printd(f2, 30); flint_printf("\n\n");
                flint_printf("F(a,b,c,z2) and F'(a,b,c,z2):\n");
                flint_printf("g1 = "); acb_printd(g1, 30); flint_printf("\n\n");
                flint_printf("g2 = "); acb_printd(g2, 30); flint_printf("\n\n");
                flint_printf("Computed F and F':\n");
                flint_printf("h1 = "); acb_printd(h1, 30); flint_printf("\n\n");
                flint_printf("h2 = "); acb_printd(h2, 30); flint_printf("\n\n");
                flint_abort();
            }
        }

        acb_clear(a); acb_clear(b); acb_clear(c);
        acb_clear(aa); acb_clear(bb); acb_clear(cc);
        acb_clear(z1); acb_clear(z2);
        acb_clear(f1); acb_clear(f2);
        acb_clear(g1); acb_clear(g2);
        acb_clear(h1); acb_clear(h2);
        mag_clear(d0); mag_clear(d1); mag_clear(dt);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
Пример #18
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);
}
Пример #19
0
void
acb_hypgeom_pfq_series_direct(acb_poly_t res,
    const acb_poly_struct * a, long p,
    const acb_poly_struct * b, long q,
    const acb_poly_t z, int regularized,
    long n, long len, long prec)
{
    acb_poly_t s, t, err;
    arb_poly_t C, T;
    long i;
    int is_real;
    int terminating;

    /* default algorithm to choose number of terms */
    if (n < 0)
    {
        n = acb_hypgeom_pfq_series_choose_n(a, p, b, q, z, len, prec);
    }

    terminating = 0;

    /* check if it terminates due to a root of the numerator */
    for (i = 0; i < p; i++)
    {
        if (acb_poly_length(a + i) == 0 && n > 0)
        {
            terminating = 1;
        }
        else if (acb_poly_length(a + i) == 1)
        {
            acb_srcptr c = acb_poly_get_coeff_ptr(a + i, 0);

            if (acb_is_int(c) && arb_is_negative(acb_realref(c)) &&
                arf_cmpabs_ui(arb_midref(acb_realref(c)), n) < 0)
            {
                terminating = 1;
            }
        }
    }

    /* check if it terminates (to order n) due to z */
    /* the following tests could be made stronger... */
    if (z->length == 0 && n >= 1)
    {
        terminating = 1;
    }
    else if (!terminating && z->length > 0 && acb_is_zero(z->coeffs) && n >= len)
    {
        if (regularized)
        {
            terminating = 1;
        }
        else
        {
            terminating = 1;

            for (i = 0; i < q; i++)
            {
                acb_srcptr c = acb_poly_get_coeff_ptr(b + i, 0);

                if (!arb_is_positive(acb_realref(c)) && acb_contains_int(c))
                    terminating = 0;
            }
        }
    }

    acb_poly_init(s);
    acb_poly_init(t);
    acb_poly_init(err);
    arb_poly_init(C);
    arb_poly_init(T);

    acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, n, len, prec);

    if (!terminating)
    {
        is_real = acb_poly_is_real(z);
        for (i = 0; i < p; i++)
            is_real = is_real && acb_poly_is_real(a + i);
        for (i = 0; i < q; i++)
            is_real = is_real && acb_poly_is_real(b + i);

        acb_poly_majorant(T, t, MAG_BITS);
        acb_hypgeom_pfq_series_bound_factor(C, a, p, b, q, z, n, len, MAG_BITS);

        if (!_arb_vec_is_finite(T->coeffs, T->length) ||
            !_arb_vec_is_finite(C->coeffs, C->length))
        {
            arb_poly_fit_length(T, len);
            _arb_vec_indeterminate(T->coeffs, len);
            _arb_poly_set_length(T, len);
        }
        else
        {
            arb_poly_mullow(T, T, C, len, MAG_BITS);
        }

        /* create polynomial of errors */
        acb_poly_fit_length(err, len);

        for (i = 0; i < FLINT_MIN(len, T->length); i++)
        {
            arb_add_error(acb_realref(err->coeffs + i), T->coeffs + i);
            if (!is_real)
                arb_add_error(acb_imagref(err->coeffs + i), T->coeffs + i);
        }

        _acb_poly_set_length(err, len);
        _acb_poly_normalise(err);

        acb_poly_add(s, s, err, prec);
    }

    acb_poly_set(res, s);

    acb_poly_clear(s);
    acb_poly_clear(t);
    acb_poly_clear(err);
    arb_poly_clear(C);
    arb_poly_clear(T);
}
Пример #20
0
void
acb_lambertw_middle(acb_t res, const acb_t z, slong prec)
{
    fmpz_t k;

    if (acb_contains_zero(z))
    {
        acb_indeterminate(res);
        return;
    }

    fmpz_init(k);
    fmpz_set_si(k, -1);

    if (arb_is_positive(acb_imagref(z)))
    {
        acb_lambertw(res, z, k, 0, prec);
    }
    else if (arb_is_negative(acb_imagref(z)))
    {
        acb_conj(res, z);
        acb_lambertw(res, res, k, 0, prec);
        acb_conj(res, res);
    }
    else if (arb_is_negative(acb_realref(z)))
    {
        if (arb_is_nonnegative(acb_imagref(z)))
        {
            acb_lambertw(res, z, k, 0, prec);
        }
        else if (arb_is_negative(acb_imagref(z)))
        {
            acb_conj(res, z);
            acb_lambertw(res, res, k, 0, prec);
            acb_conj(res, res);
        }
        else
        {
            acb_t za, zb;
            acb_init(za);
            acb_init(zb);
            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_lambertw(za, za, k, 0, prec);
            acb_lambertw(zb, zb, k, 0, prec);
            acb_conj(zb, zb);
            acb_union(res, za, zb, prec);
            acb_clear(za);
            acb_clear(zb);
        }
    }
    else /* re is positive */
    {
        if (arb_is_positive(acb_imagref(z)))
        {
            acb_lambertw(res, z, k, 0, prec);
        }
        else if (arb_is_nonpositive(acb_imagref(z)))
        {
            acb_conj(res, z);
            acb_lambertw(res, res, k, 0, prec);
            acb_conj(res, res);
        }
        else
        {
            acb_t za, zb;
            acb_init(za);
            acb_init(zb);
            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_lambertw(za, za, k, 0, prec);
            acb_lambertw(zb, zb, k, 0, prec);
            acb_conj(zb, zb);
            acb_union(res, za, zb, prec);
            acb_clear(za);
            acb_clear(zb);
        }
    }

    fmpz_clear(k);
}