// For an n-size array, compute the 2^n products // products[j] = \prod_{i s.t. j_i=1} array[i] // \times \prod_{i s.t. j_i=0}(a-array[i]) void computeAllProducts(/*Output*/CtPtrs& products, /*Index*/const CtPtrs& array, std::vector<zzX>* unpackSlotEncoding) { FHE_TIMER_START; long nBits = array.size(); if (lsize(products)>0) { long nBits2 = NTL::NumBits(lsize(products)-1); // ceil(log_2(size)) if (nBits>nBits2) nBits=nBits2; // ignore extra bits in 'array' } if (nBits<1) return; // do nothing assert(nBits <= 16); // Output cannot be bigger than 2^16 if (lsize(products)==0) // try to set the output size products.resize(1L << nBits, &array); for (long i=0; i<lsize(products); i++) products[i]->clear(); // Check that we have enough levels, try to bootstrap otherwise assert(array.ptr2nonNull() != nullptr); long bpl = array.ptr2nonNull()->getContext().BPL(); if (findMinBitCapacity(array) < (NTL::NumBits(nBits)+1)*bpl) { const Ctxt* ct = array.ptr2nonNull(); // find some non-null Ctxt assert(unpackSlotEncoding!=nullptr); assert(ct!=nullptr); assert(ct->getPubKey().isBootstrappable()); packedRecrypt(array, *unpackSlotEncoding, *(ct->getContext().ea), /*belowLevel=*/nBits +3); } if (findMinBitCapacity(array) < (NTL::NumBits(nBits)+1)*bpl) throw std::logic_error("not enough levels for table lookup"); // Call the recursive function that copmutes the products recursiveProducts(products, CtPtrs_slice(array,0,nBits)); }
// A counterpart of tableLookup. The input is an encrypted table T[] // and an array of encrypted bits I[], holding the binary representation // of an index i into T. This function increments by one the entry T[i]. void tableWriteIn(const CtPtrs& table, const CtPtrs& idx, std::vector<zzX>* unpackSlotEncoding) { FHE_TIMER_START; const Ctxt* ct = table.ptr2nonNull(); // find some non-null Ctxt long size = lsize(table); if (size==0) return; std::vector<Ctxt> products(size, Ctxt(ZeroCtxtLike, *ct)); CtPtrs_vectorCt pWrap(products); // A wrapper // Compute all products of ecnrypted bits =: b_i computeAllProducts(pWrap, idx, unpackSlotEncoding); // incrememnt each entry of T[i] by products[i] NTL_EXEC_RANGE(lsize(table), first, last) for(long i=first; i<last; i++) *table[i] += products[i]; NTL_EXEC_RANGE_END }