int fmpz_invmod_ui(fmpz_t f, const fmpz_t g, const uint32_t mod) { fmpz_t modulus; fmpz_init_set_ui(modulus, mod); return fmpz_invmod(f, g, modulus); }
void fmpz_mod_poly_div_basecase(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B) { const long lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; fmpz *q; fmpz_t invB; if (lenA < lenB) { fmpz_mod_poly_zero(Q); return; } fmpz_init(invB); fmpz_invmod(invB, B->coeffs + (lenB - 1), &(B->p)); if (Q == A || Q == B) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ); q = Q->coeffs; } _fmpz_mod_poly_div_basecase(q, NULL, A->coeffs, lenA, B->coeffs, lenB, invB, &(B->p)); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } fmpz_clear(invB); }
void fmpz_mod_poly_radix_init(fmpz_mod_poly_radix_t D, const fmpz_mod_poly_t R, long degF) { const long degR = R->length - 1; if (degF < degR) { D->k = 0; } else { const long N = degF / degR; const long k = FLINT_BIT_COUNT(N); /* k := ceil{log{N+1}} */ const long lenV = degR * ((1L << k) - 1) + k; const long lenW = degR * ((1L << k) - 1); long i; D->V = _fmpz_vec_init(lenV + lenW); D->W = D->V + lenV; D->Rpow = flint_malloc(k * sizeof(fmpz *)); D->Rinv = flint_malloc(k * sizeof(fmpz *)); for (i = 0; i < k; i++) { D->Rpow[i] = D->V + (degR * ((1L << i) - 1) + i); D->Rinv[i] = D->W + (degR * ((1L << i) - 1)); } fmpz_init(&(D->invL)); fmpz_invmod(&(D->invL), R->coeffs + degR, &(R->p)); _fmpz_mod_poly_radix_init(D->Rpow, D->Rinv, R->coeffs, degR + 1, k, &(D->invL), &(R->p)); D->k = k; D->degR = degR; } }
void fmpz_mod_poly_make_monic(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly) { const slong len = poly->length; fmpz_t inv; if (len == 0) { fmpz_mod_poly_zero(res); return; } fmpz_init(inv); fmpz_invmod(inv, fmpz_mod_poly_lead(poly), &(poly->p)); fmpz_mod_poly_fit_length(res, len); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_scalar_mul_fmpz(res->coeffs, poly->coeffs, len, inv, &(poly->p)); fmpz_clear(inv); }
long _fmpz_poly_hensel_start_lift(fmpz_poly_factor_t lifted_fac, long *link, fmpz_poly_t *v, fmpz_poly_t *w, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, long N) { const long r = local_fac->num; long i, preve; fmpz_t p, P; fmpz_poly_t monic_f; fmpz_init(p); fmpz_init(P); fmpz_poly_init(monic_f); fmpz_set_ui(p, (local_fac->p + 0)->mod.n); fmpz_pow_ui(P, p, N); if (fmpz_is_one(fmpz_poly_lead(f))) { fmpz_poly_set(monic_f, f); } else if (fmpz_cmp_si(fmpz_poly_lead(f), -1) == 0) { fmpz_poly_neg(monic_f, f); } else { fmpz_t t; fmpz_init(t); fmpz_mod(t, fmpz_poly_lead(f), P); if (fmpz_invmod(t, t, P) == 0) { printf("Exception in fmpz_poly_start_hensel_lift.\n"); abort(); } fmpz_poly_scalar_mul_fmpz(monic_f, f, t); fmpz_poly_scalar_mod_fmpz(monic_f, monic_f, P); fmpz_clear(t); } fmpz_poly_hensel_build_tree(link, v, w, local_fac); { long *e, n = FLINT_CLOG2(N) + 1; e = flint_malloc(n * sizeof(long)); for (e[i = 0] = N; e[i] > 1; i++) e[i + 1] = (e[i] + 1) / 2; for (i--; i > 0; i--) { fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, p, e[i+1], e[i], 1); } if (N > 1) { fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, p, e[i+1], e[i], 0); } preve = e[i+1]; flint_free(e); } /* Now everything is lifted to p^N, we just need to insert the factors into their correct places in lifted_fac. */ fmpz_poly_factor_fit_length(lifted_fac, r); for (i = 0; i < 2*r - 2; i++) { if (link[i] < 0) { fmpz_poly_scalar_smod_fmpz(lifted_fac->p + (- link[i] - 1), v[i], P); lifted_fac->exp[- link[i] - 1] = 1L; } } lifted_fac->num = r; fmpz_clear(p); fmpz_clear(P); fmpz_poly_clear(monic_f); return preve; }
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); }