DoubleCRT.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_DOUBLECRT_H
13 #define HELIB_DOUBLECRT_H
18 #include <helib/zzX.h>
19 #include <helib/NumbTh.h>
20 #include <helib/IndexMap.h>
21 #include <helib/timing.h>
22 
23 namespace helib {
24 
25 class Context;
26 
33 class DoubleCRTHelper : public IndexMapInit<NTL::vec_long>
34 {
35 private:
36  long val;
37 
38 public:
39  DoubleCRTHelper(const Context& context);
40 
42  virtual void init(NTL::vec_long& v) { v.FixLength(val); }
43 
46  {
47  return new DoubleCRTHelper(*this);
48  }
49 
50 private:
51  DoubleCRTHelper(); // disable default constructor
52 };
53 
75 class DoubleCRT
76 {
77  const Context& context; // the context
78 
79  // the data itself: if the i'th prime is in use then map[i] is the std::vector
80  // of evaluations wrt this prime
82 
85  void verify();
86 
87  // Generic operators.
88  // The behavior when *this and other use different primes depends on the flag
89  // matchIndexSets. When it is set to true then the effective modulus is
90  // determined by the union of the two index sets; otherwise, the index set
91  // of *this.
92 
93  class AddFun
94  {
95  public:
96  long apply(long a, long b, long n) { return NTL::AddMod(a, b, n); }
97  };
98 
99  class SubFun
100  {
101  public:
102  long apply(long a, long b, long n) { return NTL::SubMod(a, b, n); }
103  };
104 
105  class MulFun
106  {
107  public:
108  long apply(long a, long b, long n) { return NTL::MulMod(a, b, n); }
109  };
110 
111  template <typename Fun>
112  DoubleCRT& Op(const DoubleCRT& other, Fun fun, bool matchIndexSets = true);
113 
114  DoubleCRT& do_mul(const DoubleCRT& other, bool matchIndexSets = true);
115 
116  template <typename Fun>
117  DoubleCRT& Op(const NTL::ZZ& num, Fun fun);
118 
119  template <typename Fun>
120  DoubleCRT& Op(const NTL::ZZX& poly, Fun fun);
121 
122 public:
123  // Constructors and assignment operators
124 
125  // representing an integer polynomial as DoubleCRT. If the set of primes
126  // to use is not specified, the resulting object uses all the primes in
127  // the context. If the coefficients of poly are larger than the product of
128  // the used primes, they are effectively reduced modulo that product
129 
130  // Default copy-constructor:
131  DoubleCRT(const DoubleCRT& other) = default;
132 
139  // VJS-FIXME: it is not clear what the restrictions on deg(poly) are:
140  // must we have deg(poly) < phi(m)? Or is it deg(poly) < m?
141  DoubleCRT(const NTL::ZZX& poly,
142  const Context& _context,
143  const IndexSet& indexSet);
144 
145 // FIXME-IndexSet
146 #if 0
147  DoubleCRT(const NTL::ZZX&poly, const Context& _context);
148 #endif
149 
150 // FIXME-IndexSet
151 #if 0
156  // declared "explicit" to avoid implicit type conversion
157  explicit DoubleCRT(const NTL::ZZX&poly);
158 #endif
159 
161  DoubleCRT(const zzX& poly, const Context& _context, const IndexSet& indexSet);
162 
163 // FIXME-IndexSet
164 #if 0
165  DoubleCRT(const zzX&poly, const Context& _context);
166  explicit DoubleCRT(const zzX&poly);
167 #endif
168 
169 // FIXME-IndexSet
170 #if 0
171  // Without specifying a ZZX, we get the zero polynomial
172  explicit DoubleCRT(const Context &_context);
173  // declare "explicit" to avoid implicit type conversion
174 #endif
175 
177  DoubleCRT(const Context& _context, const IndexSet& indexSet);
178 
179  // Assignment operator, the following two lines are equivalent:
180  // DoubleCRT dCRT(poly, context, indexSet);
181  // or
182  // DoubleCRT dCRT(context, indexSet); dCRT = poly;
183 
184  DoubleCRT& operator=(const DoubleCRT& other);
185 
186  // Copy only the primes in s \intersect other.getIndexSet()
187  // void partialCopy(const DoubleCRT& other, const IndexSet& s);
188 
189  DoubleCRT& operator=(const zzX& poly);
190  DoubleCRT& operator=(const NTL::ZZX& poly);
191  DoubleCRT& operator=(const NTL::ZZ& num);
192  DoubleCRT& operator=(const long num)
193  {
194  *this = NTL::to_ZZ(num);
195  return *this;
196  }
197 
198  // more constructors to round out the interface
199  // implemented by delegation and assignment
200  DoubleCRT(const NTL::ZZ& num,
201  const Context& context,
202  const IndexSet& indexSet) :
203  DoubleCRT(context, indexSet)
204  {
205  *this = num;
206  }
207 
208  DoubleCRT(long num, const Context& context, const IndexSet& indexSet) :
209  DoubleCRT(context, indexSet)
210  {
211  *this = num;
212  }
213 
215  long getOneRow(NTL::Vec<long>& row, long idx, bool positive = false) const;
216  long getOneRow(NTL::zz_pX& row, long idx) const; // This affects NTL's modulus
217 
224  void toPoly(NTL::ZZX& p, const IndexSet& s, bool positive = false) const;
225  void toPoly(NTL::ZZX& p, bool positive = false) const;
226 
227  // The variant toPolyMod has another argument, which is a modulus Q, and it
228  // computes toPoly() mod Q. This is offered as a separate function in the
229  // hope that one day we will figure out a more efficient method of computing
230  // this. Right now it is not implemented
231  //
232  // void toPolyMod(ZZX& p, const ZZ &Q, const IndexSet& s) const;
233 
234  bool operator==(const DoubleCRT& other) const
235  {
236  assertEq(&context,
237  &other.context,
238  "Cannot compare DoubleCRTs with different context");
239  return map == other.map;
240  }
241 
242  bool operator!=(const DoubleCRT& other) const { return !(*this == other); }
243 
244  // @brief Set to zero
246  {
247  *this = NTL::ZZ::zero();
248  return *this;
249  }
250 
251  // @brief Set to one
253  {
254  *this = 1;
255  return *this;
256  }
257 
261  NTL::xdouble breakIntoDigits(std::vector<DoubleCRT>& dgts) const;
262 
267  void addPrimes(const IndexSet& s1, NTL::ZZX* poly_p = 0);
268 
271  double addPrimesAndScale(const IndexSet& s1);
272 
274  void removePrimes(const IndexSet& s1) { map.remove(s1); }
275 
277  void setPrimes(const IndexSet& s1)
278  {
279  addPrimes(s1 / getIndexSet());
280  removePrimes(getIndexSet() / s1);
281  }
282 
289 
290  // Addition, negation, subtraction
291  DoubleCRT& Negate(const DoubleCRT& other);
292  DoubleCRT& Negate() { return Negate(*this); }
293 
294  DoubleCRT& operator+=(const DoubleCRT& other) { return Op(other, AddFun()); }
295 
296  DoubleCRT& operator+=(const NTL::ZZX& poly) { return Op(poly, AddFun()); }
297 
298  DoubleCRT& operator+=(const NTL::ZZ& num) { return Op(num, AddFun()); }
299 
300  DoubleCRT& operator+=(long num) { return Op(NTL::to_ZZ(num), AddFun()); }
301 
302  DoubleCRT& operator-=(const DoubleCRT& other) { return Op(other, SubFun()); }
303 
304  DoubleCRT& operator-=(const NTL::ZZX& poly) { return Op(poly, SubFun()); }
305 
306  DoubleCRT& operator-=(const NTL::ZZ& num) { return Op(num, SubFun()); }
307 
308  DoubleCRT& operator-=(long num) { return Op(NTL::to_ZZ(num), SubFun()); }
309 
310  // These are the prefix versions, ++dcrt and --dcrt.
311  DoubleCRT& operator++() { return (*this += 1); };
312  DoubleCRT& operator--() { return (*this -= 1); };
313 
314  // These are the postfix versions -- return type is void,
315  // so it is offered just for style...
316  void operator++(int) { *this += 1; };
317  void operator--(int) { *this -= 1; };
318 
319  // Multiplication
321  {
322  // return Op(other,MulFun());
323  return do_mul(other);
324  }
325 
326  DoubleCRT& operator*=(const NTL::ZZX& poly) { return Op(poly, MulFun()); }
327 
328  DoubleCRT& operator*=(const NTL::ZZ& num) { return Op(num, MulFun()); }
329 
330  DoubleCRT& operator*=(long num) { return Op(NTL::to_ZZ(num), MulFun()); }
331 
332  // NOTE: the matchIndexSets business in the following routines
333  // is DEPRECATED. The requirement is that the prime set of other
334  // must contain the prime set of *this. If not, an exception is raised.
335  // Also, if matchIndexSets == true and the prime set of *this does
336  // not contain the prime set of other, an exception is also raised.
337 
338  // Procedural equivalents, supporting also the matchIndexSets flag
339  void Add(const DoubleCRT& other, bool matchIndexSets = true)
340  {
341  Op(other, AddFun(), matchIndexSets);
342  }
343 
344  void Sub(const DoubleCRT& other, bool matchIndexSets = true)
345  {
346  Op(other, SubFun(), matchIndexSets);
347  }
348 
349  void Mul(const DoubleCRT& other, bool matchIndexSets = true)
350  {
351  // Op(other, MulFun(), matchIndexSets);
352  do_mul(other, matchIndexSets);
353  }
354 
355  // Division by constant
356  DoubleCRT& operator/=(const NTL::ZZ& num);
357  DoubleCRT& operator/=(long num) { return (*this /= NTL::to_ZZ(num)); }
358 
360  void Exp(long k);
361 
363  void automorph(long k);
365  {
366  automorph(k);
367  return *this;
368  }
369 
371  void complexConj();
373 
374  // Utilities
375 
376  const Context& getContext() const { return context; }
377  const IndexMap<NTL::vec_long>& getMap() const { return map; }
378  const IndexSet& getIndexSet() const { return map.getIndexSet(); }
379 
380  // Choose random DoubleCRT's, either at random or with small/Gaussian
381  // coefficients.
382 
384  void randomize(const NTL::ZZ* seed = nullptr);
385 
389 
391  double sampleSmall();
392  double sampleSmallBounded();
393 
395  double sampleHWt(long Hwt);
396  double sampleHWtBounded(long Hwt);
397 
400  double sampleGaussian(double stdev = 0.0);
401  double sampleGaussianBounded(double stdev = 0.0);
402  NTL::xdouble sampleGaussianBounded(NTL::xdouble stdev);
403 
405  double sampleUniform(long B);
406  NTL::xdouble sampleUniform(const NTL::ZZ& B);
407 
408  // used to implement modulus switching
409  void scaleDownToSet(const IndexSet& s, long ptxtSpace, NTL::ZZX& delta);
410 
411  void FFT(const NTL::ZZX& poly, const IndexSet& s);
412  void FFT(const zzX& poly, const IndexSet& s);
413  // for internal use
414 
415  void reduce() const {} // place-holder for consistent with AltCRT
416 
417  // Raw I/O
418 
423  void writeTo(std::ostream& str) const;
424 
431  static DoubleCRT readFrom(std::istream& str, const Context& context);
432 
438  void read(std::istream& str);
439 
445  void writeToJSON(std::ostream& str) const;
446 
451  JsonWrapper writeToJSON() const;
452 
460  static DoubleCRT readFromJSON(std::istream& str, const Context& context);
461 
469  static DoubleCRT readFromJSON(const JsonWrapper& j, const Context& context);
470 
476  void readJSON(std::istream& str);
477 
483  void readJSON(const JsonWrapper& j);
484 
485  // I/O: ONLY the matrix is outputted/recovered, not the moduli chain!! An
486  // error is raised on input if this is not consistent with the current chain
487 
488  friend std::ostream& operator<<(std::ostream& s, const DoubleCRT& d);
489  friend std::istream& operator>>(std::istream& s, DoubleCRT& d);
490 };
491 
492 inline void conv(DoubleCRT& d, const NTL::ZZX& p) { d = p; }
493 
494 // FIXME-IndexSet
495 #if 0
496 inline DoubleCRT to_DoubleCRT(const NTL::ZZX& p) {
497  return DoubleCRT(p);
498 }
499 #endif
500 
501 inline void conv(NTL::ZZX& p, const DoubleCRT& d) { d.toPoly(p); }
502 
503 inline NTL::ZZX to_ZZX(const DoubleCRT& d)
504 {
505  NTL::ZZX p;
506  d.toPoly(p);
507  return p;
508 }
509 
510 typedef std::shared_ptr<DoubleCRT> DCRTptr;
511 typedef std::shared_ptr<NTL::ZZX> ZZXptr;
512 
513 } // namespace helib
514 
515 #endif // #ifndef HELIB_DOUBLECRT_H
Maintaining the HE scheme parameters.
Definition: Context.h:100
A helper class to enforce consistency within an DoubleCRTHelper object.
Definition: DoubleCRT.h:34
virtual void init(NTL::vec_long &v)
the init method ensures that all rows have the same size
Definition: DoubleCRT.h:42
virtual IndexMapInit< NTL::vec_long > * clone() const
clone allocates a new object and copies the content
Definition: DoubleCRT.h:45
Implementing polynomials (elements in the ring R_Q) in double-CRT form.
Definition: DoubleCRT.h:76
void readJSON(std::istream &str)
In-place read from the str std::istream the serialized ciphertext (Ctxt) object.
Definition: DoubleCRT.cpp:1443
void Mul(const DoubleCRT &other, bool matchIndexSets=true)
Definition: DoubleCRT.h:349
void setPrimes(const IndexSet &s1)
@ brief make prime set equal to s1
Definition: DoubleCRT.h:277
DoubleCRT & operator+=(const NTL::ZZ &num)
Definition: DoubleCRT.h:298
DoubleCRT & operator/=(const NTL::ZZ &num)
Definition: DoubleCRT.cpp:970
DoubleCRT(const NTL::ZZ &num, const Context &context, const IndexSet &indexSet)
Definition: DoubleCRT.h:200
void scaleDownToSet(const IndexSet &s, long ptxtSpace, NTL::ZZX &delta)
Definition: DoubleCRT.cpp:1312
DoubleCRT & operator*=(const NTL::ZZX &poly)
Definition: DoubleCRT.h:326
void addPrimes(const IndexSet &s1, NTL::ZZX *poly_p=0)
Expand the index set by s1. It is assumed that s1 is disjoint from the current index set....
Definition: DoubleCRT.cpp:413
DoubleCRT & operator>>=(long k)
Definition: DoubleCRT.h:364
void Sub(const DoubleCRT &other, bool matchIndexSets=true)
Definition: DoubleCRT.h:344
DoubleCRT & operator=(const DoubleCRT &other)
Definition: DoubleCRT.cpp:663
DoubleCRT & operator*=(long num)
Definition: DoubleCRT.h:330
double sampleGaussianBounded(double stdev=0.0)
Definition: DoubleCRT.cpp:1276
DoubleCRT & operator-=(const NTL::ZZX &poly)
Definition: DoubleCRT.h:304
DoubleCRT & operator++()
Definition: DoubleCRT.h:311
DoubleCRT & Negate()
Definition: DoubleCRT.h:292
double sampleHWtBounded(long Hwt)
Definition: DoubleCRT.cpp:1257
friend std::istream & operator>>(std::istream &s, DoubleCRT &d)
Definition: DoubleCRT.cpp:1372
DoubleCRT & operator*=(const DoubleCRT &other)
Definition: DoubleCRT.h:320
bool operator!=(const DoubleCRT &other) const
Definition: DoubleCRT.h:242
DoubleCRT & SetOne()
Definition: DoubleCRT.h:252
DoubleCRT(const DoubleCRT &other)=default
NTL::xdouble breakIntoDigits(std::vector< DoubleCRT > &dgts) const
Break into n digits,according to the primeSets in context.digits. See Section 3.1....
Definition: DoubleCRT.cpp:327
const IndexMap< NTL::vec_long > & getMap() const
Definition: DoubleCRT.h:377
DoubleCRT & SetZero()
Definition: DoubleCRT.h:245
JsonWrapper writeToJSON() const
Write out the ciphertext (Ctxt) object to a JsonWrapper.
Definition: DoubleCRT.cpp:1416
void toPoly(NTL::ZZX &p, const IndexSet &s, bool positive=false) const
Recovering the polynomial in coefficient representation. This yields an integer polynomial with coeff...
Definition: DoubleCRT.cpp:773
double sampleSmall()
Coefficients are -1/0/1, Prob[0]=1/2.
Definition: DoubleCRT.cpp:1229
void FFT(const NTL::ZZX &poly, const IndexSet &s)
Definition: DoubleCRT.cpp:53
double addPrimesAndScale(const IndexSet &s1)
Expand index set by s1, and multiply by Prod_{q in s1}. s1 is disjoint from the current index set,...
Definition: DoubleCRT.cpp:451
DoubleCRT & operator-=(const NTL::ZZ &num)
Definition: DoubleCRT.h:306
double sampleUniform(long B)
Coefficients are uniform in [-B..B].
Definition: DoubleCRT.cpp:1296
void reduce() const
Definition: DoubleCRT.h:415
double sampleSmallBounded()
Definition: DoubleCRT.cpp:1238
DoubleCRT & operator-=(long num)
Definition: DoubleCRT.h:308
void randomize(const NTL::ZZ *seed=nullptr)
Fills each row i with random ints mod pi, uses NTL's PRG.
Definition: DoubleCRT.cpp:1106
void removePrimes(const IndexSet &s1)
Remove s1 from the index set.
Definition: DoubleCRT.h:274
DoubleCRT & operator+=(long num)
Definition: DoubleCRT.h:300
void operator++(int)
Definition: DoubleCRT.h:316
void Add(const DoubleCRT &other, bool matchIndexSets=true)
Definition: DoubleCRT.h:339
long getOneRow(NTL::Vec< long > &row, long idx, bool positive=false) const
Get one row of a polynomial.
Definition: DoubleCRT.cpp:749
void Exp(long k)
Small-exponent polynomial exponentiation.
Definition: DoubleCRT.cpp:990
void writeTo(std::ostream &str) const
Write out the DoubleCRT object in binary format.
Definition: DoubleCRT.cpp:1378
static DoubleCRT readFrom(std::istream &str, const Context &context)
Read from the stream the serialized DoubleCRT object in binary format.
Definition: DoubleCRT.cpp:1390
const IndexSet & getIndexSet() const
Definition: DoubleCRT.h:378
DoubleCRT & operator+=(const DoubleCRT &other)
Definition: DoubleCRT.h:294
const Context & getContext() const
Definition: DoubleCRT.h:376
DoubleCRT & operator-=(const DoubleCRT &other)
Definition: DoubleCRT.h:302
DoubleCRT & operator/=(long num)
Definition: DoubleCRT.h:357
double sampleHWt(long Hwt)
Coefficients are -1/0/1 with pre-specified number of nonzeros.
Definition: DoubleCRT.cpp:1248
void complexConj()
Compute the complex conjugate, the same as automorph(m-1)
Definition: DoubleCRT.cpp:1088
double sampleGaussian(double stdev=0.0)
Coefficients are Gaussians Return a high probability bound on L-infty norm of canonical embedding.
Definition: DoubleCRT.cpp:1266
bool operator==(const DoubleCRT &other) const
Definition: DoubleCRT.h:234
DoubleCRT & operator--()
Definition: DoubleCRT.h:312
DoubleCRT & operator*=(const NTL::ZZ &num)
Definition: DoubleCRT.h:328
friend std::ostream & operator<<(std::ostream &s, const DoubleCRT &d)
Definition: DoubleCRT.cpp:1366
DoubleCRT & operator=(const long num)
Definition: DoubleCRT.h:192
void operator--(int)
Definition: DoubleCRT.h:317
static DoubleCRT readFromJSON(std::istream &str, const Context &context)
Read from the stream the serialized ciphertext (Ctxt) object using JSON format.
Definition: DoubleCRT.cpp:1429
void automorph(long k)
Apply the automorphism F(X) --> F(X^k) (with gcd(k,m)=1)
Definition: DoubleCRT.cpp:1008
void read(std::istream &str)
In-place read from the stream the serialized DoubleCRT object in binary format.
Definition: DoubleCRT.cpp:1398
DoubleCRT(long num, const Context &context, const IndexSet &indexSet)
Definition: DoubleCRT.h:208
DoubleCRT & operator+=(const NTL::ZZX &poly)
Definition: DoubleCRT.h:296
void remove(long j)
Delete indexes from IndexSet, may cause objects to be destroyed.
Definition: IndexMap.h:103
const IndexSet & getIndexSet() const
Get the underlying index set.
Definition: IndexMap.h:66
Initializing elements in an IndexMap.
Definition: IndexMap.h:28
A dynamic set of non-negative integers.
Definition: IndexSet.h:33
Definition: apiAttributes.h:21
std::shared_ptr< NTL::ZZX > ZZXptr
Definition: DoubleCRT.h:511
std::shared_ptr< DoubleCRT > DCRTptr
Definition: DoubleCRT.h:510
NTL::Vec< long > zzX
Definition: zzX.h:24
NTL::ZZX to_ZZX(const DoubleCRT &d)
Definition: DoubleCRT.h:503
void assertEq(const T &a, const T &b, const std::string &message)
Definition: assertions.h:108
void conv(DoubleCRT &d, const NTL::ZZX &p)
Definition: DoubleCRT.h:492
Definition: JsonWrapper.h:9