// incrementalZeroTest sets each res[i], for i=0..n-1, to // a ciphertext in which each slot is 0 or 1 according // to whether or not bits 0..i of corresponding slot in ctxt // is zero (1 if not zero, 0 if zero). // It is assumed that res and each res[i] is already initialized // by the caller. // Complexity: O(d + n log d) smart automorphisms // O(n d) void incrementalZeroTest(Ctxt* res[], const EncryptedArray& ea, const Ctxt& ctxt, long n) { FHE_TIMER_START; long nslots = ea.size(); long d = ea.getDegree(); // compute linearized polynomial coefficients vector< vector<ZZX> > Coeff; Coeff.resize(n); for (long i = 0; i < n; i++) { // coeffients for mask on bits 0..i // L[j] = X^j for j = 0..i, L[j] = 0 for j = i+1..d-1 vector<ZZX> L; L.resize(d); for (long j = 0; j <= i; j++) SetCoeff(L[j], j); vector<ZZX> C; ea.buildLinPolyCoeffs(C, L); Coeff[i].resize(d); for (long j = 0; j < d; j++) { // Coeff[i][j] = to the encoding that has C[j] in all slots // FIXME: maybe encrtpted array should have this functionality // built in vector<ZZX> T; T.resize(nslots); for (long s = 0; s < nslots; s++) T[s] = C[j]; ea.encode(Coeff[i][j], T); } } vector<Ctxt> Conj(d, ctxt); // initialize Cong[j] to ctxt^{2^j} for (long j = 0; j < d; j++) { Conj[j].smartAutomorph(1L << j); } for (long i = 0; i < n; i++) { res[i]->clear(); for (long j = 0; j < d; j++) { Ctxt tmp = Conj[j]; tmp.multByConstant(Coeff[i][j]); *res[i] += tmp; } // *res[i] now has 0..i in each slot // next, we raise to the power 2^d-1 fastPower(*res[i], d); } FHE_TIMER_STOP; }
/** * @brief Extract coefficients from ciphertext polynomial * @param coeffs extracted coefficients * @param ctxt ciphertext * @param n extract "n" lowest degree coefficients */ void extractCoeffs(EncryptedArray& ea, vector<Ctxt>& coeffs, Ctxt& ctxt, long n) { long d = ea.getDegree(); if (d < n) n = d; coeffs.clear(); vector<Ctxt> conj; for (int coeff = 0; coeff < n; ++coeff) { vector<ZZX> LM(d); LM[coeff] = ZZX(0, 1); // "building" the linearized-polynomial coefficients vector<ZZX> C(d); ea.buildLinPolyCoeffs(C, LM); coeffs.push_back(ctxt); applyLinPoly1(ea, coeffs[coeff], C, conj); } }