1/*==============================================================================
2|
3| NAME
4|
5| ppPolynomial.hpp
6|
7| DESCRIPTION
8|
9| Header file for all the polynomial classes.
10|
11| User manual and technical documentation are described in detail in my web page at
12| http://seanerikoconnor.freeservers.com/Mathematics/AbstractAlgebra/PrimitivePolynomials/overview.html
13|
14| LEGAL
15|
16| Primpoly Version 16.3 - A Program for Computing Primitive Polynomials.
17| Copyright (C) 1999-2024 by Sean Erik O'Connor. All Rights Reserved.
18|
19| This program is free software: you can redistribute it and/or modify
20| it under the terms of the GNU General Public License as published by
21| the Free Software Foundation, either version 3 of the License, or
22| (at your option) any later version.
23|
24| This program is distributed in the hope that it will be useful,
25| but WITHOUT ANY WARRANTY; without even the implied warranty of
26| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27| GNU General Public License for more details.
28|
29| You should have received a copy of the GNU General Public License
30| along with this program. If not, see http://www.gnu.org/licenses/.
31|
32| The author's address is seanerikoconnor!AT!gmail!DOT!com
33| with !DOT! replaced by . and the !AT! replaced by @
34|
35==============================================================================*/
36
37// Wrap this header file to prevent duplication if it is included
38// accidentally more than once.
39#ifndef __POLYNOMIAL_H__
40#define __POLYNOMIAL_H__
41
42/*=============================================================================
43|
44| NAME
45|
46| PolynomialError
47| PolynomialRangeError
48|
49| DESCRIPTION
50|
51| Exception classes for classes Polynomial and PolyMod
52| derived from the STL exception class runtime_error.
53|
54+============================================================================*/
55
56// General purpose exception for a polynomial.
57class PolynomialError : public runtime_error
58{
59 public:
60 // Throw with error message, file name and line number.
61 PolynomialError( const string & description, const string & file, const int & line )
62 : runtime_error( description + " in file " + file + " at line " + to_string(line) )
63 {
64 } ;
65
66 // Throw with an error message.
67 PolynomialError( const string & description )
68 : runtime_error( description )
69 {
70 } ;
71
72 // Throw with default error message.
73 PolynomialError()
74 : runtime_error( "Polynomial error: " )
75 {
76 } ;
77
78} ; // end class PolynomialError
79
80// Typically thrown when we parse a bad string which is not a proper polynomial.
81class PolynomialRangeError : public PolynomialError
82{
83 public:
84 // Throw with error message, file name and line number.
85 PolynomialRangeError( const string & description, const string & file, const int & line )
86 : PolynomialError( description + " in file " + file + " at line " + to_string(line) )
87 {
88 } ;
89
90 // Throw with an error message.
91 PolynomialRangeError( const string & description )
92 : PolynomialError( description )
93 {
94 } ;
95
96 // Throw with default error message.
97 PolynomialRangeError()
98 : PolynomialError( "Polynomial range error: " )
99 {
100 } ;
101
102} ; // end class PolynomialRangeError
103
104
105/*=============================================================================
106|
107| NAME
108|
109| Polynomial
110|
111| DESCRIPTION
112|
113| Represents the monic polynomial f( x ) of degree n, with
114| coefficients in GF( p ). Precisely,
115|
116| n n-1
117| f( x ) = x + a x + ... a x + a 0 <= a < p
118| n-1 1 0 i
119|
120| The constant polynomial is of degree 0.
121|
122| We support these basic operations:
123|
124| Polynomial f ; Construct f(x) = 0 mod 2.
125| <destructor>
126| Polynomial f( f2 ) ; Copy, f(x) = f2(x)
127| Polynomial f = f2 ; Overwrite, f(x) = f2(x)
128| Polynomial f( "x^2+1, 3" ) ; Polynomial from string.
129| String s = f ; Poly to string.
130| stream << p Read the poly.
131| p >> stream Print the poly.
132| p1 == p2, p1 != p2 Test for equality.
133| f[ i ] = coeff Set poly coefficient.
134| f.deg() Return the degree of f(x).
135| f.modulus() Return the modulus p of f(x).
136| int coeff = f[ i ] Get poly coefficient.
137| f(x) + g(x) Add poly mod p.
138| f(x) Evaluate f(x) for integer x
139| f.hasLinearFactor() Check if f(x) has any linear factors.
140| f.isInteger() Is f(x) = constant?
141| f.firstTrialPoly() Set f(x) = x^n - 1
142| f.nextTrialPoly() Set f(x) = next poly in sequence.
143|
144| Exceptions: throw PolynomialError or one of its subclasses such as
145| PolynomialRangeError.
146|
147| NOTES
148|
149| The member functions and friends are documented in ppPolynomial.cpp
150|
151+============================================================================*/
152
153class Polynomial
154{
155 public:
156 // Default constructor which sets f(x) = 0 modulo 2.
157 Polynomial() ;
158
159 // Constructor for a polynomial from a vector of integers.
160 explicit Polynomial( const vector<ppuint> ) ;
161
162 // Destructor.
163 virtual ~Polynomial() ;
164
165 // Copy constructor.
166 Polynomial( const Polynomial & g ) ;
167
168 // Assignment.
169 virtual Polynomial & operator=( const Polynomial & g ) ;
170
171 // String to polynomial assignment.
172 virtual Polynomial & operator=( string s ) ;
173
174 // Construct from string:
175 // Polynomial p( "x^2 + 2 x + 1, 3" ) ;
176 // If modulus isn't specified, use the one in specified in the
177 // polynomial string.
178 Polynomial( string s, ppuint p = 0 ) ;
179
180 // Operator casting to string type.
181 operator string() const ;
182
183 // Equality tests.
184 friend bool operator==( const Polynomial & p1, const Polynomial & p2 ) ;
185 friend bool operator!=( const Polynomial & p1, const Polynomial & p2 ) ;
186
187 // cout << p and cin >> p
188 friend ostream & operator<<( ostream & out, const Polynomial & p ) ;
189 friend istream & operator>>( istream & in, Polynomial & p ) ;
190
191 // Bounds checked indexing operator which allows an lvalue:
192 // p[ i ] = coeff ;
193 ppuint & operator[]( int i ) ;
194
195 // Bounds checked indexing operator for read only access:
196 // coeff = p[ i ] ;
197 const ppuint operator[]( int i ) const ;
198
199 // Return the degree n of f(x).
200 int deg() const ;
201
202 // Return the modulus p of f(x).
203 ppuint modulus() const ;
204
205 // Set the modulus p of f(x).
206 void setModulus( const ppuint p ) ;
207
208 // Addition modulo p: f(x) + g(x) mod p
209 friend const Polynomial operator+( const Polynomial & f, const Polynomial & g ) ;
210
211 // Addition.
212 Polynomial & operator+=( const Polynomial & g ) ;
213
214 // Scalar multiple.
215 friend const Polynomial
216 operator*( const Polynomial & f, const ppuint k ) ;
217
218 Polynomial & operator*=( const ppuint k ) ;
219
220 // Evaluation: f( x ) mod p
221 ppuint operator()( int x ) ;
222
223 // Does f(x) have any linear factor?
224 bool hasLinearFactor() ;
225
226 // Is f(x) an integer?
227 bool isInteger() const ;
228
229 // Only to show how we override a virtual function in C++. We actually don't need to define this function here in the base class.
230 virtual void initialTrialPoly( const ppuint n, const ppuint p )
231 { throw PolynomialError( "Trying to call initialTrialPoly() from Polynomial class instead of its child class TrialPolynomial", __FILE__, __LINE__ ) ;
232} ;
233
234 // Private data accessible by member functions only, and
235 // derived classes for convenience.
236 protected:
237 vector<ppuint> f_ ; // Polynomial coefficients:
238 // f_[0] = const coeff ... f_[n] = nth degree coeff.
239 // then f_.size() = n+1
240 int n_ ; // Degree of the polynomial.
241 ppuint p_ ; // Coefficients are in GF( p ).
242 ModP<ppuint,ppsint> mod ; // modulo p functionoid.
243} ;
244
245/*=============================================================================
246|
247| NAME
248|
249| TrialPolynomial
250|
251| DESCRIPTION
252|
253| Trial polynomial used in primitivity testing. Just a Polynomial with
254| a couple of functions to initialize and iterate over a sequence of
255| polynomials.
256|
257| NOTES
258|
259+============================================================================*/
260
261// final means a derived class won't be able to override any of the virtual
262// functions.
263class TrialPolynomial final : public Polynomial
264{
265 using Polynomial::Polynomial ; // Inherit all the base class constructors.
266
267 public:
268 // First trial polynomial. Set
269 // n
270 // f( x ) = x - 1
271 // override makes the compiler check the args AND the return type also
272 // to make sure there's an exact match to the base class function.
273 virtual void initialTrialPoly( const ppuint n, const ppuint p ) override ;
274
275 // Update f( x ) := next polynomial in sequence.
276 void nextTrialPoly() ;
277} ;
278
279/*=============================================================================
280|
281| NAME
282|
283| PolyMod
284|
285| DESCRIPTION
286|
287| Represents the monic polynomial g( x ) of degree m with coefficients in GF( p ),
288|
289| m m-1
290| g( x ) = x + a x + ... + a 0 <= a < p
291| m-1 0 i
292|
293| modulo f( x ) for monic polynomial f( x ) of degree n over GF( p ),
294|
295| n n-1
296| f( x ) = x + a x + ... + a 0 <= a < p
297| n-1 0 i
298|
299| We support these basic operations:
300|
301| PolyMod p() ; Set g(x)=0 and f(x) = 0 mod 2
302| Destructor.
303| PolyMod p( g, f ) Constructor from polynomials g(x) and f(x)
304| PolyMod p( p2 ) Copy p(x) = p2(x).
305| PolyMod p = p2 Assign p(x) = p2(x).
306| p.timesX() ; p(x) := x p( x ) (mod f( x ), p)
307| 2
308| p.square() ; p(x) := p( x ) (mod f( x ), p)
309| p *= p2 Do p(x) = p(x) * p2(x) (mod f( x ), p)
310| p1 * p2 Do p1(x) * p2(x) (mod f( x ), p)
311| m
312| p.power( m ) p(x) = x (mod f(x), p)
313|
314| Exceptions: throw PolynomialError or one of its subclasses such as
315| PolynomialRangeError.
316|
317| NOTES
318|
319| The member functions and friends are documented in ppPolynomial.hpp
320|
321+============================================================================*/
322
323// Friends of PolyMod
324ppuint autoConvolve( const Polynomial & t, const int k, const int lower, const int upper ) ;
325
326ppuint coeffOfSquare( const Polynomial & g, const int k, const int n ) ;
327
328ppuint coeffOfProduct( const Polynomial & s, const Polynomial & t, const int k, const int n ) ;
329
330ppuint convolve( const Polynomial & s, const Polynomial & t, const int k, const int lower, const int upper ) ;
331
332class PolyMod
333{
334 public:
335 // Set g( x ) = 0 modulo f(x) = 0 and p = 2
336 PolyMod() ;
337
338 // Destructor.
339 virtual ~PolyMod() ;
340
341 // Construct from polynomials g(x) and f(x).
342 PolyMod( const Polynomial & g, const Polynomial & f ) ;
343
344 // Construct from string g and polynomial f(x).
345 PolyMod( const string & g, const Polynomial & f ) ;
346
347 // Operator casting g(x) to string type.
348 operator string() const ;
349
350 // cout << p prints g(x) to output stream
351 friend ostream & operator<<( ostream & out, const PolyMod & p ) ;
352
353 // Copy g( x ) = g2( x ).
354 PolyMod( const PolyMod & g2 ) ;
355
356 // Assign g( x ) = g2( x )
357 virtual PolyMod & operator=( const PolyMod & g2 ) ;
358
359 // Bounds checked indexing operator for read only access:
360 // coeff = p[ i ] ;
361 const ppuint operator[]( int i ) const ;
362
363 // Multiply by x: g(x) := g(x) x (mod f( x ), p)
364 void timesX() ;
365
366 // Squaring: 2
367 // g(x) := g(x) (mod f( x ), p)
368 void square() ;
369
370 // Multiplication: g(x) := g(x) g2(x) (mod f( x ), p)
371 PolyMod & operator*=( const PolyMod & g2 ) ;
372
373 // Multiplication: g(x) := s(x) t(x) (mod f( x ), p)
374 friend const PolyMod operator*( const PolyMod & s, const PolyMod & t ) ;
375
376 // Special exponentiation: g(x) ^ m (mod f(x), p)
377 // for g(x) = x only for now!
378 friend const PolyMod power( const PolyMod & g, const BigInt & m ) ;
379
380 bool isInteger() const ;
381
382 //-----------------< Helper functions >-------------------------------
383 const Polynomial getf() const ;
384
385 const ppuint getModulus() const ;
386
387
388 private:
389 // Polynomial g(x).
390 Polynomial g_ ;
391
392 // Modulus polynomial f(x) and modulus p.
393 Polynomial f_ ;
394
395 // Two dimensional precomputed power table.
396 //
397 // Precompute the n-1 polynomials
398 //
399 // n 2n-2
400 // x ... x (mod f(x), p)
401 //
402 // n+i
403 // powerTable_[ i ] = x (mod f(x), p)
404 //
405 vector<Polynomial> powerTable_ ;
406
407 ModP<ppuint,ppsint> mod ; // modulo p functionoid.
408
409 // Helper functions. Note the friend functions are really public due to C++ rules.
410 protected:
411 // Offset into powerTable.
412 int inline offset( const int i ) const { return i - f_.deg() ; }
413
414 // Power table of the polynomial.
415 void constructPowerTable() ;
416
417 // Reduce g( x ) mod f( x ) and p
418 void modf() ;
419
420 // Autoconvolution product.
421 friend ppuint autoConvolve( const Polynomial & t, const int k, const int lower, const int upper ) ;
422
423 // Convolution product.
424 friend ppuint convolve( const Polynomial & s, const Polynomial & t,
425 const int k, const int lower, const int upper ) ;
426
427 // 2
428 // kth coeff of g (x) for degree n.
429 friend ppuint coeffOfSquare( const Polynomial & g, const int k, const int n ) ;
430
431 // Coeff of s(x) t(x) for degree n.
432 friend ppuint coeffOfProduct( const Polynomial & s, const Polynomial & t, const int k, const int n ) ;
433} ;
434
435
436
437/*=============================================================================
438|
439| NAME
440|
441| PolyOrder
442|
443| DESCRIPTION
444|
445| Order tests on the monic polynomial f( x ) of degree n,
446| with coefficients in GF( p ).
447|
448| n n-1
449| f( x ) = x + a x + ... + a 0 <= a < p
450| n-1 0 i
451|
452| Exceptions: throw PolynomialError or one of its subclasses such as
453| PolynomialRangeError.
454|
455| NOTES
456|
457| The member functions and friends are documented in ppPolynomial.hpp
458|
459+============================================================================*/
460
461class PolyOrder
462{
463 public:
464 // Do tests on the nth degree polynomial f(x) modulo p.
465 explicit PolyOrder( const Polynomial & f ) ;
466
467 // n
468 // p - 1
469 // Compute r = -------- and factor r into the product of primes
470 // p - 1
471 void factorR() ;
472
473 void computeMaxNumPoly() ;
474
475 void computeNumPrimPoly() ;
476
477 void resetPolynomial( const Polynomial &f ) ;
478
479 // m r
480 // Check that x (mod f(x), p) is not an integer for m = ---
481 // p
482 // i
483 // but skip this test if p | (p-1).
484 // i
485 bool orderM() ;
486
487 // r
488 // Check if x (mod f(x), p) = a, for integer a.
489 // If a is not an integer, return 0.
490 ppuint orderR() ;
491
492 // k n
493 // Check if x = 1 (mod f(x), p) only for k = p - 1
494 // Note this is O( p^n ); very expensive.
495 bool maximal_order() ;
496
497 // Check if the monic polynomial f( x ) has 2 or more distinct factors.
498 // Uses x_to_power().
499 bool hasMultipleDistinctFactors( bool earlyOut = true ) ;
500
501 inline BigInt getR() const { return r_ ; } ;
502
503 inline BigInt getNumPrimPoly() const { return num_prim_poly_ ; } ;
504
505 inline BigInt getMaxNumPoly() const { return max_num_poly_ ; } ;
506
507 // Test if a given polynomial f(x) is primitive.
508 bool isPrimitive() ;
509
510 // Test function.
511 string printQMatrix() const ;
512
513 inline int getNullity() const { return nullity_ ; } ;
514
515 inline Factorization<BigInt> getFactorsOfR() const { return factors_of_R_ ; }
516
517 // Allow direct access to this simple data type for convenience.
518 public:
519 OperationCount statistics_ ;
520
521 protected:
522 // Polynomial f(x) modulo p of degree n which is to be tested.
523 Polynomial f_ ;
524 ppuint n_ ;
525 ppuint p_ ;
526 ModP<ppuint,ppsint> mod ;
527
528 // n
529 // p - 1
530 BigInt p_to_n_minus_1_ ;
531
532 // n
533 // p - 1
534 // r = -------
535 // p - 1
536 BigInt r_ ;
537
538 // Constant factor a (see notes).
539 ppuint a_ ;
540
541 // n
542 // Factorization of p - 1
543 Factorization<BigInt> factors_of_p_to_n_minus_1_ ;
544
545 // Factorization of r.
546 Factorization<BigInt> factors_of_R_ ;
547
548 // Number of possible primitive polynomials.
549 BigInt num_prim_poly_ ;
550
551 // Total number of possible polynomials.
552 BigInt max_num_poly_ ;
553
554 // Two dimensional Q matrix for irreducibility testing.
555 vector< vector<ppsint> > Q_ ;
556
557 int nullity_ ;
558
559 // Helper functions.
560 protected:
561 void generateQMatrix() ;
562
563 void findNullity( bool earlyOut = true ) ;
564
565} ;
566
567#endif // __POLYNOMIAL_H__ --- End of wrapper for header file.