示例#1
0
void 
_padic_log_balanced(fmpz_t z, const fmpz_t y, long v, const fmpz_t p, long N)
{
    fmpz_t pv, pN, r, t, u;
    long val;
    padic_inv_t S;

    fmpz_init(pv);
    fmpz_init(pN);
    fmpz_init(r);
    fmpz_init(t);
    fmpz_init(u);
    _padic_inv_precompute(S, p, N);

    fmpz_set(t, y);
    fmpz_set(pv, p);
    fmpz_pow_ui(pN, p, N);
    fmpz_zero(z);
    val = 1;

    /*
        TODO:  Abort earlier if larger than $p^N$, possible
        with variable precision?
     */
    while (!fmpz_is_zero(t))
    {
        fmpz_mul(pv, pv, pv);
        fmpz_fdiv_qr(t, r, t, pv);

        if (!fmpz_is_zero(t))
        {
            fmpz_mul(t, t, pv);
            fmpz_add_ui(u, r, 1);
            _padic_inv_precomp(u, u, S);
            fmpz_mul(t, t, u);
            fmpz_mod(t, t, pN);
        }

        if (!fmpz_is_zero(r))
        {
            fmpz_neg(r, r);
            _padic_log_bsplit(r, r, val, p, N);
            fmpz_sub(z, z, r);
        }
        val *= 2;
    }

    fmpz_clear(pv);
    fmpz_clear(pN);
    fmpz_clear(r);
    fmpz_clear(t);
    fmpz_clear(u);
    _padic_inv_clear(S);
}
示例#2
0
static void precompute_nu(fmpz *nu, long *v, long M, 
                          const long *C, long lenC, long p, long N)
{
    const long R  = M / p;
    const long N2 = N + (M / (p - 1));

    fmpz_t P, PN2, t;
    padic_inv_t S;
    double pinv;

    long i, j;

    fmpz_init_set_ui(P, p);
    fmpz_init(PN2);
    fmpz_pow_ui(PN2, P, N2);
    fmpz_init(t);

    /*
        Step 1. Compute $i! mod p^{N_2}$ where $N_2 \geq N + \max \ord_p (i!)$
        Step 2. Invert the unit part of $i!$ modulo $p^N$
     */

    fmpz_one(nu + 0);
    for (i = 1; i <= R; i++)
    {
        fmpz_mul_ui(nu + i, nu + (i - 1), i);
        fmpz_mod(nu + i, nu + i, PN2);
    }

    /* Let j denote the greatest index s.t. nu[j] has been computed */
    for (j = R, i = R + 1; i <= M; i++)
    {
        if (_bsearch(C, 0, lenC, i % p) != -1)
        {
            fmpz_mod_rfac_uiui(t, j + 1, i - j, PN2);
            fmpz_mul(nu + i, nu + j, t);
            fmpz_mod(nu + i, nu + i, PN2);
            j = i;
        }
    }

    _padic_inv_precompute(S, P, N);

    pinv = n_precompute_inverse(p);

    v[0] = 0;
    for (i = 1; i <= R; i++)
    {
        v[i] = - _fmpz_remove(nu + i, P, pinv);
        _padic_inv_precomp(nu + i, nu + i, S);
    }
    for (i = R + 1; i <= M; i++)
    {
        if (_bsearch(C, 0, lenC, i % p) != -1)
        {
            v[i] = - _fmpz_remove(nu + i, P, pinv);
            _padic_inv_precomp(nu + i, nu + i, S);
        }
    }

    fmpz_clear(P);
    fmpz_clear(PN2);
    fmpz_clear(t);
    _padic_inv_clear(S);
}