void PAlgebraLift(const ZZX& phimx, const vec_zz_pX& lfactors, vec_zz_pX& factors, vec_zz_pX& crtc, long r) { long p = zz_p::modulus(); long nSlots = lfactors.length(); vec_ZZX vzz; // need to go via ZZX // lift the factors of Phi_m(X) from mod-2 to mod-2^r if (lfactors.length() > 1) MultiLift(vzz, lfactors, phimx, r); // defined in NTL::ZZXFactoring else { vzz.SetLength(1); vzz[0] = phimx; } // Compute the zz_pContext object for mod p^r arithmetic zz_p::init(power_long(p, r)); zz_pX phimxmod = to_zz_pX(phimx); factors.SetLength(nSlots); for (long i=0; i<nSlots; i++) // Convert from ZZX to zz_pX conv(factors[i], vzz[i]); // Finally compute the CRT coefficients for the factors crtc.SetLength(nSlots); for (long i=0; i<nSlots; i++) { zz_pX& fct = factors[i]; zz_pX te = phimxmod / fct; // \prod_{j\ne i} Fj te %= fct; // \prod_{j\ne i} Fj mod Fi InvModpr(crtc[i], te, fct, p, r);// \prod_{j\ne i} Fj^{-1} mod Fi } }
void PAlgebraMod2r::init(unsigned r, unsigned m) { if (m == zmStar.M()) return; // nothign to do if (r<2 || r>=NTL_SP_NBITS) return; // sanity check ((PAlgebraModTwo&)modTwo).init(m); // initialize zmStar and modTwo, if needed if (zmStar.M()==0 || zmStar.NSlots()==0) return; // error in zmStar init long nSlots = zmStar.NSlots(); // Take the factors and their CRT coefficients mod 2 and lift them to mod 2^r zz_p::init(2); // convert the factors of Phi_m(X) from GF2X to zz_pX objects with p=2 vec_zz_pX vzzp; // no direct conversion from GF2X to zz_pX, vec_ZZX vzz; // need to go via ZZX vzzp.SetLength(nSlots); vzz.SetLength(nSlots); for (long i=0; i<nSlots; i++) { vzz[i] = to_ZZX(modTwo.factors[i]); conv(vzzp[i], vzz[i]); } // lift the factors of Phi_m(X) from mod-2 to mod-2^r MultiLift(vzz, vzzp, zmStar.PhimX(), r); // defined in NTL::ZZXFactoring // Compute the zz_pContext object for mod-2^r arithmetic rr = r; unsigned two2r = 1UL << r; // compute 2^r zz_p::init(two2r); mod2rContext.save(); PhimXmod = to_zz_pX(zmStar.PhimX()); // Phi_m(X) mod 2^r factors.SetLength(nSlots); for (long i=0; i<nSlots; i++) // Convert from ZZX to zz_pX conv(factors[i],vzz[i]); /* Debugging sanity-check #1: we should have Ft= GCD(F1(X^t),Phi_m(X)) zz_pXModulus F1(factors[0]); // We choose factors[0] as F1 zz_pXModulus Pm2(PhimXmod); for (long i=1; i<nSlots; i++) { unsigned t = zmStar.ith_rep(i); zz_pX X2t = PowerXMod(t,PhimXmod); // X2t = X^t mod Phi_m(X) zz_pX Ft = GCD(CompMod(F1,X2t,Pm2),Pm2); if (Ft != factors[i]) { cout << "Ft != F1(X^t) mod Phi_m(X), t=" << t << endl; exit(0); } }*******************************************************************/ // Finally compute the CRT coefficients for the factors crtCoeffs.SetLength(nSlots); for (long i=0; i<nSlots; i++) { zz_pX& fct = factors[i]; zz_pX te = PhimXmod / fct; // \prod_{j\ne i} Fj te %= fct; // \prod_{j\ne i} Fj mod Fi InvMod(crtCoeffs[i], te, fct);// \prod_{j\ne i} Fj^{-1} mod Fi } }
int main(int argc, char *argv[]) { argmap_t argmap; argmap["p"] = "5"; argmap["m"] = "101"; argmap["r"] = "1"; if (!parseArgs(argc, argv, argmap)) usage(argv[0]); long p = atoi(argmap["p"]); long m = atoi(argmap["m"]); long r = atoi(argmap["r"]); cout << "p=" << p << ", m=" << m << ", r=" << r << "\n"; ZZX phimx = Cyclotomic(m); zz_p::init(p); zz_pX phimx_modp = to_zz_pX(phimx); vec_zz_pX factors = SFCanZass(phimx_modp); vec_ZZX FFactors; MultiLift(FFactors, factors, phimx, r); zz_p::init(power_long(p, r)); vec_zz_pX Factors; Factors.SetLength(FFactors.length()); for (long i = 0; i < Factors.length(); i++) conv(Factors[i], FFactors[i]); zz_pX G = Factors[0]; long d = deg(G); cout << "d=" << d << "\n"; zz_pE::init(G); // L selects the even coefficients vec_zz_pE L; L.SetLength(d); for (long j = 0; j < d; j++) { if (j % 2 == 0) L[j] = to_zz_pE(zz_pX(j, 1)); } vec_zz_pE C; buildLinPolyCoeffs(C, L, p, r); zz_pE alpha, beta; random(alpha); applyLinPoly(beta, C, alpha, p); cout << alpha << "\n"; cout << beta << "\n"; }