Example #1
0
static void dsum_p(
    fmpz_t rop, 
    const fmpz *dinv, const fmpz *mu, long M, const long *C, long lenC, 
    const fmpz_t a, long ui, long vi, long n, long d, long p, long N)
{
    long m, r, idx;
    fmpz_t apm1, apow, f, g, P, PN;

    fmpz_init(apm1);
    fmpz_init(apow);
    fmpz_init(f);
    fmpz_init(g);
    fmpz_init_set_ui(P, p);
    fmpz_init(PN);

    fmpz_pow_ui(PN, P, N);

    fmpz_zero(rop);

    r = 0;
    m = (p * (ui + 1) - (vi + 1)) / d;

    if (m <= M)  /* Step {r = 0} */
    {
        idx = _bsearch(C, 0, lenC, m % p);

        fmpz_powm_ui(apm1, a, p - 1, PN);
        fmpz_one(apow);
        fmpz_one(f);
        fmpz_mod(rop, mu + idx + lenC * (m / p), PN);
    }

    for (r = 1, m += p; m <= M; r++, m += p)
    {
        idx = _bsearch(C, 0, lenC, m % p);

        fmpz_mul(apow, apow, apm1);
        fmpz_mod(apow, apow, PN);
        fmpz_mul_ui(f, f, ui + 1 + (r - 1) * d);
        fmpz_mod(f, f, PN);
        fmpz_mul(g, f, dinv + r);
        fmpz_mul(g, g, apow);
        fmpz_mul(g, g, mu + idx + lenC * (m / p));
        fmpz_mod(g, g, PN);
        fmpz_add(rop, rop, g);
    }

    fmpz_mod(rop, rop, PN);

    fmpz_clear(apm1);
    fmpz_clear(apow);
    fmpz_clear(f);
    fmpz_clear(g);
    fmpz_clear(P);
    fmpz_clear(PN);
}
Example #2
0
void fmpz_powm(fmpz_t f, const fmpz_t g, const fmpz_t e, const fmpz_t m)
{
    if (fmpz_sgn(m) <= 0)
    {
        flint_printf("Exception (fmpz_powm). Modulus is less than 1.\n");
        abort();
    }
    else if (!COEFF_IS_MPZ(*e))  /* e is small */
    {
        fmpz_powm_ui(f, g, *e, m);
    }
    else  /* e is large */
    {
        if (!COEFF_IS_MPZ(*m))  /* m is small */
        {
            ulong g1 = fmpz_fdiv_ui(g, *m);
            mpz_t g2, m2;
            __mpz_struct *mpz_ptr;

            flint_mpz_init_set_ui(g2, g1);
            flint_mpz_init_set_ui(m2, *m);
            mpz_ptr = _fmpz_promote(f);

            mpz_powm(mpz_ptr, g2, COEFF_TO_PTR(*e), m2);

            mpz_clear(g2);
            mpz_clear(m2);
            _fmpz_demote_val(f);
        }
        else  /* m is large */
        {
            if (!COEFF_IS_MPZ(*g))  /* g is small */
            {
                mpz_t g2;
                __mpz_struct *mpz_ptr;

                flint_mpz_init_set_si(g2, *g);
                mpz_ptr = _fmpz_promote(f);

                mpz_powm(mpz_ptr, g2, COEFF_TO_PTR(*e), COEFF_TO_PTR(*m));

                mpz_clear(g2);
                _fmpz_demote_val(f);
            }
            else  /* g is large */
            {
                __mpz_struct *mpz_ptr = _fmpz_promote(f);

                mpz_powm(mpz_ptr, 
                    COEFF_TO_PTR(*g), COEFF_TO_PTR(*e), COEFF_TO_PTR(*m));
                _fmpz_demote_val(f);
            }
        }
    }
}
Example #3
0
static void alpha(fmpz_t rop, const long *u, const long *v, 
    const fmpz *a, const fmpz *dinv, const fmpz **mu, long M, const long **C, const long *lenC, 
    long n, long d, long p, long N)
{
    const long ku = diagfrob_k(u, n, d);

    long i;
    fmpz_t f, g, P, PN;

    fmpz_init(f);
    fmpz_init(g);
    fmpz_init_set_ui(P, p);
    fmpz_init(PN);
    fmpz_pow_ui(PN, P, N);

    fmpz_pow_ui(rop, P, ku);
    fmpz_mod(rop, rop, PN);

    for (i = 0; i <= n; i++)
    {
        long e = (p * (u[i] + 1) - (v[i] + 1)) / d;

        fmpz_powm_ui(f, a + i, e, PN);
        dsum(g, dinv, mu[i], M, C[i], lenC[i], a + i, u[i], v[i], n, d, p, N);
        fmpz_mul(rop, rop, f);
        fmpz_mul(rop, rop, g);
        fmpz_mod(rop, rop, PN);
    }

    if (ku % 2 != 0 && !fmpz_is_zero(rop))
    {
        fmpz_sub(rop, PN, rop);
    }

    fmpz_clear(f);
    fmpz_clear(g);
    fmpz_clear(P);
    fmpz_clear(PN);
}
Example #4
0
void frob(const mpoly_t P, const ctx_t ctxFracQt,
          const qadic_t t1, const qadic_ctx_t Qq,
          prec_t *prec, const prec_t *prec_in,
          int verbose)
{
    const padic_ctx_struct *Qp = &Qq->pctx;
    const fmpz *p = Qp->p;
    const long a  = qadic_ctx_degree(Qq);
    const long n  = P->n - 1;
    const long d  = mpoly_degree(P, -1, ctxFracQt);
    const long b  = gmc_basis_size(n, d);

    long i, j, k;

    /* Diagonal fibre */
    padic_mat_t F0;

    /* Gauss--Manin Connection */
    mat_t M;
    mon_t *bR, *bC;
    fmpz_poly_t r;

    /* Local solution */
    fmpz_poly_mat_t C, Cinv;
    long vC, vCinv;

    /* Frobenius */
    fmpz_poly_mat_t F;
    long vF;

    fmpz_poly_mat_t F1;
    long vF1;

    fmpz_poly_t cp;

    clock_t c0, c1;
    double c;

    if (verbose)
    {
        printf("Input:\n");
        printf("  P  = "), mpoly_print(P, ctxFracQt), printf("\n");
        printf("  p  = "), fmpz_print(p), printf("\n");
        printf("  t1 = "), qadic_print_pretty(t1, Qq), printf("\n");
        printf("\n");
        fflush(stdout);
    }

    /* Step 1 {M, r} *********************************************************/

    c0 = clock();

    mat_init(M, b, b, ctxFracQt);
    fmpz_poly_init(r);

    gmc_compute(M, &bR, &bC, P, ctxFracQt);

    {
        fmpz_poly_t t;

        fmpz_poly_init(t);
        fmpz_poly_set_ui(r, 1);
        for (i = 0; i < M->m; i++)
            for (j = 0; j < M->n; j++)
            {
                fmpz_poly_lcm(t, r, fmpz_poly_q_denref(
                                  (fmpz_poly_q_struct *) mat_entry(M, i, j, ctxFracQt)));
                fmpz_poly_swap(r, t);
            }
        fmpz_poly_clear(t);
    }

    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;

    if (verbose)
    {
        printf("Gauss-Manin connection:\n");
        printf("  r(t) = "), fmpz_poly_print_pretty(r, "t"), printf("\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    {
        qadic_t t;

        qadic_init2(t, 1);
        fmpz_poly_evaluate_qadic(t, r, t1, Qq);

        if (qadic_is_zero(t))
        {
            printf("Exception (deformation_frob).\n");
            printf("The resultant r evaluates to zero (mod p) at t1.\n");
            abort();
        }
        qadic_clear(t);
    }

    /* Precisions ************************************************************/

    if (prec_in != NULL)
    {
        *prec = *prec_in;
    }
    else
    {
        deformation_precisions(prec, p, a, n, d, fmpz_poly_degree(r));
    }

    if (verbose)
    {
        printf("Precisions:\n");
        printf("  N0   = %ld\n", prec->N0);
        printf("  N1   = %ld\n", prec->N1);
        printf("  N2   = %ld\n", prec->N2);
        printf("  N3   = %ld\n", prec->N3);
        printf("  N3i  = %ld\n", prec->N3i);
        printf("  N3w  = %ld\n", prec->N3w);
        printf("  N3iw = %ld\n", prec->N3iw);
        printf("  N4   = %ld\n", prec->N4);
        printf("  m    = %ld\n", prec->m);
        printf("  K    = %ld\n", prec->K);
        printf("  r    = %ld\n", prec->r);
        printf("  s    = %ld\n", prec->s);
        printf("\n");
        fflush(stdout);
    }

    /* Initialisation ********************************************************/

    padic_mat_init2(F0, b, b, prec->N4);

    fmpz_poly_mat_init(C, b, b);
    fmpz_poly_mat_init(Cinv, b, b);

    fmpz_poly_mat_init(F, b, b);
    vF = 0;

    fmpz_poly_mat_init(F1, b, b);
    vF1 = 0;

    fmpz_poly_init(cp);

    /* Step 2 {F0} ***********************************************************/

    {
        padic_ctx_t pctx_F0;
        fmpz *t;

        padic_ctx_init(pctx_F0, p, FLINT_MIN(prec->N4 - 10, 0), prec->N4, PADIC_VAL_UNIT);
        t = _fmpz_vec_init(n + 1);

        c0 = clock();

        mpoly_diagonal_fibre(t, P, ctxFracQt);

        diagfrob(F0, t, n, d, prec->N4, pctx_F0, 0);
        padic_mat_transpose(F0, F0);

        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;

        if (verbose)
        {
            printf("Diagonal fibre:\n");
            printf("  P(0) = {"), _fmpz_vec_print(t, n + 1), printf("}\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }

        _fmpz_vec_clear(t, n + 1);
        padic_ctx_clear(pctx_F0);
    }

    /* Step 3 {C, Cinv} ******************************************************/
    /*
        Compute C as a matrix over Z_p[[t]].  A is the same but as a series
        of matrices over Z_p.  Mt is the matrix -M^t, and Cinv is C^{-1}^t,
        the local solution of the differential equation replacing M by Mt.
     */

    c0 = clock();
    {
        const long K = prec->K;
        padic_mat_struct *A;

        gmde_solve(&A, K, p, prec->N3, prec->N3w, M, ctxFracQt);
        gmde_convert_soln(C, &vC, A, K, p);

        for(i = 0; i < K; i++)
            padic_mat_clear(A + i);
        free(A);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Local solution:\n");
        printf("  Time for C      = %f\n", c);
        fflush(stdout);
    }

    c0 = clock();
    {
        const long K = (prec->K + (*p) - 1) / (*p);
        mat_t Mt;
        padic_mat_struct *Ainv;

        mat_init(Mt, b, b, ctxFracQt);
        mat_transpose(Mt, M, ctxFracQt);
        mat_neg(Mt, Mt, ctxFracQt);
        gmde_solve(&Ainv, K, p, prec->N3i, prec->N3iw, Mt, ctxFracQt);
        gmde_convert_soln(Cinv, &vCinv, Ainv, K, p);

        fmpz_poly_mat_transpose(Cinv, Cinv);
        fmpz_poly_mat_compose_pow(Cinv, Cinv, *p);

        for(i = 0; i < K; i++)
            padic_mat_clear(Ainv + i);
        free(Ainv);
        mat_clear(Mt, ctxFracQt);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("  Time for C^{-1} = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Step 4 {F(t) := C(t) F(0) C(t^p)^{-1}} ********************************/
    /*
        Computes the product C(t) F(0) C(t^p)^{-1} modulo (p^{N_2}, t^K).
        This is done by first computing the unit part of the product
        exactly over the integers modulo t^K.
     */

    c0 = clock();
    {
        fmpz_t pN;
        fmpz_poly_mat_t T;

        fmpz_init(pN);
        fmpz_poly_mat_init(T, b, b);

        for (i = 0; i < b; i++)
        {
            /* Find the unique k s.t. F0(i,k) is non-zero */
            for (k = 0; k < b; k++)
                if (!fmpz_is_zero(padic_mat_entry(F0, i, k)))
                    break;
            if (k == b)
            {
                printf("Exception (frob). F0 is singular.\n\n");
                abort();
            }

            for (j = 0; j < b; j++)
            {
                fmpz_poly_scalar_mul_fmpz(fmpz_poly_mat_entry(T, i, j),
                                          fmpz_poly_mat_entry(Cinv, k, j),
                                          padic_mat_entry(F0, i, k));
            }
        }

        fmpz_poly_mat_mul(F, C, T);
        fmpz_poly_mat_truncate(F, prec->K);
        vF = vC + padic_mat_val(F0) + vCinv;

        /* Canonicalise (F, vF) */
        {
            long v = fmpz_poly_mat_ord_p(F, p);

            if (v == LONG_MAX)
            {
                printf("ERROR (deformation_frob).  F(t) == 0.\n");
                abort();
            }
            else if (v > 0)
            {
                fmpz_pow_ui(pN, p, v);
                fmpz_poly_mat_scalar_divexact_fmpz(F, F, pN);
                vF = vF + v;
            }
        }

        /* Reduce (F, vF) modulo p^{N2} */
        fmpz_pow_ui(pN, p, prec->N2 - vF);
        fmpz_poly_mat_scalar_mod_fmpz(F, F, pN);

        fmpz_clear(pN);
        fmpz_poly_mat_clear(T);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Matrix for F(t):\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Step 5 {G = r(t)^m F(t)} **********************************************/

    c0 = clock();
    {
        fmpz_t pN;
        fmpz_poly_t t;

        fmpz_init(pN);
        fmpz_poly_init(t);

        fmpz_pow_ui(pN, p, prec->N2 - vF);

        /* Compute r(t)^m mod p^{N2-vF} */
        if (prec->denR == NULL)
        {
            fmpz_mod_poly_t _t;

            fmpz_mod_poly_init(_t, pN);
            fmpz_mod_poly_set_fmpz_poly(_t, r);
            fmpz_mod_poly_pow(_t, _t, prec->m);
            fmpz_mod_poly_get_fmpz_poly(t, _t);
            fmpz_mod_poly_clear(_t);
        }
        else
        {
            /* TODO: We don't really need a copy */
            fmpz_poly_set(t, prec->denR);
        }

        fmpz_poly_mat_scalar_mul_fmpz_poly(F, F, t);
        fmpz_poly_mat_scalar_mod_fmpz(F, F, pN);

        /* TODO: This should not be necessary? */
        fmpz_poly_mat_truncate(F, prec->K);

        fmpz_clear(pN);
        fmpz_poly_clear(t);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Analytic continuation:\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Steps 6 and 7 *********************************************************/

    if (a == 1)
    {
        /* Step 6 {F(1) = r(t_1)^{-m} G(t_1)} ********************************/

        c0 = clock();
        {
            const long N = prec->N2 - vF;

            fmpz_t f, g, t, pN;

            fmpz_init(f);
            fmpz_init(g);
            fmpz_init(t);
            fmpz_init(pN);

            fmpz_pow_ui(pN, p, N);

            /* f := \hat{t_1}, g := r(\hat{t_1})^{-m} */
            _padic_teichmuller(f, t1->coeffs + 0, p, N);
            if (prec->denR == NULL)
            {
                _fmpz_mod_poly_evaluate_fmpz(g, r->coeffs, r->length, f, pN);
                fmpz_powm_ui(t, g, prec->m, pN);
            }
            else
            {
                _fmpz_mod_poly_evaluate_fmpz(t, prec->denR->coeffs, prec->denR->length, f, pN);
            }
            _padic_inv(g, t, p, N);

            /* F1 := g G(\hat{t_1}) */
            for (i = 0; i < b; i++)
                for (j = 0; j < b; j++)
                {
                    const fmpz_poly_struct *poly = fmpz_poly_mat_entry(F, i, j);
                    const long len               = poly->length;

                    if (len == 0)
                    {
                        fmpz_poly_zero(fmpz_poly_mat_entry(F1, i, j));
                    }
                    else
                    {
                        fmpz_poly_fit_length(fmpz_poly_mat_entry(F1, i, j), 1);

                        _fmpz_mod_poly_evaluate_fmpz(t, poly->coeffs, len, f, pN);
                        fmpz_mul(fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, g, t);
                        fmpz_mod(fmpz_poly_mat_entry(F1, i, j)->coeffs + 0,
                                 fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, pN);

                        _fmpz_poly_set_length(fmpz_poly_mat_entry(F1, i, j), 1);
                        _fmpz_poly_normalise(fmpz_poly_mat_entry(F1, i, j));
                    }
                }

            vF1 = vF;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(f);
            fmpz_clear(g);
            fmpz_clear(t);
            fmpz_clear(pN);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Evaluation:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }
    }
    else
    {
        /* Step 6 {F(1) = r(t_1)^{-m} G(t_1)} ********************************/

        c0 = clock();
        {
            const long N = prec->N2 - vF;
            fmpz_t pN;
            fmpz *f, *g, *t;

            fmpz_init(pN);

            f = _fmpz_vec_init(a);
            g = _fmpz_vec_init(2 * a - 1);
            t = _fmpz_vec_init(2 * a - 1);

            fmpz_pow_ui(pN, p, N);

            /* f := \hat{t_1}, g := r(\hat{t_1})^{-m} */
            _qadic_teichmuller(f, t1->coeffs, t1->length, Qq->a, Qq->j, Qq->len, p, N);
            if (prec->denR == NULL)
            {
                fmpz_t e;
                fmpz_init_set_ui(e, prec->m);
                _fmpz_mod_poly_compose_smod(g, r->coeffs, r->length, f, a,
                                            Qq->a, Qq->j, Qq->len, pN);
                _qadic_pow(t, g, a, e, Qq->a, Qq->j, Qq->len, pN);
                fmpz_clear(e);
            }
            else
            {
                _fmpz_mod_poly_reduce(prec->denR->coeffs, prec->denR->length, Qq->a, Qq->j, Qq->len, pN);
                _fmpz_poly_normalise(prec->denR);

                _fmpz_mod_poly_compose_smod(t, prec->denR->coeffs, prec->denR->length, f, a,
                                            Qq->a, Qq->j, Qq->len, pN);
            }
            _qadic_inv(g, t, a, Qq->a, Qq->j, Qq->len, p, N);

            /* F1 := g G(\hat{t_1}) */
            for (i = 0; i < b; i++)
                for (j = 0; j < b; j++)
                {
                    const fmpz_poly_struct *poly = fmpz_poly_mat_entry(F, i, j);
                    const long len               = poly->length;

                    fmpz_poly_struct *poly2 = fmpz_poly_mat_entry(F1, i, j);

                    if (len == 0)
                    {
                        fmpz_poly_zero(poly2);
                    }
                    else
                    {
                        _fmpz_mod_poly_compose_smod(t, poly->coeffs, len, f, a,
                                                    Qq->a, Qq->j, Qq->len, pN);

                        fmpz_poly_fit_length(poly2, 2 * a - 1);
                        _fmpz_poly_mul(poly2->coeffs, g, a, t, a);
                        _fmpz_mod_poly_reduce(poly2->coeffs, 2 * a - 1, Qq->a, Qq->j, Qq->len, pN);
                        _fmpz_poly_set_length(poly2, a);
                        _fmpz_poly_normalise(poly2);
                    }
                }

            /* Now the matrix for p^{-1} F_p at t=t_1 is (F1, vF1). */
            vF1 = vF;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(pN);
            _fmpz_vec_clear(f, a);
            _fmpz_vec_clear(g, 2 * a - 1);
            _fmpz_vec_clear(t, 2 * a - 1);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Evaluation:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }

        /* Step 7 {Norm} *****************************************************/
        /*
            Computes the matrix for $q^{-1} F_q$ at $t = t_1$ as the
            product $F \sigma(F) \dotsm \sigma^{a-1}(F)$ up appropriate
            transpositions because our convention of columns vs rows is
            the opposite of that used by Gerkmann.

            Note that, in any case, transpositions do not affect
            the characteristic polynomial.
         */

        c0 = clock();
        {
            const long N = prec->N1 - a * vF1;

            fmpz_t pN;
            fmpz_poly_mat_t T;

            fmpz_init(pN);
            fmpz_poly_mat_init(T, b, b);

            fmpz_pow_ui(pN, p, N);

            fmpz_poly_mat_frobenius(T, F1, 1, p, N, Qq);
            _qadic_mat_mul(F1, F1, T, pN, Qq);

            for (i = 2; i < a; i++)
            {
                fmpz_poly_mat_frobenius(T, T, 1, p, N, Qq);
                _qadic_mat_mul(F1, F1, T, pN, Qq);
            }

            vF1 = a * vF1;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(pN);
            fmpz_poly_mat_clear(T);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Norm:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }
    }

    /* Step 8 {Reverse characteristic polynomial} ****************************/

    c0 = clock();

    deformation_revcharpoly(cp, F1, vF1, n, d, prec->N0, prec->r, prec->s, Qq);

    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Reverse characteristic polynomial:\n");
        printf("  p(T) = "), fmpz_poly_print_pretty(cp, "T"), printf("\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Clean up **************************************************************/

    padic_mat_clear(F0);

    mat_clear(M, ctxFracQt);
    free(bR);
    free(bC);
    fmpz_poly_clear(r);

    fmpz_poly_mat_clear(C);
    fmpz_poly_mat_clear(Cinv);

    fmpz_poly_mat_clear(F);
    fmpz_poly_mat_clear(F1);
    fmpz_poly_clear(cp);
}
Example #5
0
void _qadic_norm_resultant(fmpz_t rop, const fmpz *op, slong len, 
                           const fmpz *a, const slong *j, slong lena, 
                           const fmpz_t p, slong N)
{
    const slong d = j[lena - 1];

    fmpz_t pN;

    fmpz_init(pN);
    fmpz_pow_ui(pN, p, N);

    if (len == 1)
    {
        fmpz_powm_ui(rop, op + 0, d, pN);
    }
    else  /* len >= 2 */
    {
        {
            const slong n = d + len - 1;
            slong i, k;
            fmpz *M;

            M = flint_calloc(n * n, sizeof(fmpz));

            for (k = 0; k < len-1; k++)
            {
                for (i = 0; i < lena; i++)
                {
                    M[k * n + k + (d - j[i])] = a[i];
                }
            }
            for (k = 0; k < d; k++)
            {
                for (i = 0; i < len; i++)
                {
                    M[(len-1 + k) * n + k + (len-1 - i)] = op[i];
                }
            }

            _fmpz_mod_mat_det(rop, M, n, pN);
            
            flint_free(M);
        }

        /*
            XXX:  This part of the code is currently untested as the Conway 
            polynomials used for the extension Qq/Qp are monic.
         */
        if (!fmpz_is_one(a + (lena - 1)))
        {
            fmpz_t f;

            fmpz_init(f);
            fmpz_powm_ui(f, a + (lena - 1), len - 1, pN);
            _padic_inv(f, f, p, N);
            fmpz_mul(rop, f, rop);
            fmpz_mod(rop, rop, pN);
            fmpz_clear(f);
        }
    }
    fmpz_clear(pN);
}
Example #6
0
void precompute_muex(fmpz **mu, long M, 
                     const long **C, const long *lenC, 
                     const fmpz *a, long n, long p, long N)
{
    const long ve = (p == 2) ? M / 4 + 1 : M / (p * (p - 1)) + 1;

    fmpz_t P, pNe, pe;
    fmpz_t apow, f, g, h;

    fmpz *nu;
    long *v;

    long i, j;

    fmpz_init_set_ui(P, p);
    fmpz_init(pNe);
    fmpz_init(pe);
    fmpz_pow_ui(pNe, P, N + ve);
    fmpz_pow_ui(pe, P, ve);

    fmpz_init(apow);
    fmpz_init(f);
    fmpz_init(g);
    fmpz_init(h);

    /* Precompute $(l!)^{-1}$ */
    nu = _fmpz_vec_init(M + 1);
    v  = malloc((M + 1) * sizeof(long));

    {
        long *D, lenD = 0, k = 0;

        for (i = 0; i <= n; i++)
            lenD += lenC[i];

        D = malloc(lenD * sizeof(long));

        for (i = 0; i <= n; i++)
            for (j = 0; j < lenC[i]; j++)
                D[k++] = C[i][j];

        _remove_duplicates(D, &lenD);
        _sort(D, lenD);

        precompute_nu(nu, v, M, D, lenD, p, N + ve);

        free(D);
    }

    for (i = 0; i <= n; i++)
    {
        long m = -1, quo, idx, w;
        fmpz *z;

        /* Set apow = a[i]^{-(p-1)} mod p^N */
        fmpz_invmod(apow, a + i, pNe);
        fmpz_powm_ui(apow, apow, p - 1, pNe);

        /*
            Run over all relevant m in [0, M]. 
            Note that lenC[i] > 0 for all i.
         */
        for (quo = 0; m <= M; quo++)
        {
            for (idx = 0; idx < lenC[i]; idx++)
            {
                m = quo * p + C[i][idx];

                if (m > M)
                    break;

                /*
                    Note that $\mu_m$ is equal to 
                    $\sum_{k=0}^{\floor{m/p}} p^{\floor{m/p}-k}\nu_{m-pk}\nu_k$
                    where $\nu_i$ denotes the number with unit part nu[i] 
                    and valuation v[i].
                 */
                w = (p == 2) ? (3 * m) / 4 - (m == 3 || m == 7) : m / p;
                z = mu[i] + lenC[i] * quo + idx;
                fmpz_zero(z);
                fmpz_one(h);
                for (j = 0; j <= m / p; j++)
                {
                    fmpz_pow_ui(f, P, ve + w - j + v[m - p*j] + v[j]);
                    fmpz_mul(g, nu + (m - p*j), nu + j);

                    fmpz_mul(f, f, g);
                    fmpz_mul(f, f, h);

                    fmpz_add(z, z, f);
                    fmpz_mod(z, z, pNe);

                    /* Set h = a[i]^{- (j+1)(p-1)} mod p^{N+e} */
                    fmpz_mul(h, h, apow);
                    fmpz_mod(h, h, pNe);
                }
                fmpz_divexact(z, z, pe);
            }
        }
    }

    fmpz_clear(P);
    fmpz_clear(pNe);
    fmpz_clear(pe);

    fmpz_clear(apow);
    fmpz_clear(f);
    fmpz_clear(g);
    fmpz_clear(h);

    _fmpz_vec_clear(nu, M + 1);
    free(v);
}