// Apply F(X)->F(X^k) followed by re-liearization. The automorphism is possibly // evaluated via a sequence of steps, to ensure that we can re-linearize the // result of every step. void Ctxt::smartAutomorph(long k) { FHE_TIMER_START; // Special case: if *this is empty then do nothing if (this->isEmpty()) return; long m = context.zMStar.getM(); k = mcMod(k, m); // Sanity check: verify that k \in Zm* assert (context.zMStar.inZmStar(k)); long keyID=getKeyID(); if (!inCanonicalForm(keyID)) { // Re-linearize the input, if needed reLinearize(keyID); assert (inCanonicalForm(keyID)); // ensure that re-linearization succeeded } assert (pubKey.isReachable(k,keyID)); // reachable from 1 while (k != 1) { const KeySwitch& matrix = pubKey.getNextKSWmatrix(k,keyID); long amt = matrix.fromKey.getPowerOfX(); automorph(amt); reLinearize(keyID); k = MulMod(k, InvMod(amt,m), m); } FHE_TIMER_STOP; }
// Apply F(X)->F(X^k) followed by re-liearization. The automorphism is possibly // evaluated via a sequence of steps, to ensure that we can re-linearize the // result of every step. void Ctxt::smartAutomorph(long k) { FHE_TIMER_START; // A hack: record this automorphism rather than actually performing it if (isSetAutomorphVals()) { // defined in NumbTh.h recordAutomorphVal(k); return; } // Special case: if *this is empty then do nothing if (this->isEmpty()) return; // Sanity check: verify that k \in Zm* long m = context.zMStar.getM(); k = mcMod(k, m); assert (context.zMStar.inZmStar(k)); long keyID=getKeyID(); if (!pubKey.isReachable(k,keyID)) {// must have key-switching matrices for it throw std::logic_error("no key-switching matrices for k="+std::to_string(k) + ", keyID="+std::to_string(keyID)); } if (!inCanonicalForm(keyID)) { // Re-linearize the input, if needed reLinearize(keyID); assert (inCanonicalForm(keyID)); // ensure that re-linearization succeeded } while (k != 1) { const KeySwitch& matrix = pubKey.getNextKSWmatrix(k,keyID); long amt = matrix.fromKey.getPowerOfX(); // A hack: record this automorphism rather than actually performing it if (isSetAutomorphVals2()) { // defined in NumbTh.h recordAutomorphVal2(amt); return; } //cerr << "********* automorph " << amt << "\n"; automorph(amt); reLinearize(keyID); k = MulMod(k, InvMod(amt,m), m); } FHE_TIMER_STOP; }