Basic Polynomial Algebra Subprograms (BPAS)  v. 1.700
GeneralizedFermatPrimeField.hpp
1 
2 #ifndef _GENERALIZED_FERMAT_PRIMT_FIELD_H_
3 #define _GENERALIZED_FERMAT_PRIMT_FIELD_H_
4 
5 #include "BPASFiniteField.hpp"
6 #include <iostream>
7 
8 typedef unsigned long long int usfixn64;
9 
10 //ULMAX=2^64-1 //equivalent to -1 on 64bits machines
11 #define ULMAX 18446744073709551615ULL
12 #define SQRTR 3037000502
13 #define RC 9223372019674906624ULL
14 
15 //forward declarations
16 class Integer;
17 class RationalNumber;
19 class SmallPrimeField;
20 class BigPrimeField;
23 template <class Ring>
25 
26 using std::endl;
27 using std::cout;
28 
29 // field when the prime is a generalized fermat prime:
30 // r = (2^w +- 2^u)
31 // prime = r^k
32 /**
33  * A finite field whose prime should be a generalized fermat number.
34  * That is, for r = (2^w +/- 2^u), the prime is r^k, for some k.
35  */
36 class GeneralizedFermatPrimeField : public BPASFiniteField<GeneralizedFermatPrimeField> {
37 
38 private:
39  static mpz_class& prime;
40 
41 public:
42  usfixn64 *x;
43  // number = xk-1*r^k-1 + xk-2*r^k-2 + ... + x1*r + x0
44  static mpz_class characteristic;
45  static RingProperties properties;
46 
47  static usfixn64 r;
48  static int k;
49  // static bool isPrimeField;
50  // static bool isSmallPrimeField;
51  // static bool isComplexField;
52 
54 
55  GeneralizedFermatPrimeField (mpz_class a);
56 
58 
60 
61  explicit GeneralizedFermatPrimeField (const Integer& c);
62 
63  explicit GeneralizedFermatPrimeField (const RationalNumber& c);
64 
65  explicit GeneralizedFermatPrimeField (const SmallPrimeField& c); //? NOT SURE
66 
67  explicit GeneralizedFermatPrimeField (const BigPrimeField& c);
68 
70 
72 
74 
76 
78 
79  template <class Ring>
81 
83 
85 
87 
89 
90  static void setPrime (mpz_class p,usfixn64 R, int K){
91  prime = p;
92  // characteristic = p;
93  r = R;
94  k = K;
95  }
96 
97  void setX (mpz_class a);
98 
99  mpz_class Prime() const;
100 
101  mpz_class number() const;
102 
104 
105  static mpz_class power(mpz_class xi, mpz_class yi) {
106  mpz_class res = 1; // Initialize result
107 
108  xi = xi % prime; // Update x if it is more than or
109  // equal to p
110 
111  while (yi > 0){
112  // If y is odd, multiply x with result
113  if ((yi % 2) == 1){
114  res = (res*xi) % prime;
115  yi = yi - 1;
116  }
117 
118  // y must be even now
119  yi = yi / 2; // y = y/2
120  xi = (xi*xi) % prime;
121  }
122  return res;
123  }
124 
125  GeneralizedFermatPrimeField findPrimitiveRootOfUnity(long int n) const {
126  return GeneralizedFermatPrimeField::findPrimitiveRootofUnity(n);
127  }
128 
129  static mpz_class findPrimitiveRootofUnity_plain(mpz_class n){
130  if ( ((prime - 1) % n != 0)){
131  cout << "ERROR: n does not divide prime - 1." << endl;
132  return -1;
133  }
134  bool flag = false;
135  mpz_class q = (prime - 1) / n;
136  mpz_class p1 = prime - 1;
137  mpz_class c;
138  int i = 0;
139  mpz_class test = q * n / 2;
140 
141 
142  srand (time(NULL));
143 
144  while(i < 20){
145  // std::cout << "i " << i << std::endl;
146  c = rand();
147  // cout << "c " << c << endl;
148  if (power(c,test) == p1) {
149  flag = true;
150  return power(c,q);
151  }
152  i++;
153 
154  }
155  if (!flag ){
156  cout << "No primitive root found!"<< endl;
157  return 0;
158  }
159  return 0;
160  // If no primitive root found
161  }
162 
163  // find a privimitive root of unity that w^(N/2k) = r;
164  static GeneralizedFermatPrimeField findPrimitiveRootofUnity(mpz_class n){
165  if(n<(2*k)){
166  throw std::invalid_argument( "findPrimitiveRootofUnity error: N is less than 2k");
167  }
168  mpz_class g = findPrimitiveRootofUnity_plain(n);
169  mpz_class n2k = n / (2 * k);
170  mpz_class a = power(g, n2k);
171  mpz_class b = a;
172  std::stringstream str;
173  str << r;
174  mpz_class r_mpz (str.str());
175  int j = 1;
176  while (b != r_mpz){
177  b = (a * b)%prime;
178  j++;
179  }
180  GeneralizedFermatPrimeField result(power(g,j));
181  return result;
182  }
183 
185 
186  GeneralizedFermatPrimeField& operator= (const mpz_class& c);
187 
189 
190  inline bool isZero() const {
191  for (int i = 0; i < k; i++) {
192  if (x[i] != 0) {
193  return 0;
194  }
195  }
196  return 1;
197  }
198 
199  inline void zero() {
200  memset(x, 0x00, (k) * sizeof(usfixn64));
201  }
202 
203  inline bool isOne() const {
204  for (int i = k - 1;i > 0; i --){
205  if (x[i]!=0){
206  return 0;
207  }
208  }
209 
210  if (x[0] == 1){
211  return 1;
212  }
213  else {return 0;}
214  }
215 
216  inline void one() {
217  for (int i = k - 1;i > 0; i --){
218  x[i] = 0;
219  }
220 
221  x[0] = 1;
222  }
223 
224  inline bool isNegativeOne() const {
225  for (int i = 0; i < (k - 1);i ++){
226  if (x[i] != 0){
227  return 0;
228  }
229  }
230  if (x[k - 1] != r){
231  return 0;
232  }
233  else {return 1;}
234  }
235 
236  inline void negativeOne() {
237  for (int i = 0; i < (k - 1); i ++){
238  x[i] = 0;
239  }
240  x[k - 1] = r;
241  }
242 
243  inline int isConstant() const {
244  return 1;
245  }
246 
247  inline bool operator== (const GeneralizedFermatPrimeField& c) const {
248  for (int i = 0; i < k; i++) {
249  if (x[i] != c.x[i]) {
250  return 0;
251  }
252  }
253 
254  return 1;
255  }
256 
257  inline bool operator== (const mpz_class& c) const {
259  for (int i = 0; i < k; i++) {
260  if (x[i] != b.x[i]) {
261  return 0;
262  }
263  }
264 
265  return 1;
266  }
267 
268  inline bool operator!= (const GeneralizedFermatPrimeField& c) const {
269  for (int i = 0; i < k; i++) {
270  if (x[i] != c.x[i]) {
271  return 1;
272  }
273  }
274  return 0;
275  }
276 
277  inline bool operator!= (const mpz_class& c) const {
279  for (int i = 0; i < k; i++) {
280  if (x[i] != b.x[i]) {
281  return 1;
282  }
283  }
284 
285  return 0;
286  }
287 
289  GeneralizedFermatPrimeField t (*this);
290  return (t += c);
291  }
292 
293  inline GeneralizedFermatPrimeField operator+ (const mpz_class& c) const {
294  GeneralizedFermatPrimeField t (*this);
296  return (t += b);
297  }
298 
299  inline GeneralizedFermatPrimeField& operator+= (const mpz_class& c) {
301  *this += b;
302  return *this;
303  }
304 
305  inline GeneralizedFermatPrimeField operator+ (int c) const {
306  GeneralizedFermatPrimeField t (*this);
308  return (t += b);
309  }
310 
311  inline GeneralizedFermatPrimeField& operator+= (int c) {
313  *this += b;
314  return *this;
315  }
316 
317  // computer zi = xi + yi for i in 0...k-1
318  // let zk = 0
319  // for i in 0...k-1, zi/r = qi*a + si
320  // zi+1 = zi+1 + qi
321  // if zk ==0 return
322  // if zk == 1 return (r,0,0...0)
324 
326  GeneralizedFermatPrimeField t (*this);
327  return (t -= c);
328  }
329 
330  inline GeneralizedFermatPrimeField operator- (const mpz_class& c) const {
331  GeneralizedFermatPrimeField t (*this);
333  return (t -= b);
334  }
335 
336  //TODO this and the next -= seems wrong
337  inline GeneralizedFermatPrimeField& operator-= (const mpz_class& c) {
339  *this -= b;
340  return *this;
341  }
342 
343  inline GeneralizedFermatPrimeField operator- (int c) const {
344  GeneralizedFermatPrimeField t (*this);
346  return (t -= b);
347  }
348 
349  inline GeneralizedFermatPrimeField& operator-= (int c) {
351  *this -= b;
352  return *this;
353  }
354 
355  // using similar algorithm as addition
357 
360  return (b - *this);
361  }
362 
363  // part of multiplication
364  void smallAdd2 (usfixn64 *xm, usfixn64* ym, short & c);
365 
366  void oneShiftRight (usfixn64 * xs);
367 
368  // x*y = s0 + s1*r + s2 * r^2
369  void mulLong_2 (usfixn64 x, usfixn64 y, usfixn64 &s0,usfixn64 &s1, usfixn64 &s2);
370 
371  // special one for prime3
372  void mulLong_3 (usfixn64 const &x, usfixn64 const &y, usfixn64 &s0,
373  usfixn64 &s1, usfixn64 &s2);
374 
375  void multiplication (usfixn64* __restrict__ xs, const usfixn64* __restrict__ ys,
376  usfixn64 permutationStride, usfixn64* lVector,
377  usfixn64 *hVector, usfixn64* cVector,
378  usfixn64* lVectorSub,
379  usfixn64 *hVectorSub, usfixn64* cVectorSub );
380 
381  void multiplication_step2 (usfixn64* __restrict__ xs, usfixn64 permutationStride,
382  usfixn64* __restrict__ lVector,
383  usfixn64 * __restrict__ hVector,
384  usfixn64* __restrict__ cVector);
385 
387  GeneralizedFermatPrimeField t (*this);
388  return (t *= c);
389  }
390 
391  inline GeneralizedFermatPrimeField operator* (const mpz_class& c) const {
392  GeneralizedFermatPrimeField t (*this);
394  return (t *= b);
395  }
396 
397  inline GeneralizedFermatPrimeField& operator*= (const mpz_class& c) {
399  *this *= b;
400  return *this;
401  }
402 
403  inline GeneralizedFermatPrimeField operator* (int c) const {
404  GeneralizedFermatPrimeField t (*this);
406  return (t *= b);
407  }
408 
409  inline GeneralizedFermatPrimeField& operator*= (int c) {
411  *this *= c;
412  return *this;
413  }
414 
415  // using GMP multiplication
417  mpz_class xi = number();
418  mpz_class yi = c.number();
419  *this = xi*yi;
420  return *this;
421  }
422 
423  // special multiplication for P3
424  //r = 9223372054034644992
425  // k = 8
427 
428  //Multiple by some power of r
429  //using shift only
430  GeneralizedFermatPrimeField MulPowR(int s);
431 
432 
433  void egcd (const mpz_class& x, const mpz_class& y, mpz_class *ao, mpz_class *bo, mpz_class *vo, mpz_class P);
434 
435  inline GeneralizedFermatPrimeField inverse2(){
436  mpz_class a, n, b, v;
438  a = t.number();
439  egcd (a, prime, &n, &b, &v, prime);
440  if (b < 0)
441  b += prime;
443  return R;
444  }
445 
446  inline GeneralizedFermatPrimeField operator^ (long long int c) const {
447  GeneralizedFermatPrimeField t (*this);
448  mpz_class b (std::to_string(c), 10);
449  return (t ^ b);
450  }
451 
452  inline GeneralizedFermatPrimeField operator^ (const mpz_class& exp) const {
454  mpz_class e(exp);
455 
456  if (isZero() || isOne() || e == 1)
457  t = *this;
458  else if (e == 2) {
459  t = *this * *this;
460  }
461  else if (e > 2) {
462  GeneralizedFermatPrimeField x (*this);
463  t.one();
464 
465  while (e != 0) {
466  if ((e % 2) == 1)
467  t = t * x;
468  x = x * x;
469  e >>= 1;
470  }
471  }
472  else if (e == 0) {
473  t.one();
474  }
475  else {
476  t = *this ^ (-e);
477  t=t.inverse();
478  }
479  return t;
480  }
481 
482  inline GeneralizedFermatPrimeField& operator^= (long long int c) {
483  *this = *this ^ c;
484  return *this;
485  }
486 
487  inline GeneralizedFermatPrimeField& operator^= (const mpz_class& c) {
488  *this = *this ^ c;
489  return *this;
490  }
491 
493  return ExpressionTree(new ExprTreeNode(this->number()));
494  }
495 
497  GeneralizedFermatPrimeField t (*this);
498  return (t /= c);
499  }
500 
501  inline GeneralizedFermatPrimeField operator/ (long int c) const {
502  GeneralizedFermatPrimeField t (*this);
504  return (t /= b);
505  }
506 
507  inline GeneralizedFermatPrimeField operator/ (const mpz_class& c) const {
508  GeneralizedFermatPrimeField t (*this);
510  return (t /= b);
511  }
512 
514  if (c.isZero()) {
515  std::cout << "BPAS: error, dividend is zero from GeneralizedFermatPrimeField."<< std::endl;
516  exit(1);
517  }
519  *this *= c;
520  return *this;
521  }
522 
523  inline GeneralizedFermatPrimeField& operator/= (long int c) {
525  *this /= b;
526  return *this;
527  }
528 
529  inline GeneralizedFermatPrimeField& operator/= (const mpz_class& c) {
531  *this /= b;
532  return *this;
533  }
534 
536  return 0;
537  }
538 
540  *this = 0;
541  return *this;
542  }
543 
545  std::cerr << "GeneralizedFermatPrimeField::gcd NOT YET IMPLEMENTED" << std::endl;
546  exit(1);
548  }
549 
550  /**
551  * Compute squarefree factorization of *this
552  */
554  std::vector<GeneralizedFermatPrimeField> ret;
555  ret.push_back(*this);
556  return ret;
557  }
558 
559  /**
560  * Get the euclidean size of *this.
561  */
563  return (*this).number();
564  }
565 
566  /**
567  * Perform the eucldiean division of *this and b. Returns the
568  * remainder. If q is not NULL, then returns the quotient in q.
569  */
571 
572  /**
573  * Perform the extended euclidean division on *this and b.
574  * Returns the GCD. If s and t are not NULL, returns the bezout coefficients in them.
575  */
577 
578  /**
579  * Get the quotient of *this and b.
580  */
582 
583  /**
584  * Get the remainder of *this and b.
585  */
587 
588  // GMP inverse
590 
591 
592 };
593 
594 #endif
GeneralizedFermatPrimeField & operator^=(long long int c)
Exponentiation assignment.
Definition: GeneralizedFermatPrimeField.hpp:482
GeneralizedFermatPrimeField remainder(const GeneralizedFermatPrimeField &b) const
Get the remainder of *this and b.
A univariate polynomial over an arbitrary BPASRing represented sparsely.
Definition: BigPrimeField.hpp:21
GeneralizedFermatPrimeField operator+(const GeneralizedFermatPrimeField &c) const
Addition.
Definition: GeneralizedFermatPrimeField.hpp:288
An arbitrary-precision complex rational number.
Definition: ComplexRationalNumber.hpp:23
ExpressionTree convertToExpressionTree() const
Convert this to an expression tree.
Definition: GeneralizedFermatPrimeField.hpp:492
GeneralizedFermatPrimeField operator-() const
Negation.
Definition: GeneralizedFermatPrimeField.hpp:358
An ExpressionTree encompasses various forms of data that can be expressed generically as a binary tre...
Definition: ExpressionTree.hpp:17
GeneralizedFermatPrimeField gcd(const GeneralizedFermatPrimeField &a) const
Get GCD of *this and other.
Definition: GeneralizedFermatPrimeField.hpp:544
void zero()
Make *this ring element zero.
Definition: GeneralizedFermatPrimeField.hpp:199
A finite field whose prime should be a generalized fermat number.
Definition: GeneralizedFermatPrimeField.hpp:36
GeneralizedFermatPrimeField quotient(const GeneralizedFermatPrimeField &b) const
Get the quotient of *this and b.
GeneralizedFermatPrimeField operator%(const GeneralizedFermatPrimeField &c) const
Get the remainder of *this and b;.
Definition: GeneralizedFermatPrimeField.hpp:535
GeneralizedFermatPrimeField & operator%=(const GeneralizedFermatPrimeField &c)
Assign *this to be the remainder of *this and b.
Definition: GeneralizedFermatPrimeField.hpp:539
A prime field whose prime is 32 bits or less.
Definition: SmallPrimeField.hpp:449
A univariate polynomial with Integer coefficients using a dense representation.
Definition: uzpolynomial.h:13
GeneralizedFermatPrimeField operator^(long long int c) const
Exponentiation.
Definition: GeneralizedFermatPrimeField.hpp:446
bool operator!=(const GeneralizedFermatPrimeField &c) const
Inequality test,.
Definition: GeneralizedFermatPrimeField.hpp:268
bool isZero() const
Determine if *this ring element is zero, that is the additive identity.
Definition: GeneralizedFermatPrimeField.hpp:190
A univariate polynomial with RationalNumber coefficients represented densely.
Definition: urpolynomial.h:15
GeneralizedFermatPrimeField & operator=(const GeneralizedFermatPrimeField &c)
Copy assignment.
A prime field whose prime can be arbitrarily large.
Definition: BigPrimeField.hpp:27
A simple data structure for encapsulating a collection of Factor elements.
Definition: Factors.hpp:95
An arbitrary-precision Integer.
Definition: Integer.hpp:22
GeneralizedFermatPrimeField extendedEuclidean(const GeneralizedFermatPrimeField &b, GeneralizedFermatPrimeField *s=NULL, GeneralizedFermatPrimeField *t=NULL) const
Perform the extended euclidean division on *this and b.
bool operator==(const GeneralizedFermatPrimeField &c) const
Equality test,.
Definition: GeneralizedFermatPrimeField.hpp:247
GeneralizedFermatPrimeField inverse() const
Get the inverse of *this.
GeneralizedFermatPrimeField operator*(const GeneralizedFermatPrimeField &c) const
Multiplication.
Definition: GeneralizedFermatPrimeField.hpp:386
GeneralizedFermatPrimeField & operator/=(const GeneralizedFermatPrimeField &c)
Exact division assignment.
Definition: GeneralizedFermatPrimeField.hpp:513
GeneralizedFermatPrimeField unitCanonical(GeneralizedFermatPrimeField *u=NULL, GeneralizedFermatPrimeField *v=NULL) const
Obtain the unit normal (a.k.a canonical associate) of an element.
An arbitrary-precision rational number.
Definition: RationalNumber.hpp:24
virtual mpz_class characteristic()
The characteristic of this ring class.
Definition: BPASRing.hpp:88
Factors< GeneralizedFermatPrimeField > squareFree() const
Compute squarefree factorization of *this.
Definition: GeneralizedFermatPrimeField.hpp:553
bool isOne() const
Determine if *this ring element is one, that is the multiplication identity.
Definition: GeneralizedFermatPrimeField.hpp:203
GeneralizedFermatPrimeField euclideanSize() const
Get the euclidean size of *this.
Definition: GeneralizedFermatPrimeField.hpp:562
GeneralizedFermatPrimeField euclideanDivision(const GeneralizedFermatPrimeField &b, GeneralizedFermatPrimeField *q=NULL) const
Perform the eucldiean division of *this and b.
ExprTreeNode is a single node in the bianry tree of an ExpressionTree.
Definition: ExprTreeNode.hpp:76
An abstract class defining the interface of a prime field.
Definition: BPASFiniteField.hpp:12
GeneralizedFermatPrimeField operator/(const GeneralizedFermatPrimeField &c) const
Exact division.
Definition: GeneralizedFermatPrimeField.hpp:496
void one()
Make *this ring element one.
Definition: GeneralizedFermatPrimeField.hpp:216