Пример #1
0
void rotate(DoubleCRT& d, long amt, 
            const vector< vector< DoubleCRT > > & maskTable)

// rotate d by amt

{
  const FHEcontext& context = d.getContext();
  const PAlgebra& al = context.zMstar;
  //  const PAlgebraModTwo& al2 = context.modTwo;

  long ngens = al.numOfGens();
  long nslots = al.NSlots();

  amt = amt % nslots;
  if (amt < 0) amt += nslots;

  if (amt == 0) return;

  long i, v;

  i = ngens-1;
  v = coordinate(al, i, amt);
  rotate1D(d, i, v, maskTable);

  if (i == 0) return;

  DoubleCRT mask(context, d.getIndexSet());
  mask.SetZero();
  mask.Add(maskTable[i][v], false);

  DoubleCRT tmp(context, d.getIndexSet());


  for (i--; i >= 0; i--) {
    v = coordinate(al, i, amt);

    tmp.SetZero();
    tmp += d;
    tmp *= mask;
    d -= tmp;
    rotate1D(d, i, v+1, maskTable);
    rotate1D(tmp, i, v, maskTable); 
    d += tmp;

    if (i > 0) {
      tmp.SetZero();
      tmp.Add(maskTable[i][v], false);
      tmp.Sub(maskTable[i][v+1], false);
      mask *= tmp;
      mask.Add(maskTable[i][v+1], false);
    }
  }


}
Пример #2
0
void rotate1D(DoubleCRT& d, long i, long amt, 
              const vector< vector< DoubleCRT > > & maskTable)

// rotate d in dimension i by amt

{
  const FHEcontext& context = d.getContext();
  const PAlgebra& al = context.zMstar;
  //  const PAlgebraModTwo& al2 = context.modTwo;

  long ngens = al.numOfGens();
  // long nslots = al.NSlots();

  assert(i >= 0 && i < ngens);
  long ord = al.OrderOf(i);

  amt = amt % ord;
  if (amt < 0) amt += ord;

  if (amt == 0) return;

  if (al.SameOrd(i)) {
    // "native" rotation
    long val = PowerMod(al.ZmStarGen(i), amt, al.M());
    d.automorph(val);
  }
  else {
    // more expensive "non-native" rotation
    assert(maskTable[i].size() > 0);
    long val = PowerMod(al.ZmStarGen(i), amt, al.M());
    //    long ival = InvMod(val, al.M());
    long ival = PowerMod(al.ZmStarGen(i), amt-ord, al.M());

    const DoubleCRT& m1 = maskTable[i].at(ord-amt);

    DoubleCRT d1(d);

    d1.Mul(m1, false);
    d -= d1;
    d.automorph(val);
    d1.automorph(ival);
    d += d1;

  }
}
Пример #3
0
// Add/subtract a ciphertext part to a ciphertext.
// With negative=true we subtract, otherwise we add.
void Ctxt::addPart(const DoubleCRT& part, const SKHandle& handle, 
		   bool matchPrimeSet, bool negative)
{
  FHE_TIMER_START;

  assert (&part.getContext() == &context);

  if (parts.size()==0) { // inserting 1st part 
    primeSet = part.getIndexSet();
    parts.push_back(CtxtPart(part,handle));
    if (negative) parts.back().Negate(); // not thread-safe??
  }
  else {       // adding to a ciphertext with existing parts
    if (!(part.getIndexSet() <= primeSet)) {
      // add to the the prime-set of *this, if needed (this is expensive)
      if (matchPrimeSet) {
        IndexSet setDiff = part.getIndexSet() / primeSet; // set minus
        for (size_t i=0; i<parts.size(); i++) parts[i].addPrimes(setDiff);
        primeSet.insert(setDiff);
      }
      else // this should never happen
        throw std::logic_error("part has too many primes and matchPrimeSet==false");
    }

    DoubleCRT tmp(context, IndexSet::emptySet());
    const DoubleCRT* ptr = &part;

    // mod-UP the part if needed
    IndexSet s = primeSet / part.getIndexSet();
    if (!empty(s)) { // if need to mod-UP, do it on a temporary copy
      tmp = part;
      tmp.addPrimesAndScale(s);
      ptr = &tmp;
    }
    long j = getPartIndexByHandle(handle);
    if (j>=0) { // found a matching part, add them up
      if (negative) parts[j] -= *ptr;
      else          parts[j] += *ptr;
    } else {    // no mathing part found, just append this part
      parts.push_back(CtxtPart(*ptr,handle));
      if (negative) parts.back().Negate(); // not thread-safe??
    }
  }
}