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_revert_series_lagrange(mp_ptr Qinv, mp_srcptr Q, long n, nmod_t mod) { long i; mp_ptr R, S, T, tmp; if (n >= 1) Qinv[0] = 0UL; if (n >= 2) Qinv[1] = n_invmod(Q[1], mod.n); if (n <= 2) return; R = _nmod_vec_init(n - 1); S = _nmod_vec_init(n - 1); T = _nmod_vec_init(n - 1); _nmod_poly_inv_series(R, Q + 1, n - 1, mod); _nmod_vec_set(S, R, n - 1); for (i = 2; i < n; i++) { _nmod_poly_mullow(T, S, n - 1, R, n - 1, n - 1, mod); Qinv[i] = nmod_div(T[i - 1], i, mod); tmp = S; S = T; T = tmp; } _nmod_vec_clear(R); _nmod_vec_clear(S); _nmod_vec_clear(T); }