NumbTh.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_NUMBTH_H
13 #define HELIB_NUMBTH_H
18 #include <algorithm>
19 #include <vector>
20 #include <set>
21 #include <cmath>
22 #include <complex>
23 #include <string>
24 #include <climits>
25 #include <cmath>
26 #include <iostream>
27 #include <fstream>
28 #include <sstream>
29 #include <ctime>
30 #include <memory>
31 
32 #include <NTL/version.h>
33 #include <NTL/ZZ.h>
34 #include <NTL/ZZX.h>
35 #include <NTL/ZZ_p.h>
36 #include <NTL/ZZ_pX.h>
37 #include <NTL/xdouble.h>
38 
39 #include <NTL/mat_GF2.h>
40 #include <NTL/mat_GF2E.h>
41 #include <NTL/GF2XFactoring.h>
42 
43 #include <NTL/mat_lzz_p.h>
44 #include <NTL/mat_lzz_pE.h>
45 #include <NTL/lzz_pXFactoring.h>
46 
47 #include <NTL/GF2EX.h>
48 #include <NTL/lzz_pEX.h>
49 
50 #include <NTL/FFT.h>
51 
52 // Test for the "right version" of NTL (currently 11.0.0)
53 #if (NTL_MAJOR_VERSION < 11)
54 #error "This version of HElib requires NTL version 11.0.0 or above"
55 #endif
56 
57 #include <helib/assertions.h>
58 #include <helib/apiAttributes.h>
59 
60 namespace helib {
61 
62 extern const long double PI;
63 
64 namespace FHEglobals {
69 extern bool dryRun;
70 
77 extern std::set<long>* automorphVals;
78 extern std::set<long>* automorphVals2;
79 
80 } // namespace FHEglobals
81 
82 inline bool setDryRun(bool toWhat = true)
83 {
84  return (FHEglobals::dryRun = toWhat);
85 }
86 
87 inline bool isDryRun() { return FHEglobals::dryRun; }
88 
89 inline void setAutomorphVals(std::set<long>* aVals)
90 {
92 }
93 
94 inline bool isSetAutomorphVals()
95 {
96  return FHEglobals::automorphVals != nullptr;
97 }
98 
99 inline void recordAutomorphVal(long k) { FHEglobals::automorphVals->insert(k); }
100 
101 inline void setAutomorphVals2(std::set<long>* aVals)
102 {
104 }
105 
106 inline bool isSetAutomorphVals2()
107 {
108  return FHEglobals::automorphVals2 != nullptr;
109 }
110 
111 inline void recordAutomorphVal2(long k)
112 {
113  FHEglobals::automorphVals2->insert(k);
114 }
115 
116 typedef long LONG; // using this to identify casts that we should
117  // really get rid of at some point in the future
118 
128 long bitSetToLong(long bits, long bitSize);
129 
134 
135 long mcMod(long a, long b);
136 long mcDiv(long a, long b);
137 
140 inline long balRem(long a, long q)
141 {
142  if (a > q / 2)
143  return a - q;
144  else
145  return a;
146 }
147 
149 inline double fsquare(double x) { return x * x; }
150 
152 long multOrd(long p, long m);
153 
162 void ppsolve(NTL::vec_zz_pE& x,
163  const NTL::mat_zz_pE& A,
164  const NTL::vec_zz_pE& b,
165  long p,
166  long r);
167 
169 void ppsolve(NTL::vec_GF2E& x,
170  const NTL::mat_GF2E& A,
171  const NTL::vec_GF2E& b,
172  long p,
173  long r);
174 
180 void ppInvert(NTL::mat_zz_p& X, const NTL::mat_zz_p& A, long p, long r);
181 void ppInvert(NTL::mat_zz_pE& X, const NTL::mat_zz_pE& A, long p, long r);
182 
183 // variants for GF2/GF2E to help with template code
184 inline void ppInvert(NTL::mat_GF2& X,
185  const NTL::mat_GF2& A,
186  UNUSED long p,
187  UNUSED long r)
188 {
189  NTL::inv(X, A);
190 }
191 
192 inline void ppInvert(NTL::mat_GF2E& X,
193  const NTL::mat_GF2E& A,
194  UNUSED long p,
195  UNUSED long r)
196 {
197  NTL::inv(X, A);
198 }
199 
200 void buildLinPolyMatrix(NTL::mat_zz_pE& M, long p);
201 void buildLinPolyMatrix(NTL::mat_GF2E& M, long p);
202 
210 void buildLinPolyCoeffs(NTL::vec_zz_pE& C,
211  const NTL::vec_zz_pE& L,
212  long p,
213  long r);
214 
216 void buildLinPolyCoeffs(NTL::vec_GF2E& C,
217  const NTL::vec_GF2E& L,
218  long p,
219  long r);
220 
225 void applyLinPoly(NTL::zz_pE& beta,
226  const NTL::vec_zz_pE& C,
227  const NTL::zz_pE& alpha,
228  long p);
229 
231 void applyLinPoly(NTL::GF2E& beta,
232  const NTL::vec_GF2E& C,
233  const NTL::GF2E& alpha,
234  long p);
235 
237 inline double log2(const NTL::xdouble& x) { return log(x) * 1.442695040889; }
238 
241 void factorize(std::vector<long>& factors, long N);
242 void factorize(std::vector<NTL::ZZ>& factors, const NTL::ZZ& N);
243 
246 void factorize(NTL::Vec<NTL::Pair<long, long>>& factors, long N);
247 
249 void pp_factorize(std::vector<long>& factors, long N);
250 
252 void phiN(long& phiN, std::vector<long>& facts, long N);
253 void phiN(NTL::ZZ& phiN, std::vector<NTL::ZZ>& facts, const NTL::ZZ& N);
254 
256 long phi_N(long N);
257 
260 long findGenerators(std::vector<long>& gens,
261  std::vector<long>& ords,
262  long m,
263  long p,
264  const std::vector<long>& candidates = std::vector<long>());
265 
267 void FindPrimitiveRoot(NTL::zz_p& r, unsigned long e);
268 void FindPrimitiveRoot(NTL::ZZ_p& r, unsigned long e);
269 
271 long mobius(long n);
272 
274 NTL::ZZX Cyclotomic(long N);
275 
277 NTL::ZZX makeIrredPoly(long p, long d);
278 
280 long primroot(long N, long phiN);
281 
283 long ord(long N, long p);
284 
285 inline bool is2power(long m)
286 {
287  long k = NTL::NextPowerOfTwo(m);
288  return (((unsigned long)m) == (1UL << k));
289 }
290 
292 double RandomReal();
293 
295 std::complex<double> RandomComplex();
296 
297 // Returns a random mod p polynomial of degree < n
298 NTL::ZZX RandPoly(long n, const NTL::ZZ& p);
299 
301 
307 void PolyRed(NTL::ZZX& out, const NTL::ZZX& in, long q, bool abs = false);
308 void PolyRed(NTL::ZZX& out,
309  const NTL::ZZX& in,
310  const NTL::ZZ& q,
311  bool abs = false);
312 
313 inline void PolyRed(NTL::ZZX& F, long q, bool abs = false)
314 {
315  PolyRed(F, F, q, abs);
316 }
317 
318 inline void PolyRed(NTL::ZZX& F, const NTL::ZZ& q, bool abs = false)
319 {
320  PolyRed(F, F, q, abs);
321 }
322 
323 void vecRed(NTL::Vec<NTL::ZZ>& out,
324  const NTL::Vec<NTL::ZZ>& in,
325  long q,
326  bool abs);
327 
328 void vecRed(NTL::Vec<NTL::ZZ>& out,
329  const NTL::Vec<NTL::ZZ>& in,
330  const NTL::ZZ& q,
331  bool abs);
333 
334 // The interface has changed so that abs defaults to false,
335 // which is more consistent with the other interfaces.
336 // Calls without any explicit value for abs should generate a
337 // "deprecated" warning.
338 
339 void MulMod(NTL::ZZX& out, const NTL::ZZX& f, long a, long q, bool abs);
340 
341 [[deprecated("Please use MulMod with explicit abs argument.")]] inline void
342 MulMod(NTL::ZZX& out, const NTL::ZZX& f, long a, long q)
343 {
344  MulMod(out, f, a, q, false);
345 }
346 
347 inline NTL::ZZX MulMod(const NTL::ZZX& f, long a, long q, bool abs)
348 {
349  NTL::ZZX res;
350  MulMod(res, f, a, q, abs);
351  return res;
352 }
353 
354 [[deprecated("Please use MulMod with explicit abs argument.")]] inline NTL::ZZX
355 MulMod(const NTL::ZZX& f, long a, long q)
356 {
357  NTL::ZZX res;
358  MulMod(res, f, a, q, false);
359  return res;
360 }
361 
364 void balanced_MulMod(NTL::ZZX& out, const NTL::ZZX& f, long a, long q);
365 
368 inline void convert(long& x1, const NTL::GF2X& x2) { x1 = rep(ConstTerm(x2)); }
369 inline void convert(long& x1, const NTL::zz_pX& x2) { x1 = rep(ConstTerm(x2)); }
370 void convert(NTL::vec_zz_pE& X, const std::vector<NTL::ZZX>& A);
371 void convert(NTL::mat_zz_pE& X, const std::vector<std::vector<NTL::ZZX>>& A);
372 void convert(std::vector<NTL::ZZX>& X, const NTL::vec_zz_pE& A);
373 void convert(std::vector<std::vector<NTL::ZZX>>& X, const NTL::mat_zz_pE& A);
374 void convert(NTL::Vec<long>& out, const NTL::ZZX& in);
375 
376 void convert(NTL::Vec<long>& out, const NTL::zz_pX& in, bool symmetric = false);
377 
378 void convert(NTL::Vec<long>& out, const NTL::GF2X& in);
379 void convert(NTL::ZZX& out, const NTL::Vec<long>& in);
380 void convert(NTL::GF2X& out, const NTL::Vec<long>& in);
381 // right now, this is just a place-holder...it may or may not
382 // eventually be further fleshed out
383 
385 
387 template <typename T1, typename T2>
388 void convert(T1& x1, const T2& x2)
389 {
390  NTL::conv(x1, x2);
391 }
392 
394 inline void convert(long& x1, bool x2) { x1 = x2; }
395 inline void convert(double& x1, bool x2) { x1 = x2; }
396 inline void convert(std::complex<double>& x1, bool x2) { x1 = x2; }
397 inline void convert(std::complex<double>& x1, long x2) { x1 = x2; }
398 inline void convert(std::complex<double>& x1, double x2) { x1 = x2; }
399 
400 inline void convert(NTL::ZZX& x1, NTL::GF2 x2) { x1 = rep(x2); }
401 inline void convert(NTL::ZZX& x1, NTL::zz_p x2) { x1 = rep(x2); }
402 
404 template <typename T1, typename T2>
405 void convert(std::vector<T1>& v1, const std::vector<T2>& v2)
406 {
407  long n = v2.size();
408  v1.resize(n);
409  for (long i = 0; i < n; i++) {
410  // Applying static_cast<const T2&> to avoid issues when std::vector<T2>
411  // operator[] returns a non-T2 object (this happens for std::vector<bool>
412  // that returns a __bit_const_reference object).
413  convert(v1[i], static_cast<const T2&>(v2[i]));
414  }
415 }
416 
417 template <typename T1, typename T2>
418 void convert(std::vector<T1>& v1, const NTL::Vec<T2>& v2)
419 {
420  long n = v2.length();
421  v1.resize(n);
422  for (long i = 0; i < n; i++)
423  convert(v1[i], v2[i]);
424 }
425 
426 template <typename T1, typename T2>
427 void convert(NTL::Vec<T1>& v1, const std::vector<T2>& v2)
428 {
429  long n = v2.size();
430  v1.SetLength(n);
431  for (long i = 0; i < n; i++) {
432  // Applying static_cast<const T2&> to avoid issues when std::vector<T2>
433  // operator[] returns a non-T2 object (this happens for std::vector<bool>
434  // that returns a __bit_const_reference object).
435  convert(v1[i], static_cast<const T2&>(v2[i]));
436  }
437 }
438 
440 template <typename T>
441 void convert(std::vector<T>& v1, const std::vector<T>& v2)
442 {
443  v1 = v2;
444 }
445 
446 template <typename T1, typename T2>
447 T1 convert(const T2& v2)
448 {
449  T1 v1;
450  convert(v1, v2);
451  return v1;
452 }
453 
454 template <typename T>
455 std::vector<T> vector_replicate(const T& a, long n)
456 {
457  std::vector<T> res;
458  res.resize(n);
459  for (long i = 0; i < n; i++)
460  res[i] = a;
461  return res;
462 }
463 
464 template <typename T>
465 std::vector<T> Vec_replicate(const T& a, long n)
466 {
467  NTL::Vec<T> res;
468  res.SetLength(n);
469  for (long i = 0; i < n; i++)
470  res[i] = a;
471  return res;
472 }
473 
474 // some unsafe conversions
475 inline void project(std::vector<double>& out,
476  const std::vector<std::complex<double>>& in)
477 {
478  long n = in.size();
479  out.resize(n);
480  for (long i = 0; i < n; i++)
481  out[i] = in[i].real();
482 }
483 
484 inline void project_and_round(std::vector<long>& out,
485  const std::vector<std::complex<double>>& in)
486 {
487  long n = in.size();
488  out.resize(n);
489  for (long i = 0; i < n; i++)
490  out[i] = std::round(in[i].real());
491 }
492 
494 long computeProd(const NTL::Vec<long>& vec);
495 long computeProd(const std::vector<long>& vec);
496 
497 // some useful operations
498 void mul(std::vector<NTL::ZZX>& x, const std::vector<NTL::ZZX>& a, long b);
499 void div(std::vector<NTL::ZZX>& x, const std::vector<NTL::ZZX>& a, long b);
500 void add(std::vector<NTL::ZZX>& x,
501  const std::vector<NTL::ZZX>& a,
502  const std::vector<NTL::ZZX>& b);
503 
506 long is_in(long x, int* X, long sz);
507 
510 inline long CRTcoeff(long p, long q, bool symmetric = false)
511 {
512  long pInv = NTL::InvMod(p, q); // p^-1 mod q \in [0,q)
513  if (symmetric && 2 * pInv >= q)
514  return p * (pInv - q);
515  else
516  return p * pInv;
517 }
518 
533 template <class zzvec> // zzvec can be vec_NTL::ZZ, vec_long, or Vec<zz_p>
534 bool intVecCRT(NTL::vec_ZZ& vp, const NTL::ZZ& p, const zzvec& vq, long q);
535 
546 template <typename T, bool maxFlag>
547 long argminmax(std::vector<T>& v)
548 {
549  if (v.size() < 1)
550  return -1; // error: this is an empty array
551  unsigned long idx = 0;
552  T target = v[0];
553  for (unsigned long i = 1; i < v.size(); i++)
554  if (maxFlag) {
555  if (v[i] > target) {
556  target = v[i];
557  idx = i;
558  }
559  } else {
560  if (v[i] < target) {
561  target = v[i];
562  idx = i;
563  }
564  }
565  return (long)idx;
566 }
567 
568 template <typename T>
569 long argmax(std::vector<T>& v)
570 {
571  return argminmax<T, true>(v);
572 }
573 
574 template <typename T>
575 long argmin(std::vector<T>& v)
576 {
577  return argminmax<T, false>(v);
578 }
579 
582 inline long argmax(std::vector<long>& v, bool (*moreThan)(long, long))
583 {
584  if (v.size() < 1)
585  return -INT_MAX; // error: this is an empty array
586  unsigned long idx = 0;
587  long target = v[0];
588  for (unsigned long i = 1; i < v.size(); i++)
589  if ((*moreThan)(v[i], target)) {
590  target = v[i];
591  idx = i;
592  }
593  return (long)idx;
594 }
595 
596 // Check that x is in 1 += epsilon
597 inline bool closeToOne(const NTL::xdouble& x, long p)
598 {
599  double pinv = 1.0 / p;
600  return (x < (1.0 + pinv) && x > (1 - pinv));
601 }
602 
603 // Use continued fractions to approximate a float x as x ~ a/b
604 std::pair<long, long> rationalApprox(double x, long denomBound = 0);
605 std::pair<NTL::ZZ, NTL::ZZ> rationalApprox(
606  NTL::xdouble x,
607  NTL::xdouble denomBound = NTL::xdouble(0.0));
628 {
629 private:
630  NTL::ZZ state;
631  bool restored;
632 
633 public:
635  {
636  RandomBits(state, 512);
637  restored = false;
638  }
639 
641  void restore()
642  {
643  if (!restored) {
644  SetSeed(state);
645  restored = true;
646  }
647  }
648 
650 
651 private:
652  RandomState(const RandomState&); // disable copy constructor
653  RandomState& operator=(const RandomState&); // disable assignment
654 };
655 
658 void seekPastChar(std::istream& str, int cc);
659 
661 template <typename T>
662 void reverse(NTL::Vec<T>& v, long lo, long hi)
663 {
664  long n = v.length();
665  assertInRange(lo, 0l, hi, "Invalid argument: Bad interval", true);
666  assertTrue(hi < n, "Invalid argument: Interval exceeds vector size");
667 
668  if (lo >= hi)
669  return;
670 
671  for (long i = lo, j = hi; i < j; i++, j--)
672  swap(v[i], v[j]);
673 }
674 
676 // Example: rotate by 1 means [0 1 2 3] -> [3 0 1 2]
677 // rotate by -1 means [0 1 2 3] -> [1 2 3 0]
678 template <typename T>
679 void rotate(NTL::Vec<T>& v, long k)
680 {
681  long n = v.length();
682  if (n <= 1)
683  return;
684 
685  k %= n;
686  if (k < 0)
687  k += n;
688 
689  if (k == 0)
690  return;
691 
692  reverse(v, 0, n - 1);
693  reverse(v, 0, k - 1);
694  reverse(v, k, n - 1);
695 }
696 
697 // An experimental facility as it is annoying that vector::size() is an
698 // unsigned quantity. This leads to all kinds of annoying warning messages.
700 template <typename T>
701 inline long lsize(const std::vector<T>& v)
702 {
703  return (long)v.size();
704 }
705 
707 
708 // Utility functions, release memory of std::vector and NTL::Vec
709 template <typename T>
710 void killVec(std::vector<T>& vec)
711 {
712  std::vector<T>().swap(vec);
713 }
714 
715 template <typename T>
716 void killVec(NTL::Vec<T>& vec)
717 {
718  vec.kill();
719 }
720 
721 // Set length to zero, but don't necessarily release memory
722 template <typename T>
723 void setLengthZero(std::vector<T>& vec)
724 {
725  if (vec.size() > 0)
726  vec.resize(0, vec[0]);
727 }
728 
729 template <typename T>
730 void setLengthZero(NTL::Vec<T>& vec)
731 {
732  if (vec.length() > 0)
733  vec.SetLength(0, vec[0]);
734 }
735 
736 template <typename T>
737 inline long lsize(const NTL::Vec<T>& v)
738 {
739  return v.length();
740 }
741 
742 template <typename T>
743 void resize(NTL::Vec<T>& v, long sz, const T& val)
744 {
745  return v.SetLength(sz, val);
746 }
747 
748 template <typename T>
749 void resize(std::vector<T>& v, long sz, const T& val)
750 {
751  return v.resize(sz, val);
752 }
753 
754 template <typename T>
755 void resize(NTL::Vec<T>& v, long sz)
756 {
757  return v.SetLength(sz);
758 }
759 
760 template <typename T>
761 void resize(std::vector<T>& v, long sz)
762 {
763  return v.resize(sz);
764 }
765 
767 // Believe it or not, this is really the way to do it...
768 template <typename T1, typename T2>
769 bool sameObject(const T1* p1, const T2* p2)
770 {
771  return dynamic_cast<const void*>(p1) == dynamic_cast<const void*>(p2);
772 }
773 
775 void ModComp(NTL::ZZX& res,
776  const NTL::ZZX& g,
777  const NTL::ZZX& h,
778  const NTL::ZZX& f);
779 
781 long polyEvalMod(const NTL::ZZX& poly, long x, long p);
782 
785 void interpolateMod(NTL::ZZX& poly,
786  const NTL::vec_long& x,
787  const NTL::vec_long& y,
788  long p,
789  long e = 1);
790 
792 inline long divc(long a, long b) { return (a + b - 1) / b; }
793 
798 {
799 public:
800  long m;
801  NTL::zz_pX f;
802  long n;
803 
805 
806  long k, k1;
807  NTL::fftRep R0, R1;
808 
809  NTL::zz_pXModulus fm; // just in case...
810 
811  zz_pXModulus1(long _m, const NTL::zz_pX& _f);
812 
813  const NTL::zz_pXModulus& upcast() const { return fm; }
814 };
815 
816 void rem(NTL::zz_pX& r, const NTL::zz_pX& a, const zz_pXModulus1& ff);
817 
819 class ZZ_pXModulus1 : public NTL::ZZ_pXModulus
820 {
821 public:
822  ZZ_pXModulus1(UNUSED long _m, const NTL::ZZ_pX& _f) : NTL::ZZ_pXModulus(_f) {}
823  const NTL::ZZ_pXModulus& upcast() const { return *this; }
824 };
825 
826 template <typename T>
827 std::ostream& operator<<(std::ostream& s, std::vector<T> v)
828 {
829  if (v.size() == 0)
830  return (s << "[]");
831 
832  s << '[';
833  for (long i = 0; i < (long)v.size() - 1; i++)
834  s << v[i] << ' ';
835  return (s << v[v.size() - 1] << ']');
836 }
837 
838 template <typename T>
839 std::istream& operator>>(std::istream& s, std::vector<T>& v)
840 {
841  NTL::Vec<T> vv; // read into an NTL vector, then convert
842  s >> vv;
843  convert(v, vv);
844  return s;
845 }
846 
847 template <typename T>
848 std::string vecToStr(const std::vector<T>& v)
849 {
850  std::stringstream ss;
851  ss << v;
852  return ss.str();
853 }
854 
855 template <typename T>
856 NTL::Vec<T> atoVec(const char* a)
857 {
858  NTL::Vec<T> v;
859  std::string s(a);
860  std::stringstream ss(s);
861  ss >> v;
862  return v;
863 }
864 
865 template <typename T>
866 std::vector<T> atovector(const char* a)
867 {
868  NTL::Vec<T> v1 = atoVec<T>(a);
869  std::vector<T> v2;
870  convert(v2, v1);
871  return v2;
872 }
873 
874 #ifndef NTL_PROVIDES_TRUNC_FFT
875 // Define truncated FFT routines if not provided by NTL
876 inline void TofftRep_trunc(NTL::fftRep& y,
877  const NTL::zz_pX& x,
878  long k,
879  UNUSED long len,
880  long lo,
881  long hi)
882 {
883  TofftRep(y, x, k, lo, hi);
884 }
885 
886 inline void TofftRep_trunc(NTL::fftRep& y,
887  const NTL::zz_pX& x,
888  long k,
889  long len)
890 {
891  TofftRep_trunc(y, x, k, len, 0, deg(x));
892 }
893 #endif
894 
895 // Generic routines for computing absolute values and distances
896 // on real and complex numbers
897 
898 template <typename T>
900 {
901  static_assert(std::is_same<T, double>::value ||
902  std::is_same<T, std::complex<double>>::value,
903  "Error: type T is not double or std::complex<double>.");
904 }
905 
906 template <typename T>
907 double Norm(const T& x)
908 {
909  AssertRealOrComplex<T>();
910  return std::abs(x);
911 }
912 
913 template <typename T, typename U>
914 double Distance(const T& x, const U& y)
915 {
916  AssertRealOrComplex<T>();
917  AssertRealOrComplex<U>();
918  return std::abs(x - y);
919 }
920 
921 // for vectors, we us the infty norm
922 template <typename T>
923 double Norm(const std::vector<T>& x)
924 {
925  long n = x.size();
926  double res = 0;
927  for (long i = 0; i < n; i++)
928  res = std::max(res, Norm(x[i]));
929  return res;
930 }
931 
932 // we require same-length vectors
933 template <typename T, typename U>
934 double Distance(const std::vector<T>& x, const std::vector<U>& y)
935 {
936  assertTrue(x.size() == y.size(), "Distance: mismatched vector sizes");
937  long n = x.size();
938  double res = 0;
939  for (long i = 0; i < n; i++)
940  res = std::max(res, Distance(x[i], y[i]));
941  return res;
942 }
943 
944 // General mechanisms for comparing approximate numbers
945 
946 // returns true iff |x-y| <= tolerance*max(|y|,floor)
947 
948 // the template mechanism will allow comparisons
949 // between scalars of real/complex types, or between vectors
950 // of real/complex types.
951 // For vectors, sizes must be equal and the infty norm is used
952 
953 template <typename T, typename U>
954 inline bool approx_equal(const T& x, const U& y, double tolerance, double floor)
955 {
956  return Distance(x, y) <= tolerance * std::max(Norm(y), floor);
957 }
958 
959 template <class T>
961 {
962  const T& val;
963  double tolerance;
964  double floor;
965 
966  ApproxClass(const T& val_, double tolerance_, double floor_) :
967  val(val_), tolerance(tolerance_), floor(floor_)
968  {}
969 };
970 
971 template <class T>
972 ApproxClass<T> Approx(const T& val, double tolerance = 0.01, double floor = 1.0)
973 {
974  return ApproxClass<T>(val, tolerance, floor);
975 }
976 
977 template <class T, class U>
978 bool operator==(const T& x, const ApproxClass<U>& y)
979 {
980  return approx_equal(x, y.val, y.tolerance, y.floor);
981 }
982 
983 template <class T, class U>
984 bool operator!=(const T& x, const ApproxClass<U>& y)
985 {
986  return !approx_equal(x, y.val, y.tolerance, y.floor);
987 }
988 
992 double NextPow2(double x);
993 
997 class OptLong
998 {
999  long data;
1000  bool defined;
1001 
1002 public:
1003  OptLong() : defined(false) {}
1004  OptLong(long _data) : data(_data), defined(true) {}
1005  // implict conversion from long
1006 
1007  bool isDefined() const { return defined; }
1008  operator long() const { return data; }
1009  // implict conversion to long
1010 };
1011 
1015 template <typename T, typename P, typename... Args>
1016 void make_lazy(const NTL::Lazy<T, P>& obj, Args&&... args)
1017 {
1018  typename NTL::Lazy<T, P>::Builder builder(obj);
1019  if (!builder())
1020  return;
1021  NTL::UniquePtr<T, P> ptr;
1022  ptr.make(std::forward<Args>(args)...);
1023  builder.move(ptr);
1024 }
1025 
1029 template <typename T, typename P, typename F, typename... Args>
1030 void make_lazy_with_fun(const NTL::Lazy<T, P>& obj, F f, Args&&... args)
1031 {
1032  typename NTL::Lazy<T, P>::Builder builder(obj);
1033  if (!builder())
1034  return;
1035  NTL::UniquePtr<T, P> ptr;
1036  ptr.make();
1037  f(*ptr, std::forward<Args>(args)...);
1038  builder.move(ptr);
1039 }
1040 
1041 // An array of inverse erfc values.
1042 // erfc_inverse[i] = x means 2^{-i} = erfc(x/sqrt(2))
1043 
1044 const double erfc_inverse[] = {0,
1045  0.6744897501960817432,
1046  1.1503493803760081782,
1047  1.5341205443525463117,
1048  1.8627318674216514554,
1049  2.1538746940614562129,
1050  2.4175590162365050618,
1051  2.6600674686174596585,
1052  2.8856349124267571473,
1053  3.0972690781987844623,
1054  3.2971933456919633418,
1055  3.4871041041144311068,
1056  3.6683292851213230192,
1057  3.8419306855019108708,
1058  4.0087725941685849622,
1059  4.1695693233491057549,
1060  4.3249190408260462571,
1061  4.4753284246542033544,
1062  4.6212310014992471565,
1063  4.7630010342678139569,
1064  4.9009642079631930118};
1065 
1066 #define ERFC_INVERSE_SIZE (long(sizeof(erfc_inverse) / sizeof(erfc_inverse[0])))
1067 
1068 } // namespace helib
1069 
1070 #endif // ifndef HELIB_NUMBTH_H
Represents the set of long int's plus a distinguished value that can be used to denote "undefined"....
Definition: NumbTh.h:998
OptLong()
Definition: NumbTh.h:1003
bool isDefined() const
Definition: NumbTh.h:1007
OptLong(long _data)
Definition: NumbTh.h:1004
Facility for "restoring" the NTL PRG state.
Definition: NumbTh.h:628
~RandomState()
Definition: NumbTh.h:649
void restore()
Restore the PRG state of NTL.
Definition: NumbTh.h:641
RandomState()
Definition: NumbTh.h:634
placeholder for pXModulus ...no optimizations
Definition: NumbTh.h:820
ZZ_pXModulus1(UNUSED long _m, const NTL::ZZ_pX &_f)
Definition: NumbTh.h:822
const NTL::ZZ_pXModulus & upcast() const
Definition: NumbTh.h:823
Auxiliary classes to facilitate faster reduction mod Phi_m(X) when the input has degree less than m.
Definition: NumbTh.h:798
NTL::zz_pX f
Definition: NumbTh.h:801
long n
Definition: NumbTh.h:802
NTL::zz_pXModulus fm
Definition: NumbTh.h:809
NTL::fftRep R0
Definition: NumbTh.h:807
NTL::fftRep R1
Definition: NumbTh.h:807
long k1
Definition: NumbTh.h:806
long k
Definition: NumbTh.h:806
const NTL::zz_pXModulus & upcast() const
Definition: NumbTh.h:813
zz_pXModulus1(long _m, const NTL::zz_pX &_f)
Definition: NumbTh.cpp:1738
bool specialLogic
Definition: NumbTh.h:804
long m
Definition: NumbTh.h:800
Definition: io.cpp:18
std::set< long > * automorphVals2
Definition: Ctxt.cpp:100
bool dryRun
A dry-run flag The dry-run option disables most operations, to save time. This lets us quickly go ove...
Definition: NumbTh.cpp:27
std::set< long > * automorphVals
A list of required automorphisms When non-nullptr, causes Ctxt::smartAutomorphism to just record the ...
Definition: Ctxt.cpp:99
Definition: apiAttributes.h:21
void balanced_MulMod(NTL::ZZX &out, const NTL::ZZX &f, long a, long q)
Definition: NumbTh.cpp:873
std::pair< long, long > rationalApprox(double x, long denomBound=0)
Definition: NumbTh.cpp:1598
void make_lazy_with_fun(const NTL::Lazy< T, P > &obj, F f, Args &&... args)
Definition: NumbTh.h:1030
void mul(const EncryptedArray &ea, PlaintextArray &pa, const PlaintextArray &other)
Definition: EncryptedArray.cpp:1612
void applyLinPoly(NTL::zz_pE &beta, const NTL::vec_zz_pE &C, const NTL::zz_pE &alpha, long p)
Apply a linearized polynomial with coefficient vector C.
Definition: NumbTh.cpp:1551
void seekPastChar(std::istream &str, int cc)
Advance the input stream beyond white spaces and a single instance of the char cc.
Definition: NumbTh.cpp:1069
NTL::Vec< T > atoVec(const char *a)
Definition: NumbTh.h:856
long polyEvalMod(const NTL::ZZX &poly, long x, long p)
Evaluates a modular integer polynomial, returns poly(x) mod p.
Definition: NumbTh.cpp:979
long is_in(long x, int *X, long sz)
Finds whether x is an element of the set X of size sz, Returns -1 it not and the location if true.
Definition: NumbTh.cpp:890
NTL::ZZX Cyclotomic(long N)
Compute cyclotomic polynomial.
Definition: NumbTh.cpp:531
double NextPow2(double x)
Compute next power of two in floating point NextPow2(x) returns 1 if x < 1, and otherwise returns 2^(...
Definition: NumbTh.cpp:1803
void setAutomorphVals(std::set< long > *aVals)
Definition: NumbTh.h:89
bool sameObject(const T1 *p1, const T2 *p2)
Testing if two vectors point to the same object.
Definition: NumbTh.h:769
std::vector< T > Vec_replicate(const T &a, long n)
Definition: NumbTh.h:465
void project_and_round(std::vector< long > &out, const std::vector< std::complex< double >> &in)
Definition: NumbTh.h:484
bool closeToOne(const NTL::xdouble &x, long p)
Definition: NumbTh.h:597
void killVec(std::vector< T > &vec)
NTL/std compatibility.
Definition: NumbTh.h:710
std::vector< T > vector_replicate(const T &a, long n)
Definition: NumbTh.h:455
long mcMod(long a, long b)
Routines for computing mathematically correct mod and div.
Definition: NumbTh.cpp:45
void pp_factorize(std::vector< long > &factors, long N)
Prime-power factorization.
Definition: NumbTh.cpp:203
void add(const EncryptedArray &ea, PlaintextArray &pa, const PlaintextArray &other)
Definition: EncryptedArray.cpp:1537
long argmin(std::vector< T > &v)
Definition: NumbTh.h:575
void make_lazy(const NTL::Lazy< T, P > &obj, Args &&... args)
Definition: NumbTh.h:1016
void recordAutomorphVal2(long k)
Definition: NumbTh.h:111
bool intVecCRT(NTL::vec_ZZ &vp, const NTL::ZZ &p, const zzvec &vq, long q)
Incremental integer CRT for vectors.
Definition: NumbTh.cpp:915
long mcDiv(long a, long b)
Definition: NumbTh.cpp:55
void buildLinPolyCoeffs(NTL::vec_zz_pE &C, const NTL::vec_zz_pE &L, long p, long r)
Combination of buildLinPolyMatrix and ppsolve.
Definition: NumbTh.cpp:1511
bool is2power(long m)
Definition: NumbTh.h:285
long findGenerators(std::vector< long > &gens, std::vector< long > &ords, long m, long p, const std::vector< long > &candidates=std::vector< long >())
Definition: NumbTh.cpp:342
void ppInvert(NTL::mat_zz_p &X, const NTL::mat_zz_p &A, long p, long r)
Compute the inverse mod p^r of an n x n matrix.
Definition: NumbTh.cpp:1455
void recordAutomorphVal(long k)
Definition: NumbTh.h:99
void buildLinPolyMatrix(NTL::mat_zz_pE &M, long p)
Definition: NumbTh.cpp:1096
std::istream & operator>>(std::istream &s, CtxtPart &p)
Definition: Ctxt.cpp:2762
long ord(long N, long p)
Compute the highest power of p that divides N.
Definition: NumbTh.cpp:697
void convert(long &x1, const NTL::GF2X &x2)
Definition: NumbTh.h:368
void factorize(std::vector< long > &factors, long N)
Factoring by trial division, only works for N<2^{60}, only the primes are recorded,...
Definition: NumbTh.cpp:155
void reverse(NTL::Vec< T > &v, long lo, long hi)
Reverse a vector in place.
Definition: NumbTh.h:662
void assertInRange(const T &elem, const T &min, const T &max, const std::string &message, bool right_inclusive=false)
Definition: assertions.h:183
bool approx_equal(const T &x, const U &y, double tolerance, double floor)
Definition: NumbTh.h:954
void setAutomorphVals2(std::set< long > *aVals)
Definition: NumbTh.h:101
void MulMod(NTL::ZZX &out, const NTL::ZZX &f, long a, long q, bool abs)
Definition: NumbTh.cpp:852
long phi_N(long N)
Compute Phi(N).
Definition: NumbTh.cpp:235
long multOrd(long p, long m)
Return multiplicative order of p modulo m, or 0 if GCD(p, m) != 1.
Definition: NumbTh.cpp:68
long computeProd(const NTL::Vec< long > &vec)
returns \prod_d vec[d]
Definition: NumbTh.cpp:92
void div(std::vector< NTL::ZZX > &x, const std::vector< NTL::ZZX > &a, long b)
Definition: NumbTh.cpp:1227
void AssertRealOrComplex()
Definition: NumbTh.h:899
long primroot(long N, long phiN)
Find a primitive root modulo N.
Definition: NumbTh.cpp:673
bool operator==(const PtxtArray &a, const PtxtArray &b)
Definition: EncryptedArray.h:2426
void vecRed(NTL::Vec< NTL::ZZ > &out, const NTL::Vec< NTL::ZZ > &in, long q, bool abs)
Definition: NumbTh.cpp:802
void FindPrimitiveRoot(NTL::zz_p &r, unsigned long e)
Find e-th root of unity modulo the current modulus.
Definition: NumbTh.cpp:492
void interpolateMod(NTL::ZZX &poly, const NTL::vec_long &x, const NTL::vec_long &y, long p, long e=1)
Interpolate polynomial such that poly(x[i] mod p)=y[i] (mod p^e) It is assumed that the points x[i] a...
Definition: NumbTh.cpp:1040
const long double PI
Definition: NumbTh.cpp:24
bool isDryRun()
Definition: NumbTh.h:87
double Distance(const EncryptedArray &ea, const PlaintextArray &pa, const PlaintextArray &other)
Definition: EncryptedArray.cpp:1943
std::string vecToStr(const std::vector< T > &v)
Definition: NumbTh.h:848
long argminmax(std::vector< T > &v)
Find the index of the (first) largest/smallest element.
Definition: NumbTh.h:547
void TofftRep_trunc(NTL::fftRep &y, const NTL::zz_pX &x, long k, UNUSED long len, long lo, long hi)
Definition: NumbTh.h:876
const double erfc_inverse[]
Definition: NumbTh.h:1044
double log2(const NTL::xdouble &x)
Base-2 logarithm.
Definition: NumbTh.h:237
double RandomReal()
returns a pseudo-random number in uniform in [0, 1)
Definition: NumbTh.cpp:707
void rotate(Ctxt &ctxt, long k)
Definition: EncryptedArray.h:1969
bool isSetAutomorphVals()
Definition: NumbTh.h:94
void assertTrue(const T &value, const std::string &message)
Definition: assertions.h:61
void ppsolve(NTL::vec_zz_pE &x, const NTL::mat_zz_pE &A, const NTL::vec_zz_pE &b, long p, long r)
Prime power solver.
Definition: NumbTh.cpp:1251
std::vector< T > atovector(const char *a)
Definition: NumbTh.h:866
std::ostream & operator<<(std::ostream &os, const ContextBuilder< SCHEME > &cb)
ostream operator for serializing the ContextBuilder object.
NTL::ZZX RandPoly(long n, const NTL::ZZ &p)
Definition: NumbTh.cpp:728
long mobius(long n)
Compute mobius function (naive method as n is small).
Definition: NumbTh.cpp:502
void resize(NTL::Vec< T > &v, long sz, const T &val)
Definition: NumbTh.h:743
long LONG
Definition: NumbTh.h:116
void ModComp(NTL::ZZX &res, const NTL::ZZX &g, const NTL::ZZX &h, const NTL::ZZX &f)
Modular composition of polynomials: res = g(h) mod f.
Definition: NumbTh.cpp:961
long divc(long a, long b)
returns ceiling(a/b); assumes a >=0, b>0, a+b <= MAX_LONG
Definition: NumbTh.h:792
double fsquare(double x)
Return the square of a number as a double.
Definition: NumbTh.h:149
std::complex< double > RandomComplex()
returns a pseudo-random number comomlex number z with |z| < 1
Definition: NumbTh.cpp:718
NTL::ZZX makeIrredPoly(long p, long d)
Return a degree-d irreducible polynomial mod p.
Definition: NumbTh.cpp:102
void phiN(long &phiN, std::vector< long > &facts, long N)
Compute Phi(N) and also factorize N.
Definition: NumbTh.cpp:228
void setLengthZero(std::vector< T > &vec)
Definition: NumbTh.h:723
long argmax(std::vector< T > &v)
Definition: NumbTh.h:569
long lsize(const std::vector< T > &v)
Size of STL vector as a long (rather than unsigned long)
Definition: NumbTh.h:701
void PolyRed(NTL::ZZX &out, const NTL::ZZX &in, long q, bool abs=false)
Reduce all the coefficients of a polynomial modulo q.
Definition: NumbTh.cpp:772
long balRem(long a, long q)
Definition: NumbTh.h:140
ApproxClass< T > Approx(const T &val, double tolerance=0.01, double floor=1.0)
Definition: NumbTh.h:972
long bitSetToLong(long bits, long bitSize)
Considers bits as a vector of bits and returns the value it represents when interpreted as a n-bit 2'...
Definition: NumbTh.cpp:32
void project(std::vector< double > &out, const std::vector< std::complex< double >> &in)
Definition: NumbTh.h:475
void rem(NTL::zz_pX &r, const NTL::zz_pX &a, const zz_pXModulus1 &ff)
Definition: NumbTh.cpp:1764
bool operator!=(const PtxtArray &a, const PtxtArray &b)
Definition: EncryptedArray.h:2432
bool setDryRun(bool toWhat=true)
Definition: NumbTh.h:82
double Norm(const EncryptedArray &ea, const PlaintextArray &pa)
Definition: EncryptedArray.cpp:1936
long CRTcoeff(long p, long q, bool symmetric=false)
Returns a CRT coefficient: x = (0 mod p, 1 mod q). If symmetric is set then x \in [-pq/2,...
Definition: NumbTh.h:510
bool isSetAutomorphVals2()
Definition: NumbTh.h:106
Definition: NumbTh.h:961
ApproxClass(const T &val_, double tolerance_, double floor_)
Definition: NumbTh.h:966
const T & val
Definition: NumbTh.h:962
double floor
Definition: NumbTh.h:964
double tolerance
Definition: NumbTh.h:963