Basic Polynomial Algebra Subprograms (BPAS)  v. 1.791
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 
46  static usfixn64 r;
47  static int k;
48  // static bool isPrimeField;
49  // static bool isSmallPrimeField;
50  // static bool isComplexField;
51 
53 
54  GeneralizedFermatPrimeField (mpz_class a);
55 
57 
59 
60  explicit GeneralizedFermatPrimeField (const Integer& c);
61 
62  explicit GeneralizedFermatPrimeField (const RationalNumber& c);
63 
64  explicit GeneralizedFermatPrimeField (const SmallPrimeField& c); //? NOT SURE
65 
66  explicit GeneralizedFermatPrimeField (const BigPrimeField& c);
67 
69 
71 
73 
75 
77 
78  template <class Ring>
80 
82 
84 
86 
88 
89  static void setPrime (mpz_class p,usfixn64 R, int K){
90  prime = p;
91  characteristic = p;
92  r = R;
93  k = K;
94  }
95 
96  mpz_class getCharacteristic() const override {
97  return characteristic;
98  }
99 
100  void setX (mpz_class a);
101 
102  mpz_class Prime() const;
103 
104  mpz_class number() const;
105 
107 
108  static mpz_class power(mpz_class xi, mpz_class yi) {
109  mpz_class res = 1; // Initialize result
110 
111  xi = xi % prime; // Update x if it is more than or
112  // equal to p
113 
114  while (yi > 0){
115  // If y is odd, multiply x with result
116  if ((yi % 2) == 1){
117  res = (res*xi) % prime;
118  yi = yi - 1;
119  }
120 
121  // y must be even now
122  yi = yi / 2; // y = y/2
123  xi = (xi*xi) % prime;
124  }
125  return res;
126  }
127 
128  GeneralizedFermatPrimeField findPrimitiveRootOfUnity(long int n) const {
129  return GeneralizedFermatPrimeField::findPrimitiveRootofUnity(n);
130  }
131 
132  static mpz_class findPrimitiveRootofUnity_plain(mpz_class n){
133  if ( ((prime - 1) % n != 0)){
134  cout << "ERROR: n does not divide prime - 1." << endl;
135  return -1;
136  }
137  bool flag = false;
138  mpz_class q = (prime - 1) / n;
139  mpz_class p1 = prime - 1;
140  mpz_class c;
141  int i = 0;
142  mpz_class test = q * n / 2;
143 
144 
145  srand (time(NULL));
146 
147  while(i < 20){
148  // std::cout << "i " << i << std::endl;
149  c = rand();
150  // cout << "c " << c << endl;
151  if (power(c,test) == p1) {
152  flag = true;
153  return power(c,q);
154  }
155  i++;
156 
157  }
158  if (!flag ){
159  cout << "No primitive root found!"<< endl;
160  return 0;
161  }
162  return 0;
163  // If no primitive root found
164  }
165 
166  // find a privimitive root of unity that w^(N/2k) = r;
167  static GeneralizedFermatPrimeField findPrimitiveRootofUnity(mpz_class n){
168  if(n<(2*k)){
169  throw std::invalid_argument( "findPrimitiveRootofUnity error: N is less than 2k");
170  }
171  mpz_class g = findPrimitiveRootofUnity_plain(n);
172  mpz_class n2k = n / (2 * k);
173  mpz_class a = power(g, n2k);
174  mpz_class b = a;
175  std::stringstream str;
176  str << r;
177  mpz_class r_mpz (str.str());
178  int j = 1;
179  while (b != r_mpz){
180  b = (a * b)%prime;
181  j++;
182  }
183  GeneralizedFermatPrimeField result(power(g,j));
184  return result;
185  }
186 
188 
189  GeneralizedFermatPrimeField& operator= (const mpz_class& c);
190 
192 
193  inline bool isZero() const {
194  for (int i = 0; i < k; i++) {
195  if (x[i] != 0) {
196  return 0;
197  }
198  }
199  return 1;
200  }
201 
202  inline void zero() {
203  memset(x, 0x00, (k) * sizeof(usfixn64));
204  }
205 
206  inline bool isOne() const {
207  for (int i = k - 1;i > 0; i --){
208  if (x[i]!=0){
209  return 0;
210  }
211  }
212 
213  if (x[0] == 1){
214  return 1;
215  }
216  else {return 0;}
217  }
218 
219  inline void one() {
220  for (int i = k - 1;i > 0; i --){
221  x[i] = 0;
222  }
223 
224  x[0] = 1;
225  }
226 
227  inline bool isNegativeOne() const {
228  for (int i = 0; i < (k - 1);i ++){
229  if (x[i] != 0){
230  return 0;
231  }
232  }
233  if (x[k - 1] != r){
234  return 0;
235  }
236  else {return 1;}
237  }
238 
239  inline void negativeOne() {
240  for (int i = 0; i < (k - 1); i ++){
241  x[i] = 0;
242  }
243  x[k - 1] = r;
244  }
245 
246  inline int isConstant() const {
247  return 1;
248  }
249 
250  inline bool operator== (const GeneralizedFermatPrimeField& c) const {
251  for (int i = 0; i < k; i++) {
252  if (x[i] != c.x[i]) {
253  return 0;
254  }
255  }
256 
257  return 1;
258  }
259 
260  inline bool operator== (const mpz_class& c) const {
262  for (int i = 0; i < k; i++) {
263  if (x[i] != b.x[i]) {
264  return 0;
265  }
266  }
267 
268  return 1;
269  }
270 
271  inline bool operator!= (const GeneralizedFermatPrimeField& c) const {
272  for (int i = 0; i < k; i++) {
273  if (x[i] != c.x[i]) {
274  return 1;
275  }
276  }
277  return 0;
278  }
279 
280  inline bool operator!= (const mpz_class& c) const {
282  for (int i = 0; i < k; i++) {
283  if (x[i] != b.x[i]) {
284  return 1;
285  }
286  }
287 
288  return 0;
289  }
290 
292  GeneralizedFermatPrimeField t (*this);
293  return (t += c);
294  }
295 
296  inline GeneralizedFermatPrimeField operator+ (const mpz_class& c) const {
297  GeneralizedFermatPrimeField t (*this);
299  return (t += b);
300  }
301 
302  inline GeneralizedFermatPrimeField& operator+= (const mpz_class& c) {
304  *this += b;
305  return *this;
306  }
307 
308  inline GeneralizedFermatPrimeField operator+ (int c) const {
309  GeneralizedFermatPrimeField t (*this);
311  return (t += b);
312  }
313 
314  inline GeneralizedFermatPrimeField& operator+= (int c) {
316  *this += b;
317  return *this;
318  }
319 
320  // computer zi = xi + yi for i in 0...k-1
321  // let zk = 0
322  // for i in 0...k-1, zi/r = qi*a + si
323  // zi+1 = zi+1 + qi
324  // if zk ==0 return
325  // if zk == 1 return (r,0,0...0)
327 
329  GeneralizedFermatPrimeField t (*this);
330  return (t -= c);
331  }
332 
333  inline GeneralizedFermatPrimeField operator- (const mpz_class& c) const {
334  GeneralizedFermatPrimeField t (*this);
336  return (t -= b);
337  }
338 
339  //TODO this and the next -= seems wrong
340  inline GeneralizedFermatPrimeField& operator-= (const mpz_class& c) {
342  *this -= b;
343  return *this;
344  }
345 
346  inline GeneralizedFermatPrimeField operator- (int c) const {
347  GeneralizedFermatPrimeField t (*this);
349  return (t -= b);
350  }
351 
352  inline GeneralizedFermatPrimeField& operator-= (int c) {
354  *this -= b;
355  return *this;
356  }
357 
358  // using similar algorithm as addition
360 
363  return (b - *this);
364  }
365 
366  // part of multiplication
367  void smallAdd2 (usfixn64 *xm, usfixn64* ym, short & c);
368 
369  void oneShiftRight (usfixn64 * xs);
370 
371  // x*y = s0 + s1*r + s2 * r^2
372  void mulLong_2 (usfixn64 x, usfixn64 y, usfixn64 &s0,usfixn64 &s1, usfixn64 &s2);
373 
374  // special one for prime3
375  void mulLong_3 (usfixn64 const &x, usfixn64 const &y, usfixn64 &s0,
376  usfixn64 &s1, usfixn64 &s2);
377 
378  void multiplication (usfixn64* __restrict__ xs, const usfixn64* __restrict__ ys,
379  usfixn64 permutationStride, usfixn64* lVector,
380  usfixn64 *hVector, usfixn64* cVector,
381  usfixn64* lVectorSub,
382  usfixn64 *hVectorSub, usfixn64* cVectorSub );
383 
384  void multiplication_step2 (usfixn64* __restrict__ xs, usfixn64 permutationStride,
385  usfixn64* __restrict__ lVector,
386  usfixn64 * __restrict__ hVector,
387  usfixn64* __restrict__ cVector);
388 
390  GeneralizedFermatPrimeField t (*this);
391  return (t *= c);
392  }
393 
394  inline GeneralizedFermatPrimeField operator* (const mpz_class& c) const {
395  GeneralizedFermatPrimeField t (*this);
397  return (t *= b);
398  }
399 
400  inline GeneralizedFermatPrimeField& operator*= (const mpz_class& c) {
402  *this *= b;
403  return *this;
404  }
405 
406  inline GeneralizedFermatPrimeField operator* (int c) const {
407  GeneralizedFermatPrimeField t (*this);
409  return (t *= b);
410  }
411 
412  inline GeneralizedFermatPrimeField& operator*= (int c) {
414  *this *= c;
415  return *this;
416  }
417 
418  // using GMP multiplication
420  mpz_class xi = number();
421  mpz_class yi = c.number();
422  *this = xi*yi;
423  return *this;
424  }
425 
426  // special multiplication for P3
427  //r = 9223372054034644992
428  // k = 8
430 
431  //Multiple by some power of r
432  //using shift only
433  GeneralizedFermatPrimeField MulPowR(int s);
434 
435 
436  void egcd (const mpz_class& x, const mpz_class& y, mpz_class *ao, mpz_class *bo, mpz_class *vo, mpz_class P);
437 
438  inline GeneralizedFermatPrimeField inverse2(){
439  mpz_class a, n, b, v;
441  a = t.number();
442  egcd (a, prime, &n, &b, &v, prime);
443  if (b < 0)
444  b += prime;
446  return R;
447  }
448 
449  inline GeneralizedFermatPrimeField operator^ (long long int c) const {
450  GeneralizedFermatPrimeField t (*this);
451  mpz_class b (std::to_string(c), 10);
452  return (t ^ b);
453  }
454 
455  inline GeneralizedFermatPrimeField operator^ (const mpz_class& exp) const {
457  mpz_class e(exp);
458 
459  if (isZero() || isOne() || e == 1)
460  t = *this;
461  else if (e == 2) {
462  t = *this * *this;
463  }
464  else if (e > 2) {
465  GeneralizedFermatPrimeField x (*this);
466  t.one();
467 
468  while (e != 0) {
469  if ((e % 2) == 1)
470  t = t * x;
471  x = x * x;
472  e >>= 1;
473  }
474  }
475  else if (e == 0) {
476  t.one();
477  }
478  else {
479  t = *this ^ (-e);
480  t=t.inverse();
481  }
482  return t;
483  }
484 
485  inline GeneralizedFermatPrimeField& operator^= (long long int c) {
486  *this = *this ^ c;
487  return *this;
488  }
489 
490  inline GeneralizedFermatPrimeField& operator^= (const mpz_class& c) {
491  *this = *this ^ c;
492  return *this;
493  }
494 
496  return ExpressionTree(new ExprTreeNode(this->number()));
497  }
498 
500  GeneralizedFermatPrimeField t (*this);
501  return (t /= c);
502  }
503 
504  inline GeneralizedFermatPrimeField operator/ (long int c) const {
505  GeneralizedFermatPrimeField t (*this);
507  return (t /= b);
508  }
509 
510  inline GeneralizedFermatPrimeField operator/ (const mpz_class& c) const {
511  GeneralizedFermatPrimeField t (*this);
513  return (t /= b);
514  }
515 
517  if (c.isZero()) {
518  std::cout << "BPAS: error, dividend is zero from GeneralizedFermatPrimeField."<< std::endl;
519  exit(1);
520  }
522  *this *= c;
523  return *this;
524  }
525 
526  inline GeneralizedFermatPrimeField& operator/= (long int c) {
528  *this /= b;
529  return *this;
530  }
531 
532  inline GeneralizedFermatPrimeField& operator/= (const mpz_class& c) {
534  *this /= b;
535  return *this;
536  }
537 
539  return 0;
540  }
541 
543  *this = 0;
544  return *this;
545  }
546 
548  std::cerr << "GeneralizedFermatPrimeField::gcd NOT YET IMPLEMENTED" << std::endl;
549  exit(1);
551  }
552 
553  /**
554  * Compute squarefree factorization of *this
555  */
557  std::vector<GeneralizedFermatPrimeField> ret;
558  ret.push_back(*this);
559  return ret;
560  }
561 
562  /**
563  * Get the euclidean size of *this.
564  */
565  inline Integer euclideanSize() const {
566  return Integer(1);
567  }
568 
569  /**
570  * Perform the eucldiean division of *this and b. Returns the
571  * remainder. If q is not NULL, then returns the quotient in q.
572  */
574 
575  /**
576  * Perform the extended euclidean division on *this and b.
577  * Returns the GCD. If s and t are not NULL, returns the bezout coefficients in them.
578  */
580 
581  /**
582  * Get the quotient of *this and b.
583  */
585 
586  /**
587  * Get the remainder of *this and b.
588  */
590 
591  // GMP inverse
593 
594 
595 };
596 
597 #endif
GeneralizedFermatPrimeField & operator^=(long long int c)
Exponentiation assignment.
Definition: GeneralizedFermatPrimeField.hpp:485
GeneralizedFermatPrimeField remainder(const GeneralizedFermatPrimeField &b) const
Get the remainder of *this and b.
A sparsely represented univariate polynomial over an arbitrary ring.
Definition: BigPrimeField.hpp:21
GeneralizedFermatPrimeField operator+(const GeneralizedFermatPrimeField &c) const
Addition.
Definition: GeneralizedFermatPrimeField.hpp:291
An arbitrary-precision complex rational number.
Definition: ComplexRationalNumber.hpp:23
ExpressionTree convertToExpressionTree() const
Convert this to an expression tree.
Definition: GeneralizedFermatPrimeField.hpp:495
GeneralizedFermatPrimeField operator-() const
Negation.
Definition: GeneralizedFermatPrimeField.hpp:361
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:547
void zero()
Make *this ring element zero.
Definition: GeneralizedFermatPrimeField.hpp:202
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:538
GeneralizedFermatPrimeField & operator%=(const GeneralizedFermatPrimeField &c)
Assign *this to be the remainder of *this and b.
Definition: GeneralizedFermatPrimeField.hpp:542
A prime field whose prime is 32 bits or less.
Definition: SmallPrimeField.hpp:450
A univariate polynomial with Integer coefficients using a dense representation.
Definition: uzpolynomial.h:14
GeneralizedFermatPrimeField operator^(long long int c) const
Exponentiation.
Definition: GeneralizedFermatPrimeField.hpp:449
Integer euclideanSize() const
Get the euclidean size of *this.
Definition: GeneralizedFermatPrimeField.hpp:565
bool operator!=(const GeneralizedFermatPrimeField &c) const
Inequality test,.
Definition: GeneralizedFermatPrimeField.hpp:271
bool isZero() const
Determine if *this ring element is zero, that is the additive identity.
Definition: GeneralizedFermatPrimeField.hpp:193
A univariate polynomial with RationalNumber coefficients represented densely.
Definition: urpolynomial.h:16
GeneralizedFermatPrimeField & operator=(const GeneralizedFermatPrimeField &c)
Copy assignment.
A prime field whose prime can be arbitrarily large.
Definition: BigPrimeField.hpp:27
mpz_class getCharacteristic() const override
The characteristic of this ring class.
Definition: GeneralizedFermatPrimeField.hpp:96
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:250
GeneralizedFermatPrimeField inverse() const
Get the inverse of *this.
GeneralizedFermatPrimeField operator*(const GeneralizedFermatPrimeField &c) const
Multiplication.
Definition: GeneralizedFermatPrimeField.hpp:389
GeneralizedFermatPrimeField & operator/=(const GeneralizedFermatPrimeField &c)
Exact division assignment.
Definition: GeneralizedFermatPrimeField.hpp:516
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
Factors< GeneralizedFermatPrimeField > squareFree() const
Compute squarefree factorization of *this.
Definition: GeneralizedFermatPrimeField.hpp:556
bool isOne() const
Determine if *this ring element is one, that is the multiplication identity.
Definition: GeneralizedFermatPrimeField.hpp:206
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:499
void one()
Make *this ring element one.
Definition: GeneralizedFermatPrimeField.hpp:219