void Ctxt::multiplyBy2(const Ctxt& other1, const Ctxt& other2) { // Special case: if *this is empty then do nothing if (this->isEmpty()) return; long lvl = findBaseLevel(); long lvl1 = other1.findBaseLevel(); long lvl2 = other2.findBaseLevel(); if (lvl<lvl1 && lvl<lvl2){ // if both others at higher levels than this, Ctxt tmp = other1; // multiply others by each other, then by this if (&other1 == &other2) tmp *= tmp; // squaring rather than multiplication else tmp *= other2; *this *= tmp; } else if (lvl<lvl2) { // lvl1<=lvl<lvl2, multiply by other2, then by other1 *this *= other2; *this *= other1; } else { // multiply first by other1, then by other2 *this *= other1; *this *= other2; } reLinearize(); // re-linearize after all the multiplications }
void Ctxt::multiplyBy2(const Ctxt& other1, const Ctxt& other2) { FHE_TIMER_START; // Special case: if *this is empty then do nothing if (this->isEmpty()) return; long lvl = findBaseLevel(); long lvl1 = other1.findBaseLevel(); long lvl2 = other2.findBaseLevel(); if (lvl<lvl1 && lvl<lvl2){ // if both others at higher levels than this, Ctxt tmp = other1; // multiply others by each other, then by this if (&other1 == &other2) tmp *= tmp; // squaring rather than multiplication else tmp *= other2; *this *= tmp; reLinearize(); // re-linearize after all the multiplications return; } const Ctxt *first, *second; if (lvl<lvl2) { // lvl1<=lvl<lvl2, multiply by other2, then by other1 first = &other2; second = &other1; } else { // multiply first by other1, then by other2 first = &other1; second = &other2; } if (this == second) { // handle pointer collision Ctxt tmp = *second; *this *= *first; *this *= tmp; if (this == first) // cubing operation noiseVar *= 3; // a correction factor due to dependency else noiseVar *= 2; // a correction factor due to dependency } else { *this *= *first; *this *= *second; } reLinearize(); // re-linearize after all the multiplications }
void decryptAndPrint(ostream& s, const Ctxt& ctxt, const FHESecKey& sk, const EncryptedArray& ea, long flags) { const FHEcontext& context = ctxt.getContext(); xdouble noiseEst = sqrt(ctxt.getNoiseVar()); xdouble modulus = xexp(context.logOfProduct(ctxt.getPrimeSet())); vector<ZZX> ptxt; ZZX p, pp; sk.Decrypt(p, ctxt, pp); s << "plaintext space mod "<<ctxt.getPtxtSpace() << ", level="<<ctxt.findBaseLevel() << ", \n |noise|=q*" << (coeffsL2Norm(pp)/modulus) << ", |noiseEst|=q*" << (noiseEst/modulus) <<endl; if (flags & FLAG_PRINT_ZZX) { s << " before mod-p reduction="; printZZX(s,pp) <<endl; } if (flags & FLAG_PRINT_POLY) { s << " after mod-p reduction="; printZZX(s,p) <<endl; } if (flags & FLAG_PRINT_VEC) { ea.decode(ptxt, p); if (ea.getAlMod().getTag() == PA_zz_p_tag && ctxt.getPtxtSpace() != ea.getAlMod().getPPowR()) { long g = GCD(ctxt.getPtxtSpace(), ea.getAlMod().getPPowR()); for (long i=0; i<ea.size(); i++) PolyRed(ptxt[i], g, true); } s << " decoded to "; if (deg(p) < 40) // just pring the whole thing s << ptxt << endl; else if (ptxt.size()==1) // a single slot printZZX(s, ptxt[0]) <<endl; else { // print first and last slots printZZX(s, ptxt[0],20) << "--"; printZZX(s, ptxt[ptxt.size()-1], 20) <<endl; } } }