Exemplo n.º 1
0
// Extract digits from fully packed slots
void extractDigitsPacked(Ctxt& ctxt, long botHigh, long r, long ePrime,
			 const vector<ZZX>& unpackSlotEncoding)
{
  FHE_TIMER_START;

  // Step 1: unpack the slots of ctxt
  FHE_NTIMER_START(unpack);
  ctxt.cleanUp();

  // Apply the d automorphisms and store them in scratch area
  long d = ctxt.getContext().zMStar.getOrdP();

  vector<Ctxt> scratch; // used below 
  vector<Ctxt> unpacked(d, Ctxt(ZeroCtxtLike, ctxt));
  { // explicit scope to force all temporaries to be released
    vector< shared_ptr<DoubleCRT> > coeff_vector;
    coeff_vector.resize(d);
    for (long i = 0; i < d; i++)
      coeff_vector[i] = shared_ptr<DoubleCRT>(new 
        DoubleCRT(unpackSlotEncoding[i], ctxt.getContext(), ctxt.getPrimeSet()) );
    Ctxt tmp1(ZeroCtxtLike, ctxt);
    Ctxt tmp2(ZeroCtxtLike, ctxt);

    // FIXME: implement using hoisting!
    for (long j = 0; j < d; j++) { // process jth Frobenius 
      tmp1 = ctxt;
      tmp1.frobeniusAutomorph(j);
      tmp1.cleanUp();
      // FIXME: not clear if we should call cleanUp here

      for (long i = 0; i < d; i++) {
        tmp2 = tmp1;
        tmp2.multByConstant(*coeff_vector[mcMod(i+j, d)]);
        unpacked[i] += tmp2;
      }
    }
  }
  FHE_NTIMER_STOP(unpack);

  // Step 2: extract the digits top-1,...,0 from the slots of unpacked[i]
  long p = ctxt.getContext().zMStar.getP();
  long p2r = power_long(p,r);
  long topHigh = botHigh + r-1;

#ifdef DEBUG_PRINTOUT
  cerr << "+ After unpack ";
  decryptAndPrint(cerr, unpacked[0], *dbgKey, *dbgEa, printFlag);
  cerr << "    extracting "<<(topHigh+1)<<" digits\n";
#endif

  if (p==2 && r>2)
    topHigh--; // For p==2 we sometime get a bit for free

  FHE_NTIMER_START(extractDigits);
  for (long i=0; i<(long)unpacked.size(); i++) {
    if (topHigh<=0) { // extracting LSB = no-op
      scratch.assign(1,unpacked[i]);
    } else {          // extract digits topHigh...0, store them in scratch
      extractDigits(scratch, unpacked[i], topHigh+1);
    }

    // set upacked[i] = -\sum_{j=botHigh}^{topHigh} scratch[j] * p^{j-botHigh}
    if (topHigh >= (long)scratch.size()) {
      topHigh = scratch.size() -1;
      cerr << " @ suspect: not enough digits in extractDigitsPacked\n";
    }

    unpacked[i] = scratch[topHigh];
    for (long j=topHigh-1; j>=botHigh; --j) {
      unpacked[i].multByP();
      unpacked[i] += scratch[j];
    }
    if (p==2 && botHigh>0)   // For p==2, subtract also the previous bit
      unpacked[i] += scratch[botHigh-1];
    unpacked[i].negate();

    if (r>ePrime) {          // Add in digits from the bottom part, if any
      long topLow = r-1 - ePrime;
      Ctxt tmp = scratch[topLow];
      for (long j=topLow-1; j>=0; --j) {
	tmp.multByP();
	tmp += scratch[j];
      }
      if (ePrime>0)
	tmp.multByP(ePrime); // multiply by p^e'
      unpacked[i] += tmp;
    }
    unpacked[i].reducePtxtSpace(p2r); // Our plaintext space is now mod p^r
  }
  FHE_NTIMER_STOP(extractDigits);

#ifdef DEBUG_PRINTOUT
  cerr << "+ Before repack ";
  decryptAndPrint(cerr, unpacked[0], *dbgKey, *dbgEa, printFlag);
#endif

  // Step 3: re-pack the slots
  FHE_NTIMER_START(repack);
  const EncryptedArray& ea2 = *ctxt.getContext().ea;
  ZZX xInSlots;
  vector<ZZX> xVec(ea2.size());
  ctxt = unpacked[0];
  for (long i=1; i<d; i++) {
    x2iInSlots(xInSlots, i, xVec, ea2);
    unpacked[i].multByConstant(xInSlots);
    ctxt += unpacked[i];
  }
  FHE_NTIMER_STOP(repack);
}
Exemplo n.º 2
0
// Extract digits from thinly packed slots
void extractDigitsThin(Ctxt& ctxt, long botHigh, long r, long ePrime)
{
  FHE_TIMER_START;

  Ctxt unpacked(ctxt);
  unpacked.cleanUp();

  vector<Ctxt> scratch;


  // Step 2: extract the digits top-1,...,0 from the slots of unpacked[i]
  long p = ctxt.getContext().zMStar.getP();
  long p2r = power_long(p,r);
  long topHigh = botHigh + r-1;

#ifdef DEBUG_PRINTOUT
  cerr << "+ After unpack ";
  decryptAndPrint(cerr, unpacked, *dbgKey, *dbgEa, printFlag);
  cerr << "    extracting "<<(topHigh+1)<<" digits\n";
#endif

  if (p==2 && r>2)
    topHigh--; // For p==2 we sometime get a bit for free

  if (topHigh<=0) { // extracting LSB = no-op
    scratch.assign(1, unpacked);
  } else {          // extract digits topHigh...0, store them in scratch
    extractDigits(scratch, unpacked, topHigh+1);
  }

  // set upacked = -\sum_{j=botHigh}^{topHigh} scratch[j] * p^{j-botHigh}
  if (topHigh >= LONG(scratch.size())) {
    topHigh = scratch.size() -1;
    cerr << " @ suspect: not enough digits in extractDigitsPacked\n";
  }

  unpacked = scratch[topHigh];
  for (long j=topHigh-1; j>=botHigh; --j) {
    unpacked.multByP();
    unpacked += scratch[j];
  }
  if (p==2 && botHigh>0)   // For p==2, subtract also the previous bit
    unpacked += scratch[botHigh-1];
  unpacked.negate();

  if (r>ePrime) {          // Add in digits from the bottom part, if any
    long topLow = r-1 - ePrime;
    Ctxt tmp = scratch[topLow];
    for (long j=topLow-1; j>=0; --j) {
      tmp.multByP();
      tmp += scratch[j];
    }
    if (ePrime>0)
      tmp.multByP(ePrime); // multiply by p^e'
    unpacked += tmp;
  }
  unpacked.reducePtxtSpace(p2r); // Our plaintext space is now mod p^r

#ifdef DEBUG_PRINTOUT
  cerr << "+ Before repack ";
  decryptAndPrint(cerr, unpacked[0], *dbgKey, *dbgEa, printFlag);
#endif

  ctxt = unpacked;

}