// X_i^p = X_i void nmod_multi_poly_mod_fermat(mp_ptr f_bar, const mp_ptr f, slong p, slong d, slong m, const slong* P) { if(p < d) { slong i, cpt, *pos, coord_p; _nmod_vec_zero(f_bar,n_pow(p,m)); pos = (slong*)calloc(sizeof(slong),m); coord_p; cpt = 0; while(pos[m-1] != d) { coord_p = Coord_mod(P,p,pos,m); f_bar[coord_p] = n_addmod(f_bar[coord_p],f[cpt],p); pos[0]++; cpt++; i = 0; while( (pos[i] == d) && (i != (m-1)) ) { pos[i] = 0; // Le i est incrémenté avant pos++ pos[++i]++; } } free(pos); } }
void partition_function_nmod_vec(mp_ptr res, long len, nmod_t mod) { mp_ptr tmp; mp_limb_t r; long k, n; r = mod.n - 1UL; if (len < 1) return; tmp = _nmod_vec_init(len); _nmod_vec_zero(tmp, len); tmp[0] = 1UL; for (n = k = 1; n + 4*k + 2 < len; k += 2) { tmp[n] = r; tmp[n + k] = r; tmp[n + 3*k + 1] = 1UL; tmp[n + 4*k + 2] = 1UL; n += 6*k + 5; } if (n < len) tmp[n] = r; if (n + k < len) tmp[n + k] = r; if (n + 3*k + 1 < len) tmp[n + 3*k + 1] = 1L; _nmod_poly_inv_series(res, tmp, len, mod); _nmod_vec_free(tmp); }
void nmod_poly_randtest_pentomial(nmod_poly_t poly, flint_rand_t state, slong len) { nmod_poly_fit_length(poly, len); _nmod_vec_zero(poly->coeffs, len); poly->coeffs[0] = n_randtest(state) % poly->mod.n; poly->coeffs[1] = n_randtest(state) % poly->mod.n; poly->coeffs[2] = n_randtest(state) % poly->mod.n; poly->coeffs[3] = n_randtest(state) % poly->mod.n; poly->coeffs[len - 1] = 1; _nmod_poly_set_length(poly, len); }
void nmod_poly_randtest_trinomial(nmod_poly_t poly, flint_rand_t state, slong len) { ulong k; nmod_poly_fit_length(poly, len); _nmod_vec_zero(poly->coeffs, len); poly->coeffs[0] = n_randtest(state) % poly->mod.n; poly->coeffs[len - 1] = 1; k = (n_randtest(state) % (len - 2)) + 1; poly->coeffs[k] = n_randtest(state) % poly->mod.n; _nmod_poly_set_length(poly, len); }
void __nmod_poly_exp_series_prealloc(mp_ptr f, mp_ptr g, mp_srcptr h, mp_srcptr hprime, mp_ptr T, mp_ptr U, long n, nmod_t mod, int extend) { long m, m2, l; if (n < NMOD_NEWTON_EXP_CUTOFF) { _nmod_poly_exp_series_basecase(f, h, n, n, mod); _nmod_poly_inv_series_basecase(g, f, extend ? n : (n + 1) / 2, mod); return; } m = (n + 1) / 2; m2 = (m + 1) / 2; l = m - 1; /* shifted for derivative */ /* f := exp(h) + O(x^m), g := exp(-h) + O(x^m2) */ __nmod_poly_exp_series_prealloc(f, g, h, hprime, T, U, m, mod, 0); /* g := exp(-h) + O(x^m) */ _nmod_poly_mullow(T, f, m, g, m2, m, mod); _nmod_poly_mullow(g + m2, g, m2, T + m2, m - m2, m - m2, mod); _nmod_vec_neg(g + m2, g + m2, m - m2, mod); /* U := h' + g (f' - f h') + O(x^(n-1)) Note: should replace h' by h' mod x^(m-1) */ _nmod_vec_zero(f + m, n - m); _nmod_poly_mullow(T, f, n, hprime, n, n, mod); /* should be mulmid */ _nmod_poly_derivative(U, f, n, mod); /* should skip low terms */ _nmod_vec_sub(U + l, U + l, T + l, n - l, mod); _nmod_poly_mullow(T + l, g, n - m, U + l, n - m, n - m, mod); _nmod_vec_add(U + l, hprime + l, T + l, n - m, mod); /* f := f + f * (h - int U) + O(x^n) = exp(h) + O(x^n) */ _nmod_poly_integral(U, U, n, mod); /* should skip low terms */ _nmod_vec_sub(U + m, h + m, U + m, n - m, mod); _nmod_poly_mullow(f + m, f, n - m, U + m, n - m, n - m, mod); /* g := exp(-h) + O(x^n) */ if (extend) { _nmod_poly_mullow(T, f, n, g, m, n, mod); _nmod_poly_mullow(g + m, g, m, T + m, n - m, n - m, mod); _nmod_vec_neg(g + m, g + m, n - m, mod); } }
void _fq_nmod_trace(fmpz_t rop2, const mp_limb_t *op, slong len, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); ulong i, l; mp_limb_t *t, rop; t = _nmod_vec_init(d); _nmod_vec_zero(t, d); t[0] = n_mod2_preinv(d, ctx->mod.n, ctx->mod.ninv); for (i = 1; i < d; i++) { for (l = ctx->len - 2; l >= 0 && ctx->j[l] >= d - (i - 1); l--) { t[i] = n_addmod(t[i], n_mulmod2_preinv(t[ctx->j[l] + i - d], ctx->a[l], ctx->mod.n, ctx->mod.ninv), ctx->mod.n); } if (l >= 0 && ctx->j[l] == d - i) { t[i] = n_addmod(t[i], n_mulmod2_preinv(ctx->a[l], i, ctx->mod.n, ctx->mod.ninv), ctx->mod.n); } t[i] = n_negmod(t[i], ctx->mod.n); } rop = WORD(0); for (i = 0; i < d; i++) { rop = n_addmod(rop, n_mulmod2_preinv(op[i], t[i], ctx->mod.n, ctx->mod.ninv), ctx->mod.n); } _nmod_vec_clear(t); fmpz_set_ui(rop2, rop); }
void _nmod_poly_exp_series_monomial_ui(mp_ptr res, mp_limb_t coeff, ulong power, slong n, nmod_t mod) { slong k, r; mp_limb_t rfac; mp_limb_t a; r = (n - 1) / power; rfac = n_factorial_mod2_preinv(r, mod.n, mod.ninv); rfac = n_invmod(rfac, mod.n); if (power > 1) _nmod_vec_zero(res, n); res[0] = UWORD(1); if (coeff == UWORD(1)) { a = rfac; for (k = r; k >= 1; k--) { res[k * power] = a; a = n_mulmod2_preinv(a, k, mod.n, mod.ninv); } } else { a = coeff; for (k = power; k < n; k += power) { res[k] = a; a = n_mulmod2_preinv(a, coeff, mod.n, mod.ninv); } a = rfac; for (k = r; k >= 1; k--) { res[k * power] = n_mulmod2_preinv(res[k * power], a, mod.n, mod.ninv); a = n_mulmod2_preinv(a, k, mod.n, mod.ninv); } } }
void _nmod_poly_interpolate_nmod_vec_barycentric(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod) { mp_ptr P, Q, w; slong i, j; if (n == 1) { poly[0] = ys[0]; return; } P = _nmod_vec_init(n + 1); Q = _nmod_vec_init(n); w = _nmod_vec_init(n); _nmod_poly_product_roots_nmod_vec(P, xs, n, mod); for (i = 0; i < n; i++) { w[i] = UWORD(1); for (j = 0; j < n; j++) { if (i != j) w[i] = nmod_mul(w[i], nmod_sub(xs[i], xs[j], mod), mod); } w[i] = n_invmod(w[i], mod.n); } _nmod_vec_zero(poly, n); for (i = 0; i < n; i++) { _nmod_poly_div_root(Q, P, n + 1, xs[i], mod); _nmod_vec_scalar_addmul_nmod(poly, Q, n, nmod_mul(w[i], ys[i], mod), mod); } _nmod_vec_clear(P); _nmod_vec_clear(Q); _nmod_vec_clear(w); }
void _nmod_poly_compose_series_horner(mp_ptr res, mp_srcptr poly1, long len1, mp_srcptr poly2, long len2, long n, nmod_t mod) { if (n == 1) { res[0] = poly1[0]; } else { long i = len1 - 1; long lenr; mp_ptr t = _nmod_vec_init(n); lenr = len2; _nmod_vec_scalar_mul_nmod(res, poly2, len2, poly1[i], mod); i--; res[0] = nmod_add(res[0], poly1[i], mod); while (i > 0) { i--; if (lenr + len2 - 1 < n) { _nmod_poly_mul(t, res, lenr, poly2, len2, mod); lenr = lenr + len2 - 1; } else { _nmod_poly_mullow(t, res, lenr, poly2, len2, n, mod); lenr = n; } _nmod_poly_add(res, t, lenr, poly1 + i, 1, mod); } _nmod_vec_zero(res + lenr, n - lenr); _nmod_vec_clear(t); } }
void _fq_nmod_pow(mp_limb_t *rop, const mp_limb_t *op, slong len, const fmpz_t e, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); if (fmpz_is_zero(e)) { rop[0] = WORD(1); _nmod_vec_zero(rop + 1, 2 * d - 1 - 1); } else if (fmpz_is_one(e)) { _nmod_vec_set(rop, op, len); _nmod_vec_zero(rop + len, 2 * d - 1 - len); } else { ulong bit; mp_limb_t *v = _nmod_vec_init(2 * d - 1); mp_limb_t *R, *S, *T; _nmod_vec_zero(v, 2 * d - 1); _nmod_vec_zero(rop, 2 * d - 1); /* Set bits to the bitmask with a 1 one place lower than the msb of e */ bit = fmpz_bits(e) - 2; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if (fmpz_tstbit(e, bit2)) swaps = ~swaps; while (bit2--) if (!fmpz_tstbit(e, bit2)) swaps = ~swaps; if (swaps == 0U) { R = rop; S = v; } else { R = v; S = rop; } } /* We unroll the first step of the loop, referring to {op, len} */ _nmod_poly_mul(R, op, len, op, len, ctx->mod); _fq_nmod_reduce(R, 2 * len - 1, ctx); if (fmpz_tstbit(e, bit)) { _nmod_poly_mul(S, R, d, op, len, ctx->mod); _fq_nmod_reduce(S, d + len - 1, ctx); T = R; R = S; S = T; } while (bit--) { if (fmpz_tstbit(e, bit)) { _nmod_poly_mul(S, R, d, R, d, ctx->mod); _fq_nmod_reduce(S, 2 * d - 1, ctx); _nmod_poly_mul(R, S, d, op, len, ctx->mod); _fq_nmod_reduce(R, d + len - 1, ctx); } else { _nmod_poly_mul(S, R, d, R, d, ctx->mod); _fq_nmod_reduce(S, 2 * d - 1, ctx); T = R; R = S; S = T; } } _nmod_vec_clear(v); } }