Esempio n. 1
0
void
acb_lambertw_left(acb_t res, const acb_t z, const fmpz_t k, slong prec)
{
    if (acb_contains_zero(z) && !(fmpz_equal_si(k, -1) && acb_is_real(z)))
    {
        acb_indeterminate(res);
        return;
    }

    if (arb_is_positive(acb_imagref(z)))
    {
        acb_lambertw(res, z, k, 0, prec);
    }
    else if (arb_is_nonpositive(acb_imagref(z)))
    {
        fmpz_t kk;
        fmpz_init(kk);
        fmpz_add_ui(kk, k, 1);
        fmpz_neg(kk, kk);

        acb_conj(res, z);
        acb_lambertw(res, res, kk, 0, prec);
        acb_conj(res, res);

        fmpz_clear(kk);
    }
    else
    {
        acb_t za, zb;
        fmpz_t kk;

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

        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));

        fmpz_add_ui(kk, k, 1);
        fmpz_neg(kk, kk);

        acb_lambertw(za, za, k, 0, prec);
        acb_lambertw(zb, zb, kk, 0, prec);
        acb_conj(zb, zb);

        acb_union(res, za, zb, prec);

        acb_clear(za);
        acb_clear(zb);
        fmpz_clear(kk);
    }
}
Esempio n. 2
0
void
acb_lambertw_cleared_cut_fix_small(acb_t res, const acb_t z,
    const acb_t ez1, const fmpz_t k, int flags, slong prec)
{
    acb_t zz, zmid, zmide1;
    arf_t eps;

    acb_init(zz);
    acb_init(zmid);
    acb_init(zmide1);
    arf_init(eps);

    arf_mul_2exp_si(eps, arb_midref(acb_realref(z)), -prec);
    acb_set(zz, z);

    if (arf_sgn(arb_midref(acb_realref(zz))) < 0 &&
        (!fmpz_is_zero(k) || arf_sgn(arb_midref(acb_realref(ez1))) < 0) &&
        arf_cmpabs(arb_midref(acb_imagref(zz)), eps) < 0)
    {
        /* now the value must be in [0,2eps] */
        arf_get_mag(arb_radref(acb_imagref(zz)), eps);
        arf_set_mag(arb_midref(acb_imagref(zz)), arb_radref(acb_imagref(zz)));

        if (arf_sgn(arb_midref(acb_imagref(z))) >= 0)
        {
            acb_lambertw_cleared_cut(res, zz, k, flags, prec);
        }
        else
        {
            fmpz_t kk;
            fmpz_init(kk);
            fmpz_neg(kk, k);
            acb_lambertw_cleared_cut(res, zz, kk, flags, prec);
            acb_conj(res, res);
            fmpz_clear(kk);
        }
    }
    else
    {
        acb_lambertw_cleared_cut(res, zz, k, flags, prec);
    }

    acb_clear(zz);
    acb_clear(zmid);
    acb_clear(zmide1);
    arf_clear(eps);
}
Esempio n. 3
0
void
acb_dirichlet_zeta_rs_mid(acb_t res, const acb_t s, slong K, slong prec)
{
    acb_t R1, R2, X, t;
    slong wp;

    if (arf_sgn(arb_midref(acb_imagref(s))) < 0)
    {
        acb_init(t);
        acb_conj(t, s);
        acb_dirichlet_zeta_rs(res, t, K, prec);
        acb_conj(res, res);
        acb_clear(t);
        return;
    }

    acb_init(R1);
    acb_init(R2);
    acb_init(X);
    acb_init(t);

    /* rs_r increases the precision internally */
    wp = prec;

    acb_dirichlet_zeta_rs_r(R1, s, K, wp);

    if (arb_is_exact(acb_realref(s)) &&
        (arf_cmp_2exp_si(arb_midref(acb_realref(s)), -1) == 0))
    {
        acb_conj(R2, R1);
    }
    else
    {
        /* conj(R(conj(1-s))) */
        arb_sub_ui(acb_realref(t), acb_realref(s), 1, 10 * wp);
        arb_neg(acb_realref(t), acb_realref(t));
        arb_set(acb_imagref(t), acb_imagref(s));
        acb_dirichlet_zeta_rs_r(R2, t, K, wp);
        acb_conj(R2, R2);
    }

    if (acb_is_finite(R1) && acb_is_finite(R2))
    {
        wp += 10 + arf_abs_bound_lt_2exp_si(arb_midref(acb_imagref(s)));
        wp = FLINT_MAX(wp, 10);

        /* X = pi^(s-1/2) gamma((1-s)/2) rgamma(s/2)
             = (2 pi)^s rgamma(s) / (2 cos(pi s / 2)) */
        acb_rgamma(X, s, wp);
        acb_const_pi(t, wp);
        acb_mul_2exp_si(t, t, 1);
        acb_pow(t, t, s, wp);
        acb_mul(X, X, t, wp);
        acb_mul_2exp_si(t, s, -1);
        acb_cos_pi(t, t, wp);
        acb_mul_2exp_si(t, t, 1);
        acb_div(X, X, t, wp);

        acb_mul(R2, R2, X, wp);
    }

    /* R1 + X * R2 */
    acb_add(res, R1, R2, prec);

    acb_clear(R1);
    acb_clear(R2);
    acb_clear(X);
    acb_clear(t);
}
Esempio n. 4
0
void
acb_dirichlet_l(acb_t res, const acb_t s,
    const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
    if (!acb_is_finite(s))
    {
        acb_indeterminate(res);
    }
    else if (G == NULL || G->q == 1)
    {
        acb_dirichlet_zeta(res, s, prec);
    }
    else if (dirichlet_char_is_primitive(G, chi) &&
        (arf_cmp_d(arb_midref(acb_realref(s)), -0.5) < 0 ||
            (G->q != 1 && dirichlet_parity_char(G, chi) == 0 &&
                arf_cmpabs_d(arb_midref(acb_imagref(s)), 0.125) < 0 &&
                arf_cmp_d(arb_midref(acb_realref(s)), 0.125) < 0)))
    {
        /* use functional equation */
        acb_t t, u, v;
        int parity;
        ulong q;

        parity = dirichlet_parity_char(G, chi);
        q = G->q;

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

        /* gamma((1-s+p)/2) / gamma((s+p)/2) */
        acb_add_ui(t, s, parity, prec);
        acb_mul_2exp_si(t, t, -1);
        acb_rgamma(t, t, prec);

        if (!acb_is_zero(t))  /* assumes q != 1 when s = 0 */
        {
            acb_neg(u, s);
            acb_add_ui(u, u, 1 + parity, prec);
            acb_mul_2exp_si(u, u, -1);
            acb_gamma(u, u, prec);
            acb_mul(t, t, u, prec);

            /* epsilon */
            acb_dirichlet_root_number(u, G, chi, prec);
            acb_mul(t, t, u, prec);

            /* (pi/q)^(s-1/2) */
            acb_const_pi(u, prec);
            acb_div_ui(u, u, q, prec);
            acb_set_d(v, -0.5);
            acb_add(v, v, s, prec);
            acb_pow(u, u, v, prec);
            acb_mul(t, t, u, prec);

            acb_sub_ui(u, s, 1, prec);
            acb_neg(u, u);
            acb_conj(u, u);
            acb_dirichlet_l_general(u, u, G, chi, prec);
            acb_conj(u, u);
            acb_mul(t, t, u, prec);

            if (dirichlet_char_is_real(G, chi) && acb_is_real(s))
                arb_zero(acb_imagref(t));
        }

        acb_set(res, t);

        acb_clear(t);
        acb_clear(u);
        acb_clear(v);
    }
    else
    {
        acb_dirichlet_l_general(res, s, G, chi, prec);
    }
}
Esempio n. 5
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);
}
Esempio n. 6
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);
    }
}
Esempio n. 7
0
static void
acb_log_sin_pi_half(acb_t res, const acb_t z, slong prec, int upper)
{
    acb_t t, u, zmid;
    arf_t n;
    arb_t pi;

    acb_init(t);
    acb_init(u);
    acb_init(zmid);
    arf_init(n);
    arb_init(pi);

    arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z)));
    arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z)));

    arf_floor(n, arb_midref(acb_realref(zmid)));
    arb_sub_arf(acb_realref(zmid), acb_realref(zmid), n, prec);

    arb_const_pi(pi, prec);

    if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(zmid)), 2) < 1)
    {
        acb_sin_pi(t, zmid, prec);
        acb_log(t, t, prec);
    }
    else  /* i*pi*(z-0.5) + log((1-exp(-2i*pi*z))/2) */
    {
        acb_mul_2exp_si(t, zmid, 1);
        acb_neg(t, t);

        if (upper)
            acb_conj(t, t);

        acb_exp_pi_i(t, t, prec);
        acb_sub_ui(t, t, 1, prec);
        acb_neg(t, t);

        acb_mul_2exp_si(t, t, -1);

        acb_log(t, t, prec);
        acb_one(u);
        acb_mul_2exp_si(u, u, -1);
        acb_sub(u, zmid, u, prec);
        if (upper)
            acb_conj(u, u);
        acb_mul_onei(u, u);
        acb_addmul_arb(t, u, pi, prec);
        if (upper)
            acb_conj(t, t);
    }

    if (upper)
        arb_submul_arf(acb_imagref(t), pi, n, prec);
    else
        arb_addmul_arf(acb_imagref(t), pi, n, prec);

    /* propagated error bound from the derivative pi cot(pi z) */
    if (!acb_is_exact(z))
    {
        mag_t zm, um;

        mag_init(zm);
        mag_init(um);

        acb_cot_pi(u, z, prec);
        acb_mul_arb(u, u, pi, prec);

        mag_hypot(zm, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z)));
        acb_get_mag(um, u);
        mag_mul(um, um, zm);

        acb_add_error_mag(t, um);

        mag_clear(zm);
        mag_clear(um);
    }

    acb_set(res, t);

    acb_clear(t);
    acb_clear(u);
    acb_clear(zmid);
    arf_clear(n);
    arb_clear(pi);
}