void CanZass(vec_pair_GF2X_long& factors, const GF2X& f, long verbose) { if (IsZero(f)) Error("CanZass: bad args"); double t; vec_pair_GF2X_long sfd; vec_GF2X x; if (verbose) { cerr << "square-free decomposition..."; t = GetTime(); } SquareFreeDecomp(sfd, f); if (verbose) cerr << (GetTime()-t) << "\n"; factors.SetLength(0); long i, j; for (i = 0; i < sfd.length(); i++) { if (verbose) { cerr << "factoring multiplicity " << sfd[i].b << ", deg = " << deg(sfd[i].a) << "\n"; } SFCanZass(x, sfd[i].a, verbose); for (j = 0; j < x.length(); j++) append(factors, cons(x[j], sfd[i].b)); } }
template<> void PAlgebraModTmpl<zz_pX,vec_zz_pX,zz_pXModulus>::decodePlaintext( vector<zz_pX>& alphas, const zz_pX& ptxt, const zz_pX &G, const vector<zz_pX>& maps) const { unsigned nSlots = zmStar.NSlots(); if (nSlots==0 || maps.size()!= nSlots ||deg(G)<1|| zmStar.OrdTwo()%deg(G)!=0){ alphas.resize(0); return; } // First decompose p into CRT componsnt vector<zz_pX> CRTcomps(nSlots); // allocate space for CRT component CRT_decompoe(CRTcomps, ptxt); // CRTcomps[i] = p mod facors[i] // Next convert each entry in CRTcomps[] back to base-G representation // (this is roughly the inverse of the embedInSlots operation) // maps contains all the base-G ==> base-Fi maps // SHAI: The code below is supposed to be Nigel's code, borrowed partly // from the constructor Algebra::Algebra(...) and partly from the // function AElement::to_type(2). I don't really unerstand that code, // so hopefully nothing was lost in translation alphas.resize(nSlots); zz_pE::init(G); // the extension field R[X]/G(X) for (unsigned i=0; i<nSlots; i++) { // We need to lift Fi from R[Y] to (R[X]/G(X))[Y] zz_pEX Qi; conv(Qi,(zz_pX&)factors[i]); vec_zz_pEX FRts=SFCanZass(Qi); // factor Fi over Z_2[X]/G(X) // need to choose the right factor, the one that gives us back X int j; for (j=0; j<FRts.length(); j++) { // lift maps[i] to (R[X]/G(X))[Y] and reduce mod j'th factor of Fi zz_pEX GRti = to_zz_pEX((zz_pX&)maps[i]); GRti %= FRts[j]; if (IsX(rep(coeff(GRti,0)))) { // is GRti == X? Qi = FRts[j]; // If so, we found the right factor break; } // If this does not happen then move to the next factor of Fi } zz_pEX te; conv(te,CRTcomps[i]); // lift i'th CRT componnet to mod G(X) te %= Qi; // reduce CRTcomps[i](Y) mod Qi(Y), over (Z_2[X]/G(X)) // the free term (no Y component) should be our answer (as a poly(X)) alphas[i] = rep(coeff(te,0)); } }
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"; }