static void compute_a_vals(Vec<ZZ>& a, long p, long e) // computes a[m] = a(m)/m! for m = p..(e-1)(p-1)+1, // as defined by Chen and Han. // a.length() is set to (e-1)(p-1)+2 { ZZ p_to_e = power_ZZ(p, e); ZZ p_to_2e = power_ZZ(p, 2*e); long len = (e-1)*(p-1)+2; ZZ_pPush push(p_to_2e); ZZ_pX x_plus_1_to_p = power(ZZ_pX(INIT_MONO, 1) + 1, p); ZZ_pX denom = InvTrunc(x_plus_1_to_p - ZZ_pX(INIT_MONO, p), len); ZZ_pX poly = MulTrunc(x_plus_1_to_p, denom, len); poly *= p; a.SetLength(len); ZZ m_fac(1); for (long m = 2; m < p; m++) { m_fac = MulMod(m_fac, m, p_to_2e); } for (long m = p; m < len; m++) { m_fac = MulMod(m_fac, m, p_to_2e); ZZ c = rep(coeff(poly, m)); ZZ d = GCD(m_fac, p_to_2e); if (d == 0 || d > p_to_e || c % d != 0) Error("cannot divide"); ZZ m_fac_deflated = (m_fac / d) % p_to_e; ZZ c_deflated = (c / d) % p_to_e; a[m] = MulMod(c_deflated, InvMod(m_fac_deflated, p_to_e), p_to_e); } }
static CYTHON_INLINE struct ZZ_pX ZZ_pE_to_ZZ_pX(struct ZZ_pE x) { return ZZ_pX(rep(x)); }