Context.h
1 /* Copyright (C) 2012-2020 IBM Corp.
2  * This program is Licensed under the Apache License, Version 2.0
3  * (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://www.apache.org/licenses/LICENSE-2.0
6  * Unless required by applicable law or agreed to in writing, software
7  * distributed under the License is distributed on an "AS IS" BASIS,
8  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9  * See the License for the specific language governing permissions and
10  * limitations under the License. See accompanying LICENSE file.
11  */
12 #ifndef HELIB_CONTEXT_H
13 #define HELIB_CONTEXT_H
18 #include <helib/PAlgebra.h>
19 #include <helib/CModulus.h>
20 #include <helib/IndexSet.h>
21 #include <helib/recryption.h>
22 #include <helib/primeChain.h>
23 #include <helib/powerful.h>
24 #include <helib/apiAttributes.h>
25 #include <helib/range.h>
26 #include <helib/scheme.h>
27 #include <helib/JsonWrapper.h>
28 
29 #include <NTL/Lazy.h>
30 
31 namespace helib {
32 
33 constexpr int MIN_SK_HWT = 120;
34 constexpr int BOOT_DFLT_SK_HWT = MIN_SK_HWT;
35 
64 double lweEstimateSecurity(int n, double log2AlphaInv, int hwt);
65 
79 long FindM(long k,
80  long nBits,
81  long c,
82  long p,
83  long d,
84  long s,
85  long chosen_m,
86  bool verbose = false);
87 
88 class EncryptedArray;
89 struct PolyModRing;
90 
91 // Forward declaration of ContextBuilder
92 template <typename SCHEME>
93 class ContextBuilder;
94 
99 class Context
100 {
101 private:
102  template <typename SCHEME>
103  friend class ContextBuilder;
104 
105  // Forward declarations of useful param structs
106  // for Context and ContextBuilder.
107  struct ModChainParams;
108  struct BootStrapParams;
109 
110  // For serialization.
111  struct SerializableContent;
112 
113  // Cmodulus objects for the different primes
114  // The implementation assumes that the list of
115  // primes only grows and no prime is ever modified or removed.
116  std::vector<Cmodulus> moduli;
117 
118  // A helper table to map required modulo-sizes to primeSets
119  ModuliSizes modSizes;
120 
121  // The structure of Zm*.
122  PAlgebra zMStar;
123 
124  // Parameters stored in alMod.
125  // These are NOT invariant: it is possible to work
126  // with View objects that use a different PAlgebra object.
127 
128  // The structure of Z[X]/(Phi_m(X),p^r).
129  PAlgebraMod alMod;
130 
131  // A default EncryptedArray.
132  std::shared_ptr<const EncryptedArray> ea;
133 
134  // These parameters are currently set by buildPrimeChain
135  long hwt_param = 0; // Hamming weight of all keys associated with context
136  // 0 means "dense"
137  long e_param = 0; // parameters specific to bootstrapping
138  long ePrime_param = 0;
139 
140  std::shared_ptr<const PowerfulDCRT> pwfl_converter;
141 
142  // The structure of a single slot of the plaintext space.
143  // Note, this will be Z[X]/(G(x),p^r) for some irreducible factor G of
144  // Phi_m(X).
145  std::shared_ptr<PolyModRing> slotRing;
146 
147  // The `sqrt(variance)` of the LWE error (default=3.2).
148  NTL::xdouble stdev;
149 
150  double scale; // default = 10
151 
152  // The "ciphertext primes" are the "normal" primes that are used to
153  // represent the public encryption key and ciphertexts. These are all
154  // "large" single=precision primes, or bit-size roughly NTL_SP_SIZE bits.
155  IndexSet ctxtPrimes;
156 
157  // A disjoint set of primes, used for key switching. See section 3.1.6
158  // in the design document (key-switching). These too are "large"
159  // single=precision primes, or bit-size close to NTL_SP_SIZE bits.
160  IndexSet specialPrimes;
161 
162  // Yet a third set of primes, aimed at allowing modulus-switching with
163  // higher resolution. These are somewhat smaller single-precision
164  // primes, of size from NTL_SP_SIZE-20 to NTL_SP_SIZE-1.
165  IndexSet smallPrimes;
166 
167  // The set of primes for the digits.
168  //
169  // The different columns in any key-switching matrix contain encryptions
170  // of multiplies of the secret key, sk, B1*sk, B2*B1*sk, B3*B2*B1*sk,...
171  // with each Bi a product of a few "non-special" primes in the chain. The
172  // digits data member indicate which primes correspond to each of the Bi's.
173  // These are all IndexSet objects, whose union is the subset ctxtPrimes.
174  //
175  // The number of Bi's is one less than the number of columns in the key
176  // switching matrices (since the 1st column encrypts sk, without any Bi's),
177  // but we keep in the digits std::vector also an entry for the primes that do
178  // not participate in any Bi (so digits.size() is the same as the number
179  // of columns in the key switching matrices).
180  // See section 3.1.6 in the design document (key-switching).
181  // Digits of ctxt/columns of key-switching matrix
182  std::vector<IndexSet> digits;
183 
184  // Bootstrapping-related data in the context includes both thin and thick
185  ThinRecryptData rcData;
186 
187  // Helper for serialisation.
188  static SerializableContent readParamsFrom(std::istream& str);
189 
190  // Helper for serialisation.
191  static SerializableContent readParamsFromJSON(const JsonWrapper& str);
192 
193  // Constructor for the `Context` object.
194  // m The index of the cyclotomic polynomial.
195  // p The plaintext modulus.
196  // r BGV: The Hensel lifting parameter. CKKS: The bit precision.
197  // gens The generators of `(Z/mZ)^*` (other than `p`).
198  // ords The orders of each of the generators of `(Z/mZ)^*`.
199  Context(unsigned long m,
200  unsigned long p,
201  unsigned long r,
202  const std::vector<long>& gens = std::vector<long>(),
203  const std::vector<long>& ords = std::vector<long>());
204 
205  // Used by ContextBuilder
206  Context(long m,
207  long p,
208  long r,
209  const std::vector<long>& gens,
210  const std::vector<long>& ords,
211  const std::optional<ModChainParams>& mparams,
212  const std::optional<BootStrapParams>& bparams);
213 
214  // Used for serialisation
215  Context(const SerializableContent& content);
216 
217  // Methods for adding primes.
218  void addSpecialPrimes(long nDgts,
219  bool willBeBootstrappable,
220  long bitsInSpecialPrimes);
221 
222  void addCtxtPrimes(long nBits, long targetSize);
223 
224  void addSmallPrimes(long resolution, long cpSize);
225 
226  // Add the given prime to the `smallPrimes` set.
227  // q The prime to add.
228  void addSmallPrime(long q);
229 
230  // Add the given prime to the `ctxtPrimes` set.
231  // q The prime to add.
232  void addCtxtPrime(long q);
233 
234  // Add the given prime to the `specialPrimes` set.
235  // q The prime to add.
236  void addSpecialPrime(long q);
237 
238 public:
243  static constexpr std::string_view typeName = "Context";
244 
245  // NOTE: Parameters stored in zMStar are invariant for any computations
246  // involving this Context.
247 
252  long getM() const { return zMStar.getM(); }
253 
258  long getP() const { return zMStar.getP(); }
259 
264  long getPhiM() const { return zMStar.getPhiM(); }
265 
270  long getOrdP() const { return zMStar.getOrdP(); }
271 
277  long getNSlots() const { return zMStar.getNSlots(); }
278 
283  double getScale() const { return scale; }
284 
289  NTL::xdouble getStdev() const { return stdev; }
290 
298  long getR() const { return alMod.getR(); }
299 
306  long getPPowR() const { return alMod.getPPowR(); }
307 
308  // synonymn for getR().
309  // this is used in various corner cases in CKKS where
310  // we really need some default precisiion parameter.
311  // It is also possible to define this differently
312  // in the future.
320  long getPrecision() const { return alMod.getR(); }
321 
326  const PowerfulDCRT& getPowerfulConverter() const { return *pwfl_converter; }
327 
332  const std::shared_ptr<PolyModRing>& getSlotRing() const { return slotRing; };
333 
338  const IndexSet& getSmallPrimes() const { return smallPrimes; }
339 
344  const IndexSet& getCtxtPrimes() const { return ctxtPrimes; }
345 
350  const IndexSet& getSpecialPrimes() const { return specialPrimes; }
351 
357  const std::vector<IndexSet>& getDigits() const { return digits; }
358 
365  const IndexSet& getDigit(long i) const { return digits[i]; }
366 
371  const ThinRecryptData& getRcData() const { return rcData; }
372 
379  bool isCKKS() const { return alMod.getTag() == PA_cx_tag; }
380 
385  long getHwt() const { return hwt_param; }
386 
391  long getE() const { return e_param; }
392 
397  long getEPrime() const { return ePrime_param; }
398 
403  const PAlgebra& getZMStar() const { return zMStar; };
404 
409  const PAlgebraMod& getAlMod() const { return alMod; };
410 
416  const EncryptedArray& getView() const { return *ea; } // preferred name
417 
425  const EncryptedArray& getEA() const { return *ea; }
426 
432  const std::shared_ptr<const EncryptedArray>& shareEA() const { return ea; }
433 
434  //======================= high probability bounds ================
435 
436  // erfc(scale/sqrt(2)) * phi(m) should be less than some negligible
437  // parameter epsilon.
438  // The default value of 10 should be good enough for most applications.
439  // NOTE: -log(erfc(8/sqrt(2)))/log(2) = 49.5
440  // -log(erfc(10/sqrt(2)))/log(2) = 75.8
441  // -log(erfc(11/sqrt(2)))/log(2) = 91.1
442  // -log(erfc(12/sqrt(2)))/log(2) =107.8
443 
444  // The way this is used is as follows. If we have a normal random
445  // variable X with variance sigma^2, then the probability that
446  // that X lies outside the interval [-scale*sigma, scale*sigma] is
447  // delta=erfc(scale/sqrt(2)). We will usually apply the union bound
448  // to a vector of phi(m) such random variables (one for each primitive
449  // m-th root of unity), so that the probability that that the L-infty
450  // norm exceeds scale*sigma is at most epsilon=phim*delta. Thus,
451  // scale*sigma will be used as a high-probability bound on the
452  // L-infty norm of such vectors.
453 
454  //=======================================
455 
456  // Assume the polynomial f(x) = sum_{i < k} f_i x^i is chosen so
457  // that each f_i is chosen uniformly and independently from the
458  // interval [-magBound, magBound], and that k = degBound.
459  // This returns a bound B such that the L-infty norm
460  // of the canonical embedding exceeds B with probability at most
461  // epsilon.
462 
463  // NOTE: this is a bit heuristic: we assume that if we evaluate
464  // f at a primitive root of unity, then we get something that well
465  // approximates a normal random variable with the same variance,
466  // which is equal to the sum of the variances of the individual
467  // f_i's, which is (2*magBound)^2/12 = magBound^2/3.
468  // We then multiply the sqrt of the variance by scale to get
469  // the high probability bound.
470 
474  double noiseBoundForUniform(double magBound, long degBound) const
475  {
476  return scale * std::sqrt(double(degBound) / 3.0) * magBound;
477  }
478 
482  NTL::xdouble noiseBoundForUniform(NTL::xdouble magBound, long degBound) const
483  {
484  return scale * std::sqrt(double(degBound) / 3.0) * magBound;
485  }
486 
487  // Assume the polynomial f(x) = sum_{i < k} f_i x^i is chosen so
488  // that each f_i is chosen uniformly and independently from the
489  // from the set of balanced residues modulo the given modulus.
490  // This returns a bound B such that the L-infty norm
491  // of the canonical embedding exceeds B with probability at most
492  // epsilon.
493 
494  // NOTE: for odd modulus, this means each f_i is uniformly distributed
495  // over { -floor(modulus/2), ..., floor(modulus/2) }.
496  // For even modulus, this means each f_i is uniformly distributed
497  // over { modulus/2, ..., modulus/2 }, except that the two endpoints
498  // (which represent the same residue class) occur with half the
499  // probability of the others.
500 
501  // NOTE: this is a bit heuristic: we assume that if we evaluate
502  // f at a primitive root of unity, then we get something that well
503  // approximates a normal random variable with the same variance,
504  // which is equal to the sum of the variances of the individual
505  // f_i's, which is (modulus)^2/12 + 1/6 for even modulus,
506  // and is at most (modulus^2)/12 for odd modulus.
507  // We then multiply the sqrt of the variance by scale to get
508  // the high probability bound.
509 
510  // NOTE: this is slightly more accurate that just calling
511  // noiseBoundForUniform with magBound=modulus/2.
512 
516  double noiseBoundForMod(long modulus, long degBound) const
517  {
518  double var = fsquare(modulus) / 12.0;
519  if (modulus % 2 == 0)
520  var += 1.0 / 6.0;
521 
522  return scale * std::sqrt(degBound * var);
523  }
524 
525  // Assume the polynomial f(x) = sum_{i < k} f_i x^i is chosen
526  // so that each f_i is chosen uniformly and independently from
527  // N(0, sigma^2), and that k = degBound.
528  // This returns a bound B such that the L-infty norm
529  // of the canonical embedding exceeds B with probability at most
530  // epsilon.
531 
532  // NOTE: if we evaluate f at a primitive root of unity,
533  // then we get a normal random variable variance degBound * sigma^2.
534  // We then multiply the sqrt of the variance by scale to get
535  // the high probability bound.
536 
540  double noiseBoundForGaussian(double sigma, long degBound) const
541  {
542  return scale * std::sqrt(double(degBound)) * sigma;
543  }
544 
548  NTL::xdouble noiseBoundForGaussian(NTL::xdouble sigma, long degBound) const
549  {
550  return scale * std::sqrt(double(degBound)) * sigma;
551  }
552 
553  // Assume the polynomial f(x) = sum_{i < k} f_i x^i is chosen
554  // so that each f_i is zero with probability 1-prob, 1 with probability
555  // prob/2, and -1 with probability prob/2.
556  // This returns a bound B such that the L-infty norm
557  // of the canonical embedding exceeds B with probability at most
558  // epsilon.
559 
560  // NOTE: this is a bit heuristic: we assume that if we evaluate
561  // f at a primitive root of unity, then we get something that
562  // well approximates a normal random variable with the same variance,
563  // which is equal to the sum of the individual variances,
564  // which is degBound*prob.
565  // We then multiply the sqrt of the variance by scale to get
566  // the high probability bound.
567 
571  double noiseBoundForSmall(double prob, long degBound) const
572  {
573  return scale * std::sqrt(double(degBound)) * std::sqrt(prob);
574  }
575 
576  // Assume the polynomial f(x) = sum_{i < k} f_i x^i is chosen
577  // hwt coefficients are chosen to \pm 1, and the remainder zero.
578  // This returns a bound B such that the L-infty norm
579  // of the canonical embedding exceeds B with probability at most
580  // epsilon.
581 
582  // NOTE: this is a bit heuristic: we assume that if we evaluate
583  // f at a primitive root of unity, then we get something that
584  // well approximates a normal random variable with the same variance,
585  // which is hwt.
586  // We then multiply the sqrt of the variance by scale to get
587  // the high probability bound.
588 
589  // NOTE: degBound is not used here, but I include it
590  // for consistency with the other noiseBound routines
591 
595  double noiseBoundForHWt(long hwt, UNUSED long degBound) const
596  {
597  return scale * std::sqrt(double(hwt));
598  }
599 
600  // This computes a high probability bound on the L-infty norm
601  // of x0+s*x1 in the pwrfl basis, assuming is chosen with coeffs
602  // in the pwrfl basis uniformly and independently dist'd over [-1/2,1/2],
603  // x0 has arbitrary coeffs over [-1/2,1/2] in the pwrfl basis,
604  // and assuming s is chosen with skHwt nonzero coeffs mod X^m-1
605  // in the power basis (uniformly and independently over {-1,1}).
606  // The bound should be satisfied with probability epsilon.
607 
608  // NOTE: this is a bit heuristic. See design document for details.
609  // NOTE: this is still valid even when m is a power of 2
610 
615  double stdDevForRecryption() const
616  {
617  long skHwt = hwt_param;
618 
619  // number of prime factors of m
620  long k = zMStar.getNFactors();
621 
622  long m = zMStar.getM();
623  long phim = zMStar.getPhiM();
624 
625  double mrat = double(phim) / double(m);
626 
627  return std::sqrt(mrat * double(skHwt) * double(1L << k) / 3.0) * 0.5;
628  }
629 
634  double boundForRecryption() const
635  {
636  return 0.5 + scale * stdDevForRecryption();
637  }
638 
643  const ModuliSizes& getModSizeTable() const { return modSizes; }
644 
648  void setModSizeTable() { modSizes.init(*this); }
649 
653  ~Context() = default;
654 
658  Context() = delete;
659 
664  Context(const Context& other) = delete;
665 
670  Context(Context&& other) = delete;
671 
676  Context& operator=(const Context& other) = delete;
677 
682  Context& operator=(Context&& other) = delete;
683 
692  void enableBootStrapping(const NTL::Vec<long>& mvec,
693  bool build_cache = false,
694  bool alsoThick = true)
695  {
696  assertTrue(e_param > 0,
697  "enableBootStrapping invoked but willBeBootstrappable "
698  "not set in buildModChain");
699 
700  rcData.init(*this, mvec, alsoThick, build_cache);
701  }
702 
707  bool isBootstrappable() const { return rcData.alMod != nullptr; }
708 
714  IndexSet fullPrimes() const { return ctxtPrimes | specialPrimes; }
715 
723  {
724  return smallPrimes | ctxtPrimes | specialPrimes;
725  }
726 
727  // returns first nprimes ctxtPrimes
734  IndexSet getCtxtPrimes(long nprimes) const
735  {
736  long first = ctxtPrimes.first();
737  long last = std::min(ctxtPrimes.last(), first + nprimes - 1);
738  return IndexSet(first, last);
739  }
740 
741  // FIXME: replacement for bitsPerLevel placeholder for now
742  long BPL() const { return 30; }
743 
749  bool operator==(const Context& other) const;
750 
756  bool operator!=(const Context& other) const { return !(*this == other); }
757 
764  long ithPrime(unsigned long i) const
765  {
766  return (i < moduli.size()) ? moduli[i].getQ() : 0;
767  }
768 
775  const Cmodulus& ithModulus(unsigned long i) const { return moduli[i]; }
776 
781  long numPrimes() const { return moduli.size(); }
782 
790  bool isZeroDivisor(const NTL::ZZ& num) const
791  {
792  for (long i : range(moduli.size()))
793  if (divide(num, moduli[i].getQ()))
794  return true;
795  return false;
796  }
797 
804  bool inChain(long p) const
805  {
806  for (long i : range(moduli.size()))
807  if (p == moduli[i].getQ())
808  return true;
809  return false;
810  }
811 
817  void productOfPrimes(NTL::ZZ& p, const IndexSet& s) const;
818  NTL::ZZ productOfPrimes(const IndexSet& s) const
819  {
820  NTL::ZZ p;
821  productOfPrimes(p, s);
822  return p;
823  }
824 
825  // FIXME: run-time error when ithPrime(i) returns 0
832  double logOfPrime(unsigned long i) const { return log(ithPrime(i)); }
833 
840  double logOfProduct(const IndexSet& s) const
841  {
842  if (s.last() >= numPrimes())
843  throw RuntimeError("Context::logOfProduct: IndexSet has too many rows");
844 
845  double ans = 0.0;
846  for (long i : s)
847  ans += logOfPrime(i);
848  return ans;
849  }
850 
856  long bitSizeOfQ() const
857  {
858  IndexSet primes = ctxtPrimes | specialPrimes;
859  return std::ceil(logOfProduct(primes) / log(2.0));
860  }
861 
874  double securityLevel() const
875  {
876  IndexSet primes = ctxtPrimes | specialPrimes;
877  if (primes.card() == 0) {
878  throw LogicError(
879  "Security level cannot be determined as modulus chain is empty.");
880  }
881 
882  double s = to_double(stdev);
883  if (zMStar.getPow2() == 0) { // not power of two
884  s *= sqrt(zMStar.getM());
885  }
886  double log2AlphaInv = (logOfProduct(primes) - log(s)) / log(2.0);
887  return lweEstimateSecurity(zMStar.getPhiM(), log2AlphaInv, hwt_param);
888  }
889 
894  void printout(std::ostream& out = std::cout) const;
895 
902  friend std::ostream& operator<<(std::ostream& str, const Context& context);
903 
916  friend void readContextBase(std::istream& str,
917  unsigned long& m,
918  unsigned long& p,
919  unsigned long& r,
920  std::vector<long>& gens,
921  std::vector<long>& ords);
922 
929  friend std::istream& operator>>(std::istream& str, Context& context);
931 
936  void writeTo(std::ostream& str) const;
937 
944  static Context readFrom(std::istream& str);
945 
952  static Context* readPtrFrom(std::istream& str);
953 
959  void writeToJSON(std::ostream& str) const;
960 
965  JsonWrapper writeToJSON() const;
966 
973  static Context readFromJSON(std::istream& str);
974 
980  static Context readFromJSON(const JsonWrapper& j);
981 
987  static Context* readPtrFromJSON(std::istream& str);
988 
989  // Internal function to undo buldModChain.
990  // Used for parameter generation programs.
991  // FIXME Should this not be private?
993  {
994  moduli.clear();
995  ctxtPrimes.clear();
996  specialPrimes.clear();
997  smallPrimes.clear();
998  modSizes.clear();
999  digits.clear();
1000  hwt_param = 0;
1001  e_param = 0;
1002  ePrime_param = 0;
1003  }
1004 
1018  void buildModChain(long nBits,
1019  long nDgts = 3,
1020  bool willBeBootstrappable = false,
1021  long skHwt = 0,
1022  long resolution = 3,
1023  long bitsInSpecialPrimes = 0);
1024 
1025  // should be called if after you build the mod chain in some way
1026  // *other* than calling buildModChain.
1027  void endBuildModChain();
1028 
1029 }; // End of class Context
1030 
1038 template <typename SCHEME>
1039 std::ostream& operator<<(std::ostream& os, const ContextBuilder<SCHEME>& cb);
1040 
1046 template <typename SCHEME>
1048 {
1049  static_assert(std::is_same<SCHEME, CKKS>::value ||
1050  std::is_same<SCHEME, BGV>::value,
1051  "Can only create context object parameterized by the crypto "
1052  "scheme (CKKS or BGV)");
1053 
1054 private:
1055  // Helper for building
1056  const std::pair<std::optional<Context::ModChainParams>,
1057  std::optional<Context::BootStrapParams>>
1058  makeParamsArgs() const;
1059 
1060  // Default values by scheme
1061  struct default_values;
1062 
1063  // General parameters
1064  std::vector<long> gens_;
1065  std::vector<long> ords_;
1066  long m_ = default_values::m; // BGV: 3, CKKS: 4
1067  long p_ = default_values::p; // BGV: 2, CKKS: -1
1068  long r_ = default_values::r; // BGV: Hensel lifting = 1,
1069  // CKKS: Precision = 20
1070  long c_ = 3;
1071 
1072  // Modulus chain params
1073  long bits_ = 300;
1074  long skHwt_ = 0;
1075  long resolution_ = 3;
1076  long bitsInSpecialPrimes_ = 0;
1077  bool buildModChainFlag_ = true; // Default build the modchain.
1078 
1079  double stdev_ = 3.2;
1080  double scale_ = 10;
1081 
1082  // Boostrap params (BGV only)
1083  NTL::Vec<long> mvec_;
1084  bool buildCacheFlag_ = false;
1085  bool thickFlag_ = false;
1086  bool bootstrappableFlag_ = false; // Default not boostrappable.
1087 
1088 public:
1093  static constexpr std::string_view typeName = "ContextBuilder";
1094 
1101  {
1102  m_ = m;
1103  return *this;
1104  }
1105 
1112  template <typename S = SCHEME,
1113  std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
1115  {
1116  p_ = p;
1117  return *this;
1118  }
1119 
1126  template <typename S = SCHEME,
1127  std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
1129  {
1130  r_ = r;
1131  return *this;
1132  }
1133 
1140  template <typename S = SCHEME,
1141  std::enable_if_t<std::is_same<S, CKKS>::value>* = nullptr>
1143  {
1144  r_ = precision;
1145  return *this;
1146  }
1147 
1154  {
1155  scale_ = scale;
1156  return *this;
1157  }
1158 
1165  {
1166  stdev_ = stdev;
1167  return *this;
1168  }
1169 
1177  {
1178  c_ = c;
1179  return *this;
1180  }
1181 
1187  ContextBuilder& gens(const std::vector<long>& gens)
1188  {
1189  gens_ = gens;
1190  return *this;
1191  }
1192 
1201  ContextBuilder& ords(const std::vector<long>& ords)
1202  {
1203  ords_ = ords;
1204  return *this;
1205  }
1206 
1214  {
1215  bits_ = bits;
1216  return *this;
1217  }
1218 
1227  {
1228  skHwt_ = skHwt;
1229  return *this;
1230  }
1231 
1238  {
1239  resolution_ = bits;
1240  return *this;
1241  }
1242 
1249  {
1250  bitsInSpecialPrimes_ = bits;
1251  return *this;
1252  }
1253 
1262  {
1263  buildModChainFlag_ = yesno;
1264  return *this;
1265  }
1266 
1273  template <typename S = SCHEME,
1274  std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
1275  ContextBuilder& mvec(const NTL::Vec<long>& mvec)
1276  {
1277  mvec_ = mvec;
1278  return *this;
1279  }
1280 
1287  template <typename S = SCHEME,
1288  std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
1289  ContextBuilder& mvec(const std::vector<long>& mvec)
1290  {
1291  mvec_ = convert<NTL::Vec<long>>(mvec);
1292  return *this;
1293  }
1294 
1300  template <typename S = SCHEME,
1301  std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
1303  {
1304  thickFlag_ = false;
1305  return *this;
1306  }
1307 
1313  template <typename S = SCHEME,
1314  std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
1316  {
1317  thickFlag_ = true;
1318  return *this;
1319  }
1320 
1328  template <typename S = SCHEME,
1329  std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
1331  {
1332  buildCacheFlag_ = yesno;
1333  return *this;
1334  }
1335 
1344  template <typename S = SCHEME,
1345  std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
1346  ContextBuilder& bootstrappable(bool yesno = true)
1347  {
1348  bootstrappableFlag_ = yesno;
1349  return *this;
1350  }
1351 
1357  Context build() const;
1358 
1364  Context* buildPtr() const;
1365 
1366  friend std::ostream& operator<<<SCHEME>(std::ostream& os,
1367  const ContextBuilder& cb);
1368 }; // End of class ContextBuilder
1369 
1370 // Default BGV values
1371 template <>
1373 {
1374  static constexpr long m = 3;
1375  static constexpr long p = 2;
1376  static constexpr long r = 1;
1377 };
1378 
1379 // Default CKKS values
1380 template <>
1382 {
1383  static constexpr long m = 4;
1384  static constexpr long p = -1;
1385  static constexpr long r = 20;
1386 };
1387 
1388 // Should point to the "current" context
1389 extern Context* activeContext;
1390 
1391 } // namespace helib
1392 
1393 #endif // ifndef HELIB_CONTEXT_H
Provides FFT and iFFT routines modulo a single-precision prime.
Definition: CModulus.h:43
Builder to help construct a context.
Definition: Context.h:1048
Context build() const
Builds a Context object from the arguments stored in the ContextBuilder object.
Definition: Context.cpp:1211
ContextBuilder & skHwt(long skHwt)
Sets the secret key Hamming weight.
Definition: Context.h:1226
ContextBuilder & buildModChain(bool yesno)
Sets a flag determining whether the modulus chain will be built.
Definition: Context.h:1261
ContextBuilder & gens(const std::vector< long > &gens)
Sets gens the generators of the ZMStar group.
Definition: Context.h:1187
ContextBuilder & bitsInSpecialPrimes(long bits)
Sets the bit size of the special primes in the modulus chain.
Definition: Context.h:1248
ContextBuilder & c(long c)
Sets c the number of columns (a.k.a. digits) in the key switching matrices.
Definition: Context.h:1176
ContextBuilder & m(long m)
Sets m the order of the cyclotomic polynomial.
Definition: Context.h:1100
ContextBuilder & scale(double scale)
Sets scale the scale parameter.
Definition: Context.h:1153
ContextBuilder & mvec(const std::vector< long > &mvec)
Sets mvec the unique primes which are factors of m.
Definition: Context.h:1289
ContextBuilder & thinboot()
Sets boostrapping to be thin.
Definition: Context.h:1302
ContextBuilder & buildCache(bool yesno)
Sets flag to choose that the cache for boostrapping will be built.
Definition: Context.h:1330
Context * buildPtr() const
Builds a Context object from the arguments stored in the ContextBuilder object.
Definition: Context.cpp:1218
ContextBuilder & bootstrappable(bool yesno=true)
Sets a flag determining if the context will be bootstrappable.
Definition: Context.h:1346
ContextBuilder & precision(long precision)
Sets precision the bit precision parameter.
Definition: Context.h:1142
static constexpr std::string_view typeName
Class label to be added to JSON serialization as object type information.
Definition: Context.h:1093
ContextBuilder & ords(const std::vector< long > &ords)
Sets ords the order of the corresponding generators in gens in ZmStar.
Definition: Context.h:1201
ContextBuilder & thickboot()
Sets boostrapping to be thick.
Definition: Context.h:1315
ContextBuilder & p(long p)
Sets p the prime number of the ciphertext space.
Definition: Context.h:1114
ContextBuilder & r(long r)
Sets r the Hensel lifting parameter.
Definition: Context.h:1128
ContextBuilder & bits(long bits)
Sets the bit size of the primes in the modulus chain.
Definition: Context.h:1213
ContextBuilder & resolution(long bits)
Sets the resolution for the modulus chain.
Definition: Context.h:1237
ContextBuilder & stdev(double stdev)
Sets stdev the standard deviation parameter.
Definition: Context.h:1164
ContextBuilder & mvec(const NTL::Vec< long > &mvec)
Sets mvec the unique primes which are factors of m.
Definition: Context.h:1275
Maintaining the HE scheme parameters.
Definition: Context.h:100
const ThinRecryptData & getRcData() const
Getter method for a recryption data object.
Definition: Context.h:371
void clearModChain()
Definition: Context.h:992
static Context * readPtrFrom(std::istream &str)
Read from the stream the serialized Context object in binary format.
Definition: Context.cpp:540
double securityLevel() const
An estimate for the security-level. This has a lower bound of 0.
Definition: Context.h:874
static Context * readPtrFromJSON(std::istream &str)
Read from the JsonWrapper the serialized Context object.
Definition: Context.cpp:592
long getHwt() const
Getter method for the Hamming weight value.
Definition: Context.h:385
void writeTo(std::ostream &str) const
Write out the Context object in binary format.
Definition: Context.cpp:415
const std::shared_ptr< const EncryptedArray > & shareEA() const
Getter method returning the std::shared_ptr to default EncryptedArray object of the created context.
Definition: Context.h:432
double noiseBoundForSmall(double prob, long degBound) const
Definition: Context.h:571
double logOfProduct(const IndexSet &s) const
Calculate the natural logarithm of productOfPrimes(s) for a given set of primes s.
Definition: Context.h:840
const ModuliSizes & getModSizeTable() const
Get the helper table to map required modulo-sizes to primeSets.
Definition: Context.h:643
void buildModChain(long nBits, long nDgts=3, bool willBeBootstrappable=false, long skHwt=0, long resolution=3, long bitsInSpecialPrimes=0)
Build the modulus chain for given Context object.
Definition: Context.cpp:1127
bool isZeroDivisor(const NTL::ZZ &num) const
Check if a number is divisible by any of the primes in the modulus chain.
Definition: Context.h:790
Context(const Context &other)=delete
Deleted copy constructor.
long getM() const
Getter method for the m used to create this context.
Definition: Context.h:252
bool operator!=(const Context &other) const
Not equals operator between two Context objects.
Definition: Context.h:756
friend std::ostream & operator<<(std::ostream &str, const Context &context)
Write out all other data associated with a given Context object.
Definition: Context.cpp:664
long BPL() const
Definition: Context.h:742
void setModSizeTable()
Set the helper table to map required modulo-sizes to primeSets.
Definition: Context.h:648
friend void readContextBase(std::istream &str, unsigned long &m, unsigned long &p, unsigned long &r, std::vector< long > &gens, std::vector< long > &ords)
Read in the basic information m, p and r required to construct a Context object.
static Context readFromJSON(std::istream &str)
Read from the stream the serialized Context object using JSON format.
Definition: Context.cpp:578
const IndexSet & getSmallPrimes() const
Getter method to the index set to the small primes.
Definition: Context.h:338
NTL::xdouble noiseBoundForGaussian(NTL::xdouble sigma, long degBound) const
Definition: Context.h:548
~Context()=default
Default destructor.
double stdDevForRecryption() const
Calculate the standard deviation for recryption.
Definition: Context.h:615
long numPrimes() const
Return the total number of small primes in the modulus chain.
Definition: Context.h:781
const PowerfulDCRT & getPowerfulConverter() const
Get a powerful converter.
Definition: Context.h:326
Context & operator=(Context &&other)=delete
Deleted move assignment.
long getPrecision() const
Getter method for the precision value of the created CKKS context.
Definition: Context.h:320
long getE() const
Getter method for the e parameter.
Definition: Context.h:391
void printout(std::ostream &out=std::cout) const
Print out algebra and other important info.
Definition: Context.cpp:728
Context(Context &&other)=delete
Deleted move constructor.
friend std::istream & operator>>(std::istream &str, Context &context)
Read in all other data associated with a given Context object.
const IndexSet & getDigit(long i) const
Getter method to get a single digit.
Definition: Context.h:365
long getPPowR() const
Getter method for the default p^r value of the created context.
Definition: Context.h:306
double getScale() const
Getter method for the scale.
Definition: Context.h:283
JsonWrapper writeToJSON() const
Write out the Context object to a JsonWrapper.
Definition: Context.cpp:601
const EncryptedArray & getView() const
Getter method returning the default view object of the created context.
Definition: Context.h:416
long getP() const
Getter method for the p used to create this context.
Definition: Context.h:258
const IndexSet & getCtxtPrimes() const
Getter method to the index set to the ciphertext primes.
Definition: Context.h:344
IndexSet fullPrimes() const
Getter method that returns the handles of both the ctxtPrimes and specialPrimes associated with this ...
Definition: Context.h:714
double noiseBoundForMod(long modulus, long degBound) const
Definition: Context.h:516
bool inChain(long p) const
Check if value is already contained within the modulus chain.
Definition: Context.h:804
NTL::ZZ productOfPrimes(const IndexSet &s) const
Definition: Context.h:818
long ithPrime(unsigned long i) const
Getter method for the small prime of the modulus chain at index i as a long.
Definition: Context.h:764
long getPhiM() const
Getter method for the phi(m) of the created context.
Definition: Context.h:264
Context & operator=(const Context &other)=delete
Deleted copy assignment.
const EncryptedArray & getEA() const
Getter method returning the default EncryptedArray object of the created context.
Definition: Context.h:425
NTL::xdouble noiseBoundForUniform(NTL::xdouble magBound, long degBound) const
Definition: Context.h:482
double noiseBoundForUniform(double magBound, long degBound) const
Definition: Context.h:474
void enableBootStrapping(const NTL::Vec< long > &mvec, bool build_cache=false, bool alsoThick=true)
Initialises the recryption data.
Definition: Context.h:692
bool isBootstrappable() const
Check if a Context is bootstrappable.
Definition: Context.h:707
double logOfPrime(unsigned long i) const
Calculate the natural logarithm of the ith prime of the modulus chain.
Definition: Context.h:832
long getR() const
Getter method for the default r value of the created context.
Definition: Context.h:298
IndexSet getCtxtPrimes(long nprimes) const
Getter method that returns the first nprimes ctxtPrimes associated with this Context.
Definition: Context.h:734
double noiseBoundForGaussian(double sigma, long degBound) const
Definition: Context.h:540
static constexpr std::string_view typeName
Class label to be added to JSON serialization as object type information.
Definition: Context.h:243
long getOrdP() const
Getter method for the ord(p) of the created context.
Definition: Context.h:270
double noiseBoundForHWt(long hwt, UNUSED long degBound) const
Definition: Context.h:595
IndexSet allPrimes() const
Getter method that returns the handles of all primes associated with this Context.
Definition: Context.h:722
NTL::xdouble getStdev() const
Getter method for the standard deviation used..
Definition: Context.h:289
double boundForRecryption() const
Calculate the bound for recryption.
Definition: Context.h:634
const Cmodulus & ithModulus(unsigned long i) const
Getter method for the small prime of the modulus chain at index i as a Cmodulus.
Definition: Context.h:775
bool isCKKS() const
Return whether this is a CKKS context or not Context.
Definition: Context.h:379
long bitSizeOfQ() const
Calculate the size of the ciphertext modulus Q in bits.
Definition: Context.h:856
void endBuildModChain()
Definition: Context.cpp:1173
const std::vector< IndexSet > & getDigits() const
Getter method to the digits.
Definition: Context.h:357
long getNSlots() const
Getter method for the number of plaintext slots of the created context.
Definition: Context.h:277
const IndexSet & getSpecialPrimes() const
Getter method to the index set to the special primes.
Definition: Context.h:350
bool operator==(const Context &other) const
Equals operator between two Context objects.
Definition: Context.cpp:368
long getEPrime() const
Getter method for the e prime parameter.
Definition: Context.h:397
const PAlgebraMod & getAlMod() const
Get the underlying AlMod object.
Definition: Context.h:409
Context()=delete
Deleted default constructor.
const PAlgebra & getZMStar() const
Get the underlying zMStar object.
Definition: Context.h:403
static Context readFrom(std::istream &str)
Read from the stream the serialized Context object in binary format.
Definition: Context.cpp:535
const std::shared_ptr< PolyModRing > & getSlotRing() const
Get a slot ring.
Definition: Context.h:332
void productOfPrimes(NTL::ZZ &p, const IndexSet &s) const
Calculate the product of all primes in the given set.
Definition: Context.cpp:361
A simple wrapper for a smart pointer to an EncryptedArrayBase. This is the interface that higher-leve...
Definition: EncryptedArray.h:1583
A dynamic set of non-negative integers.
Definition: IndexSet.h:33
long card() const
The cardinality of the set.
Definition: IndexSet.h:80
long first() const
Returns the first element, 0 if the set is empty.
Definition: IndexSet.h:68
long last() const
Returns the last element, -1 if the set is empty.
Definition: IndexSet.h:71
void clear()
Set to the empty set.
Definition: IndexSet.cpp:121
Inherits from Exception and std::logic_error.
Definition: exceptions.h:68
A helper class to map required modulo-sizes to primeSets.
Definition: primeChain.h:28
void clear()
Definition: primeChain.h:66
void init(const Context &context)
initialize helper table for a given chain
Definition: primeChain.cpp:68
The structure of (Z/mZ)* /(p)
Definition: PAlgebra.h:77
long getPhiM() const
Returns phi(m)
Definition: PAlgebra.h:170
long getP() const
Returns p.
Definition: PAlgebra.h:167
long getNSlots() const
The number of plaintext slots = phi(m)/ord(p)
Definition: PAlgebra.h:188
long getM() const
Returns m.
Definition: PAlgebra.h:164
long getOrdP() const
The order of p in (Z/mZ)^*.
Definition: PAlgebra.h:173
long getNFactors() const
The number of distinct prime factors of m.
Definition: PAlgebra.h:176
long getPow2() const
if m = 2^k, then pow2 == k; otherwise, pow2 == 0
Definition: PAlgebra.h:191
The structure of Z[X]/(Phi_m(X), p)
Definition: PAlgebra.h:816
PA_tag getTag() const
Returns the type tag: PA_GF2_tag or PA_zz_p_tag.
Definition: PAlgebra.h:860
long getR() const
The value r.
Definition: PAlgebra.h:869
long getPPowR() const
The value p^r.
Definition: PAlgebra.h:871
Conversion between powerful representation, DoubleCRT, and ZZX.
Definition: powerful.h:131
std::shared_ptr< const PAlgebraMod > alMod
for plaintext space p^{e-e'+r}
Definition: recryption.h:49
Inherits from Exception and std::runtime_error.
Definition: exceptions.h:105
Same as above, but for "thin" bootstrapping, where the slots are assumed to contain constants.
Definition: recryption.h:99
void init(const Context &context, const NTL::Vec< long > &mvec_, bool alsoThick, bool build_cache=false, bool minimal=false)
Initialize the recryption data in the context.
Definition: recryption.cpp:773
Definition: apiAttributes.h:21
Context * activeContext
Definition: Context.cpp:359
constexpr int BOOT_DFLT_SK_HWT
Definition: Context.h:34
general_range< long > range(long n)
Definition: range.h:57
constexpr int MIN_SK_HWT
Definition: Context.h:33
@ PA_cx_tag
Definition: PAlgebra.h:302
long FindM(long k, long nBits, long c, long p, long d, long s, long chosen_m, bool verbose=false)
Returns smallest parameter m satisfying various constraints.
Definition: Context.cpp:207
void assertTrue(const T &value, const std::string &message)
Definition: assertions.h:61
double lweEstimateSecurity(int n, double log2AlphaInv, int hwt)
An estimate for the security-level. This has a lower bound of 0.
Definition: Context.cpp:32
std::ostream & operator<<(std::ostream &os, const ContextBuilder< SCHEME > &cb)
ostream operator for serializing the ContextBuilder object.
double fsquare(double x)
Return the square of a number as a double.
Definition: NumbTh.h:149
Type for BGV scheme, to be used as template parameter.
Definition: scheme.h:46
Type for CKKS scheme, to be used as template parameter.
Definition: scheme.h:30
Definition: Context.cpp:180
Definition: Context.cpp:168
Definition: Context.cpp:187
Definition: Context.h:1373
static constexpr long m
Definition: Context.h:1374
static constexpr long r
Definition: Context.h:1376
static constexpr long p
Definition: Context.h:1375
Definition: JsonWrapper.h:9
Lightweight type for describing the structure of a single slot of the plaintext space.
Definition: PolyModRing.h:43