vnl_finite.h
Go to the documentation of this file.
1 // This is core/vnl/vnl_finite.h
2 #ifndef vnl_finite_h_
3 #define vnl_finite_h_
4 //:
5 // \file
6 // \brief modulo-N arithmetic (finite ring Z_N and Z_N[X])
7 //
8 // The templated vnl_finite_int<N> provides arithmetic "modulo N", i.e.,
9 // arithmetic in the finite (Galois) field GF(N) in case N is a prime
10 // or just in the finite ring (or semi-field) of integers modulo N otherwise.
11 // In that case division makes no sense (unless no zero divisor is involved),
12 // but all other operations remain valid.
13 //
14 // Note that this does not cover finite fields with non-prime sizes (4,8,9,...).
15 // These are covered by the vnl_finite_int_poly<N,M> class, which implements
16 // arithmetic with polynomials of degree < M over vnl_finite_int<N>.
17 // Multiplication is defined modulo a degree M polynomial.
18 //
19 // For N prime, and when the "modulo" polynomial is irreducible,
20 // vnl_finite_int_poly<N,M> implements the finite field GF(N^M).
21 //
22 // \author
23 // Peter Vanroose, K.U.Leuven, ESAT/PSI.
24 // \date 5 May 2002.
25 //
26 // \verbatim
27 // Modifications
28 // 1 June 2002 - Peter Vanroose - added totient(), decompose(), is_unit(), order(), log(), exp().
29 // 4 June 2002 - Peter Vanroose - renamed class and file name
30 // 8 June 2002 - Peter Vanroose - added vnl_finite_int_poly<N,M>
31 // 16 Dec 2007 - Peter Vanroose - more efficient implementation of Ntothe()
32 // \endverbatim
33 
34 #include <iostream>
35 #include <vector>
36 #include <cstddef>
37 #include <cassert>
38 #ifdef _MSC_VER
39 # include <vcl_msvc_warnings.h>
40 #endif
41 #include "vnl/vnl_export.h"
42 
43 //: finite modulo-N arithmetic
44 //
45 // The templated vnl_finite_int<N> provides arithmetic "modulo N", i.e.,
46 // arithmetic in the finite (Galois) field GF(N) in case N is a prime
47 // or just in the finite ring (or semi-field) of integers modulo N otherwise.
48 // In that case division makes no sense (unless no zero divisor is involved),
49 // but all other operations remain valid.
50 //
51 template <int N>
53 {
54  private:
55  int val_; //!< value of this number (smallest nonnegative representation)
56 
58  public:
59  //: The number of different finite_int numbers of this type
60  static unsigned int cardinality() { return N; }
61 
62  //: Creates a finite int element.
63  // Default constructor gives 0.
64  // Also serves as automatic cast from int to vnl_finite_int.
65  inline vnl_finite_int(int x = 0) : val_((x%=N)<0?N+x:x), mo_(0), lp1_(0) {assert(N>1);}
66  // Copy constructor
67  inline vnl_finite_int(Base const& x) : val_(int(x)), mo_(x.mo_), lp1_(x.lp1_) {}
68  // Destructor
69  inline ~vnl_finite_int() = default;
70  // Implicit conversions
71  inline operator int() const { return val_; }
72  inline operator int() { return val_; }
73  inline operator long() const { return val_; }
74  inline operator long() { return val_; }
75  inline operator short() const { short r = (short)val_; assert(r == val_); return r; }
76  inline operator short() { short r = (short)val_; assert(r == val_); return r; }
77 
78  //: Assignment
79  inline Base& operator=(Base const& x) { val_ = int(x); mo_=x.mo_; lp1_=x.lp1_; return *this; }
80  inline Base& operator=(int x) { x%=N; val_ = x<0 ? N+x : x; mo_=lp1_=0; return *this; }
81 
82  //: Comparison of finite int numbers.
83  // Note that finite ints have no order, so < and > make no sense.
84  inline bool operator==(Base const& x) const { return val_ == int(x); }
85  inline bool operator!=(Base const& x) const { return val_ != int(x); }
86  inline bool operator==(int x) const { return operator==(Base(x)); }
87  inline bool operator!=(int x) const { return !operator==(x); }
88 
89  //: Unary minus - returns the additive inverse
90  inline Base operator-() const { return Base(N-val_); }
91  //: Unary plus - returns the current number
92  inline Base operator+() const { return *this; }
93  //: Unary not - returns true if finite int number is equal to zero.
94  inline bool operator!() const { return val_ == 0; }
95 
96  //: Plus&assign: replace lhs by lhs + rhs
97  inline Base& operator+=(Base const& r) { mo_=lp1_=0; val_ += int(r); if (val_ >= int(N)) val_ -= N; return *this; }
98  inline Base& operator+=(int r) { return operator=(val_+r); }
99  //: Minus&assign: replace lhs by lhs - rhs
100  inline Base& operator-=(Base const& r) { mo_=lp1_=0; val_ -= int(r); if (val_ < 0) val_ += N; return *this; }
101  inline Base& operator-=(int r) { return operator=(val_-r); }
102  //: Multiply&assign: replace lhs by lhs * rhs
103  inline Base& operator*=(int r) {
104  r %=N; if (r<0) r=N+r;
105  // This rather complicated implementation is necessary to avoid integer overflow
106  if (N<=0x7fff || (val_<=0x7fff && r<=0x7fff)) { val_ *= r; val_ %= N; return *this; }
107  else { int v=val_; operator+=(v); operator*=(r/2); if (r%2) operator+=(v); return *this; }
108  }
109  //: Multiply&assign: replace lhs by lhs * rhs
110  inline Base& operator*=(Base const& r) {
111  mo_=0;
112  if (lp1_!=0 && r.lp1_!=0) set_log(lp1_+r.lp1_-2); else lp1_=0;
113  // This rather complicated implementation is necessary to avoid integer overflow
114  unsigned int s=int(r);
115  if (N<=0x7fff || (val_<=0x7fff && s<=0x7fff)) { val_ *= s; val_ %= N; return *this; }
116  else { int v=val_; operator+=(v); operator*=(s/2); if (s%2) operator+=(v); return *this; }
117  }
118 
119  //: Return the Euler totient function, i.e., the number of units of this ring
120  // This number also equals the periodicity of the exponent: every unit,
121  // when raised to this power, yields 1.
122  static unsigned int totient() {
123  static unsigned int t_ = 0; // cached value
124  if (t_ != 0) return t_;
125  std::vector<unsigned int> d = decompose();
126  t_ = 1; unsigned int p = 1;
127  for (unsigned int i : d)
128  {
129  if (p != i) t_ *= i-1;
130  else t_ *= i;
131  p = i;
132  }
133  return t_;
134  }
135 
136  //: Multiplicative inverse.
137  // Uses exp() and log() for efficient computation, unless log() is not defined.
138  Base reciproc() const {
139  assert(is_unit());
140  if (val_==1) return *this;
141  Base z = smallest_generator();
142  if (z!=1) return exp(Base::totient()-log());
143  for (unsigned int r=1; r<=N/2; ++r) {
144  unsigned int t=int(*this*int(r));
145  if (t==1) return r; else if (t==N-1) return N-r;
146  }
147  return 0; // This will never be executed
148  }
149 
150  //: Divide&assign. Uses r.reciproc() for efficient computation.
151  inline Base& operator/=(Base const& r) {
152  assert(r.is_unit());
153  return val_ == 0 ? operator=(0) : operator*=(r.reciproc());
154  }
155 
156  //: Pre-increment (++r).
157  inline Base& operator++() { mo_=lp1_=0; ++val_; if (val_==N) val_=0; return *this; }
158  //: Pre-decrement (--r).
159  inline Base& operator--() { mo_=lp1_=0; if (val_==0) val_=N; --val_; return *this; }
160  //: Post-increment (r++).
161  inline Base operator++(int) {Base b=*this; mo_=lp1_=0; ++val_; if (val_==N) val_=0; return b; }
162  //: Post-decrement (r--).
163  inline Base operator--(int) {Base b=*this; mo_=lp1_=0; if (val_==0) val_=N; --val_; return b;}
164 
165  //: Write N as the unique product of prime factors.
166  static std::vector<unsigned int> decompose() {
167  static std::vector<unsigned int> decomposition_ = std::vector<unsigned int>(); // cached value
168  if (decomposition_.size() > 0) return decomposition_;
169  unsigned int r = N;
170  for (unsigned int d=2; d*d<=r; ++d)
171  while (r%d == 0) { decomposition_.push_back(d); r /= d; }
172  if (r > 1) decomposition_.push_back(r);
173  return decomposition_;
174  }
175 
176  //: Return true when N is a prime number, i.e., when this ring is a field
177  static inline bool is_field() {
178  std::vector<unsigned int> d = Base::decompose();
179  return d.size() == 1;
180  }
181 
182  //: Return true only when x is a unit in this ring.
183  // In a field, all numbers except 0 are units.
184  // The total number of units is given by the Euler totient function.
185  bool is_unit() const { return gcd(val_) == 1; }
186 
187  //: Return true only when x is a zero divisor, i.e., is not a unit.
188  inline bool is_zero_divisor() const { return gcd(val_) != 1; }
189 
190  //: The additive order of x is the smallest nonnegative r such that r*x == 0.
191  inline unsigned int additive_order() const { if (val_ == 0) return 1; return N/gcd(val_); }
192 
193  //: The multiplicative order of x is the smallest r (>0) such that x^r == 1.
194  unsigned int multiplicative_order() const {
195  if (mo_ != 0) return mo_;
196  if (gcd(val_) != 1) return -1; // should actually return infinity
197  Base y = val_;
198  for (int r=1; r<N; ++r) { if (y==1) return mo_=r; y *= val_; }
199  return 0; // this should not happen
200  }
201 
202  //: Return the smallest multiplicative generator of the units in this ring.
203  // This is only possible if the units form a cyclic group for multiplication.
204  // If not, smallest_generator() returns 1 to indicate this fact.
205  // Note that the multiplication group of a finite \e field is always cyclic.
207  static Base gen_ = 0; // cached value
208  if (gen_ != 0) return gen_;
209  if (N==2) return gen_=1;
210  unsigned int h = Base::totient() / 2; // note that totient() is always even
211  for (gen_=2; gen_!=0; ++gen_) {
212  // calculate gen_^h
213  unsigned int g=h; Base y = 1, z = gen_; while (g>0) { if (g%2) y *= z; g/=2; z*=z; }
214  // quick elimination of non-generator:
215  if (y == 1) continue;
216  // calculate gen_.multiplicative_order() only if really necessary:
217  if (gen_.multiplicative_order() == Base::totient()) { gen_.set_log(1); return gen_; }
218  }
219  assert(!Base::is_field()); // can only reach this point when N is not prime
220  return gen_=1;
221  }
222 
223  //: Return the r-th power of this number.
224  inline Base pow(int r) {
225  r %= Base::totient(); if (r<0) r += Base::totient();
226  if (r==0) return 1; if (r==1) return *this;
227  Base y = 1, z = *this; int s=r; while (s!=0) { if (s%2) y*=z; s/=2; z*=z; }
228  if (lp1_ != 0) y.set_log(r*(lp1_-1));
229  return y;
230  }
231 
232  //: Return the smallest nonnegative exponent r for which x=g^r, where g is the smallest generator.
233  unsigned int log() const {
234  if (is_zero_divisor()) return -1; // should actually return minus infinity
235  if (lp1_ != 0) return lp1_-1;
236  Base z = smallest_generator();
237  assert(N==2||z!=1); // otherwise, the units of this ring do not form a cyclic group
238  Base y = 1;
239  for (lp1_=1; lp1_<=N; ++lp1_) {
240  if (y == *this) return lp1_-1;
241  y *= z;
242  }
243  return -1; // should never reach this point
244  }
245 
246  //: Return the inverse of log(), i.e., return g^r where g is the smallest generator.
247  static inline Base exp(int r) {
248  Base z = smallest_generator();
249  assert(N==2||z!=1); // otherwise, the units of this ring do not form a cyclic group
250  return z.pow(r);
251  }
252 
253  //: Calculate the greatest common divisor of l and N.
254  static inline unsigned int gcd(unsigned int l, unsigned int n) {
255  unsigned int l1 = n;
256  while (l!=0) { unsigned int t = l; l = l1 % l; l1 = t; }
257  return l1;
258  }
259  static inline unsigned int gcd(unsigned int l) { return gcd(l, N); }
260 
261  private:
262  //: private function to set cached value of lp1_ when available
263  void set_log(unsigned int r) const { r %= Base::totient(); lp1_ = r+1; }
264 
265  mutable unsigned int mo_; //!< cached value for multiplicative order
266  mutable unsigned int lp1_; //!< cached value for 1+log()
267 };
268 
269 //: formatted output
270 // \relatesalso vnl_finite_int
271 template <int N>
272 inline std::ostream& operator<< (std::ostream& s, vnl_finite_int<N> const& r)
273 {
274  return s << int(r);
275 }
276 
277 //: simple input
278 // \relatesalso vnl_finite_int
279 template <int N>
280 inline std::istream& operator>> (std::istream& s, vnl_finite_int<N>& r)
281 {
282  int n; s >> n; r=n; return s;
283 }
284 
285 //: Returns the sum of two finite int numbers.
286 // \relatesalso vnl_finite_int
287 template <int N>
289 {
290  vnl_finite_int<N> result(r1); return result += r2;
291 }
292 
293 //: Returns the sum of two finite int numbers.
294 // \relatesalso vnl_finite_int
295 template <int N>
297 {
298  vnl_finite_int<N> result(r1); return result += r2;
299 }
300 
301 //: Returns the sum of two finite int numbers.
302 // \relatesalso vnl_finite_int
303 template <int N>
305 {
306  vnl_finite_int<N> result(r1); return result += r2;
307 }
308 
309 //: Returns the difference of two finite int numbers.
310 // \relatesalso vnl_finite_int
311 template <int N>
313 {
314  vnl_finite_int<N> result(r1); return result -= r2;
315 }
316 
317 //: Returns the difference of two finite int numbers.
318 // \relatesalso vnl_finite_int
319 template <int N>
321 {
322  vnl_finite_int<N> result(r1); return result -= r2;
323 }
324 
325 //: Returns the difference of two finite int numbers.
326 // \relatesalso vnl_finite_int
327 template <int N>
329 {
330  vnl_finite_int<N> result(-r1); return result += r2;
331 }
332 
333 //: Returns the product of two finite int numbers.
334 // \relatesalso vnl_finite_int
335 template <int N>
337 {
338  vnl_finite_int<N> result(r1); return result *= r2;
339 }
340 
341 //: Returns the product of two finite int numbers.
342 // \relatesalso vnl_finite_int
343 template <int N>
345 {
346  vnl_finite_int<N> result(r1); return result *= r2;
347 }
348 
349 //: Returns the product of two finite int numbers.
350 // \relatesalso vnl_finite_int
351 template <int N>
353 {
354  vnl_finite_int<N> result(r1); return result *= r2;
355 }
356 
357 //: Returns the quotient of two finite int numbers.
358 // Uses r2.reciproc() for efficient computation.
359 // \relatesalso vnl_finite_int
360 template <int N>
362 {
363  assert(r2.is_unit()); return r1 == 0 ? vnl_finite_int<N>(0) : r1*r2.reciproc();
364 }
365 
366 //: Returns the quotient of two finite int numbers.
367 // \relatesalso vnl_finite_int
368 template <int N>
370 {
371  vnl_finite_int<N> result(r1); return result /= r2;
372 }
373 
374 //: Returns the quotient of two finite int numbers.
375 // \relatesalso vnl_finite_int
376 template <int N>
378 {
379  vnl_finite_int<N> result(r1); return result /= r2;
380 }
381 
382 //:
383 // \relatesalso vnl_finite_int
384 template <int N>
385 inline bool operator== (int r1, vnl_finite_int<N> const& r2) { return r2==r1; }
386 
387 //:
388 // \relatesalso vnl_finite_int
389 template <int N>
390 inline bool operator!= (int r1, vnl_finite_int<N> const& r2) { return r2!=r1; }
391 
392 namespace vnl_math
393 {
394  //:
395  // \relatesalso vnl_finite_int
396  template <int N>
397  inline vnl_finite_int<N> squared_magnitude(vnl_finite_int<N> const& x) { return x*x; }
398 
399  //:
400  // \relatesalso vnl_finite_int
401  template <int N>
402  inline vnl_finite_int<N> sqr(vnl_finite_int<N> const& x) { return x*x; }
403 
404  //:
405  // \relatesalso vnl_finite_int
406  template <int N>
407  inline bool isnan(vnl_finite_int<N> const& ) {return false;}
408 
409  //:
410  // \relatesalso vnl_finite_int
411  template <int N>
412  inline bool isfinite(vnl_finite_int<N> const& ) {return true;}
413 
414  } // end namespace vnl_math
415 
416 //: finite modulo-N arithmetic with polynomials of degree < M
417 //
418 // This class implements arithmetic with polynomials of degree < M over
419 // vnl_finite_int<N>. Multiplication is defined modulo a polynomial of degree M.
420 //
421 // For N prime, and when the "modulo" polynomial is irreducible,
422 // vnl_finite_int_poly<N,M> implements the finite field GF(N^M).
423 //
424 // Addition, subtraction and scalar multiplication are already defined without
425 // the presence of a "modulo" polynomial. Restricted to these operations,
426 // vnl_finite_int_poly<N,M> forms an M-dimensional vector space over
427 // vnl_finite_int<N>. The current implementation does not yet implement
428 // anything more than that.
429 //
430 template <int N, int M>
432 {
435 
436  std::vector<Scalar> val_; //!< M-tuple (or degree M-1 polynomial) representing this
437 
438  // This essentially implements std::pow(N,int) which is not always available
439  static unsigned int Ntothe(unsigned int m) { return m==0?1:m==1?N:Ntothe(m/2)*Ntothe((m+1)/2); }
440  public:
441  //: The number of different finite_int polynomials of this type
442  static unsigned int cardinality() { return Ntothe(M); }
443 
444  //: Creates a general finite_int_poly.
445  inline vnl_finite_int_poly(std::vector<Scalar> const& p) : val_(p) { assert(N>1); assert(M>0); assert(p.size()<=M); }
446  //: Creates a degree 0 finite_int_poly.
447  inline vnl_finite_int_poly(Scalar const& n) : val_(std::vector<Scalar>(1)) { assert(N>1); assert(M>0); val_[0]=n; }
448  //: Default constructor. Creates a degree 0 finite_int_poly equal to 0.
449  inline vnl_finite_int_poly() : val_(std::vector<Scalar>(1)) { assert(N>1); assert(M>0); val_[0]=0; }
450  // Copy constructor
451  inline vnl_finite_int_poly(Base const& x) : val_(x.val_) {}
452  // Destructor
453  inline ~vnl_finite_int_poly() = default;
454 
455  //: Formal degree of this polynomial
456  inline std::size_t deg() const { return val_.size() - 1; }
457 
458  //: Effective degree of this polynomial; equals -1 when this polynomial is 0.
459  int degree() const { for (int i=deg(); i>=0; --i) if (val_[i]!=0) return i; return -1; }
460 
461  //: Access to individual coefficients
462  inline Scalar operator[](unsigned int i) const { assert(i<M); return i<=deg() ? val_[i] : Scalar(0); }
463 
464  //: Assignment
465  inline Base& operator=(Base const& x) { val_ = x.val_; return *this; }
466  inline Base& operator=(Scalar const& n) { val_ = std::vector<Scalar>(1); val_[0] = n; return *this; }
467 
468  //: Comparison of finite int polys.
469  bool operator==(Base const& x) const {
470  for (unsigned int i=0; i<=deg(); ++i)
471  if (val_[i] != x[i]) return false;
472  for (unsigned int i=deg()+1; i<=x.deg(); ++i)
473  if (x[i] != 0) return false;
474  return true;
475  }
476  inline bool operator!=(Base const& x) const { return !operator==(x); }
477  bool operator==(Scalar const& x) const {
478  if (x!=val_[0]) return false;
479  for (unsigned int i=1; i<=deg(); ++i) if (val_[i] != 0) return false;
480  return true;
481  }
482  inline bool operator!=(Scalar const& x) const { return !operator==(x); }
483 
484  //: Unary minus - returns the additive inverse
485  Base operator-() const { std::vector<Scalar> p = val_; for (unsigned int i=0; i<p.size(); ++i) p[i]=-p[i]; return p; }
486  //: Unary plus - returns the current polynomial
487  inline Base operator+() const { return *this; }
488  //: Unary not - returns true if finite int poly is equal to zero.
489  bool operator!() const { for (unsigned int i=0; i<=deg(); ++i) if (val_[i] != 0) return false; return true; }
490 
491  //: Plus&assign: replace lhs by lhs + rhs
492  Base& operator+=(Base const& r) {
493  for (unsigned int i=0; i<=r.deg(); ++i)
494  if (i<=deg()) val_[i] += r[i];
495  else val_.push_back(r[i]);
496  return *this;
497  }
498  //: Minus&assign: replace lhs by lhs - rhs
499  Base& operator-=(Base const& r) {
500  for (unsigned int i=0; i<=r.deg(); ++i)
501  if (i<=deg()) val_[i] -= r[i];
502  else val_.push_back(-r[i]);
503  return *this;
504  }
505 
506  //: Scalar multiple of this
507  Base& operator*=(Scalar const& n) { for (unsigned int i=0; i<=deg(); ++i) val_[i] *= n; return *this; }
508 
509  //: The additive order of x is the smallest positive r such that r*x == 0.
510  unsigned int additive_order() const {
511  unsigned int r = N;
512  for (unsigned int i=0; i<=deg(); ++i)
513  if (val_[i] != 0) r=Scalar::gcd(val_[i],r);
514  return N/r;
515  }
516 
517  //: get/set the (irreducible) modulo polynomial of degree M
518  // Note that this polynomial has to be set only once, i.e., once set,
519  // it applies to all vnl_finite_int_polys with the same N and M.
520  static std::vector<Scalar>& modulo_polynomial(std::vector<Scalar> p = std::vector<Scalar>())
521  {
522  static std::vector<Scalar> poly_(M+1, Scalar(0));
523  if (p.size() == 0) { // retrieval
524  assert(poly_[M] != 0); // cannot retrieve before having set
525  }
526  else
527  {
528  assert(p.size() == M+1 && p[M].is_unit());// must be of effective degree M
529  // Now set poly_, thereby making the coefficient poly_[M] equal to -1.
530  Scalar f = -1/p[M];
531  for (int m=0; m<=M; ++m) poly_[m] = f*p[m];
532  }
533  return poly_;
534  }
535 
536  //: Multiply&assign: replace lhs by lhs * rhs, modulo the "modulo" polynomial
537  Base& operator*=(Base const& r) {
538  Base x = *this; *this = r; *this *= x[0];
539  while (val_.size() < M) val_.push_back(0);
540  for (int i=1; i<=x.degree(); ++i)
541  for (unsigned int j=0; j<=r.deg(); ++j)
542  add_modulo_poly(i+j, x[i]*r[j]);
543  return *this;
544  }
545 
546  //: Return the multiplicative order of this polynomial.
547  inline unsigned int multiplicative_order() const {
548  Base t = Scalar(1);
549  unsigned int order = 0;
550  do t *= *this, ++order; while (t != Scalar(1) && t != Scalar(0));
551  return t==Scalar(1) ? order : -1;
552  }
553 
554  //: Return true when this ring is a field.
555  // Note that this requires that N is a prime, but that condition is not
556  // sufficient: also the "modulo" polynomial must be irreducible.
557  static inline bool is_field() {
558  if (!Scalar::is_field()) return false;
559 
560  std::vector<Scalar> mod_p = Base::modulo_polynomial();
561  mod_p.pop_back(); // remove the "-1" coefficient of X^M
562  return Base(mod_p).multiplicative_order()+1 == Base::cardinality();
563  }
564 
565  //: Return the smallest multiplicative generator of the units in this ring.
566  // This is only possible if the units form a cyclic group for multiplication.
567  // If not, smallest_generator() returns 1 to indicate this fact.
568  // Note that the multiplication group of a finite \e field is always cyclic.
570  if (!Base::is_field()) return Scalar(1);
571  std::vector<Scalar> mod_p = Base::modulo_polynomial();
572  mod_p.pop_back(); // remove the "-1" coefficient of X^M
573  return Base(mod_p);
574  }
575 
576  private:
577  //: Add x to the i-th degree coefficient of val_, possibly reducing modulo the "modulo" poly.
578  void add_modulo_poly(unsigned int m, Scalar const& x)
579  {
580  if (m < M) val_[m] += x;
581  else {
582  std::vector<Scalar> p = modulo_polynomial(); // where p[M] == -1
583  for (int k=0; k<M; ++k) add_modulo_poly(m-M+k, x*p[k]); // recursive call
584  }
585  }
586 };
587 
588 //: Returns the sum of two finite int polynomials.
589 // \relatesalso vnl_finite_int_poly
590 template <int N, int M>
592 {
593  vnl_finite_int_poly<N,M> result=r1; return result += r2;
594 }
595 
596 //: Returns the difference of two finite int polynomials.
597 // \relatesalso vnl_finite_int_poly
598 template <int N, int M>
600 {
601  vnl_finite_int_poly<N,M> result=r1; return result -= r2;
602 }
603 
604 //: Returns a scalar multiple of a finite int polynomial.
605 // \relatesalso vnl_finite_int
606 // \relatesalso vnl_finite_int_poly
607 template <int N, int M>
609 {
610  vnl_finite_int_poly<N,M> result(r1); return result *= r2;
611 }
612 
613 //: Returns a scalar multiple of a finite int polynomial.
614 // \relatesalso vnl_finite_int
615 // \relatesalso vnl_finite_int_poly
616 template <int N, int M>
618 {
619  vnl_finite_int_poly<N,M> result(r1); return result *= r2;
620 }
621 
622 //: Multiplies two finite int polynomials.
623 // NOTE: this requires the "modulo" polynomial to be set.
624 // Do this by calling modulo_polynomial(p), where p is a vector of length M+1.
625 // \relatesalso vnl_finite_int_poly
626 template <int N, int M>
628 {
629  vnl_finite_int_poly<N,M> result(r1); return result *= r2;
630 }
631 
632 //: formatted output
633 // \relatesalso vnl_finite_int_poly
634 template <int N, int M>
635 inline std::ostream& operator<< (std::ostream& s, vnl_finite_int_poly<N,M> const& r)
636 {
637  bool out = false;
638  for (unsigned int i=0; i<=r.deg(); ++i) {
639  if (r[i] == 0) continue;
640  if (out) s << '+';
641  out = true;
642  if (r[i] != 1 || i==0) s << r[i];
643  if (i>0) s << 'X';
644  if (i>1) s << '^' << i;
645  }
646  if (!out) s << '0';
647  return s;
648 }
649 
650 #endif // vnl_finite_h_
bool operator==(Base const &x) const
Comparison of finite int numbers.
Definition: vnl_finite.h:84
vnl_bignum operator+(vnl_bignum const &r1, long r2)
Returns the sum of two bignum numbers.
Definition: vnl_bignum.h:279
vnl_finite_int(Base const &x)
Definition: vnl_finite.h:67
~vnl_finite_int_poly()=default
int val_
value of this number (smallest nonnegative representation)
Definition: vnl_finite.h:55
Scalar operator[](unsigned int i) const
Access to individual coefficients.
Definition: vnl_finite.h:462
Base & operator-=(Base const &r)
Minus&assign: replace lhs by lhs - rhs.
Definition: vnl_finite.h:100
bool operator!=(Base const &x) const
Definition: vnl_finite.h:476
Base operator-() const
Unary minus - returns the additive inverse.
Definition: vnl_finite.h:485
finite modulo-N arithmetic.
Definition: vnl_finite.h:52
unsigned int lp1_
cached value for 1+log()
Definition: vnl_finite.h:266
static Base smallest_generator()
Return the smallest multiplicative generator of the units in this ring.
Definition: vnl_finite.h:206
unsigned int mo_
cached value for multiplicative order
Definition: vnl_finite.h:265
#define m
Definition: vnl_vector.h:43
Base operator-() const
Unary minus - returns the additive inverse.
Definition: vnl_finite.h:90
vnl_finite_int_poly< N, M > Base
Definition: vnl_finite.h:433
Base operator--(int)
Post-decrement (r–).
Definition: vnl_finite.h:163
vnl_finite_int(int x=0)
Creates a finite int element.
Definition: vnl_finite.h:65
vnl_finite_int_poly()
Default constructor. Creates a degree 0 finite_int_poly equal to 0.
Definition: vnl_finite.h:449
real numerical constants.
Definition: vnl_bignum.h:430
Base & operator=(int x)
Definition: vnl_finite.h:80
static unsigned int gcd(unsigned int l)
Definition: vnl_finite.h:259
Base & operator *=(Scalar const &n)
Scalar multiple of this.
Definition: vnl_finite.h:507
static unsigned int gcd(unsigned int l, unsigned int n)
Calculate the greatest common divisor of l and N.
Definition: vnl_finite.h:254
static Base smallest_generator()
Return the smallest multiplicative generator of the units in this ring.
Definition: vnl_finite.h:569
bool is_unit() const
Return true only when x is a unit in this ring.
Definition: vnl_finite.h:185
bool operator!=(int x) const
Definition: vnl_finite.h:87
vnl_bignum squared_magnitude(vnl_bignum const &x)
Definition: vnl_bignum.h:433
finite modulo-N arithmetic with polynomials of degree < M.
Definition: vnl_finite.h:431
vnl_finite_int_poly(Scalar const &n)
Creates a degree 0 finite_int_poly.
Definition: vnl_finite.h:447
std::ostream & operator<<(std::ostream &s, vnl_decnum const &r)
decimal output.
Definition: vnl_decnum.h:393
Base & operator=(Base const &x)
Assignment.
Definition: vnl_finite.h:79
Base operator+() const
Unary plus - returns the current polynomial.
Definition: vnl_finite.h:487
Base & operator+=(Base const &r)
Plus&assign: replace lhs by lhs + rhs.
Definition: vnl_finite.h:492
Base & operator+=(Base const &r)
Plus&assign: replace lhs by lhs + rhs.
Definition: vnl_finite.h:97
unsigned int additive_order() const
The additive order of x is the smallest positive r such that r*x == 0.
Definition: vnl_finite.h:510
#define v
Definition: vnl_vector.h:42
vnl_finite_int_poly(Base const &x)
Definition: vnl_finite.h:451
bool isnan(vnl_bignum const &)
Definition: vnl_bignum.h:435
bool operator!=(Base const &x) const
Definition: vnl_finite.h:85
~vnl_finite_int()=default
unsigned int multiplicative_order() const
The multiplicative order of x is the smallest r (>0) such that x^r == 1.
Definition: vnl_finite.h:194
static std::vector< unsigned int > decompose()
Write N as the unique product of prime factors.
Definition: vnl_finite.h:166
bool operator==(int r1, vnl_finite_int< N > const &r2)
Definition: vnl_finite.h:385
Base operator++(int)
Post-increment (r++).
Definition: vnl_finite.h:161
void add_modulo_poly(unsigned int m, Scalar const &x)
Add x to the i-th degree coefficient of val_, possibly reducing modulo the "modulo" poly.
Definition: vnl_finite.h:578
bool operator!() const
Unary not - returns true if finite int poly is equal to zero.
Definition: vnl_finite.h:489
Base & operator=(Scalar const &n)
Definition: vnl_finite.h:466
static Base exp(int r)
Return the inverse of log(), i.e., return g^r where g is the smallest generator.
Definition: vnl_finite.h:247
std::vector< Scalar > val_
M-tuple (or degree M-1 polynomial) representing this.
Definition: vnl_finite.h:436
bool isfinite(vnl_bignum const &x)
Definition: vnl_bignum.h:436
Base & operator--()
Pre-decrement (–r).
Definition: vnl_finite.h:159
static bool is_field()
Return true when this ring is a field.
Definition: vnl_finite.h:557
Base operator+() const
Unary plus - returns the current number.
Definition: vnl_finite.h:92
static bool is_field()
Return true when N is a prime number, i.e., when this ring is a field.
Definition: vnl_finite.h:177
Base & operator-=(int r)
Definition: vnl_finite.h:101
unsigned int log() const
Return the smallest nonnegative exponent r for which x=g^r, where g is the smallest generator.
Definition: vnl_finite.h:233
vnl_finite_int< N > Scalar
Definition: vnl_finite.h:434
Base & operator-=(Base const &r)
Minus&assign: replace lhs by lhs - rhs.
Definition: vnl_finite.h:499
int degree() const
Effective degree of this polynomial; equals -1 when this polynomial is 0.
Definition: vnl_finite.h:459
static unsigned int Ntothe(unsigned int m)
Definition: vnl_finite.h:439
bool operator==(Base const &x) const
Comparison of finite int polys.
Definition: vnl_finite.h:469
static std::vector< Scalar > & modulo_polynomial(std::vector< Scalar > p=std::vector< Scalar >())
get/set the (irreducible) modulo polynomial of degree M.
Definition: vnl_finite.h:520
Base & operator=(Base const &x)
Assignment.
Definition: vnl_finite.h:465
Base & operator+=(int r)
Definition: vnl_finite.h:98
static unsigned int cardinality()
The number of different finite_int numbers of this type.
Definition: vnl_finite.h:60
Base reciproc() const
Multiplicative inverse.
Definition: vnl_finite.h:138
vnl_finite_int< N > Base
Definition: vnl_finite.h:57
VNL_EXPORT std::istream & operator>>(std::istream &s, vnl_decnum &r)
decimal input.
Definition: vnl_decnum.cxx:411
vnl_bignum operator-(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the difference of two bignum numbers.
Definition: vnl_bignum.h:290
bool operator!=(int r1, vnl_finite_int< N > const &r2)
Definition: vnl_finite.h:390
unsigned int multiplicative_order() const
Return the multiplicative order of this polynomial.
Definition: vnl_finite.h:547
void set_log(unsigned int r) const
private function to set cached value of lp1_ when available.
Definition: vnl_finite.h:263
unsigned int additive_order() const
The additive order of x is the smallest nonnegative r such that r*x == 0.
Definition: vnl_finite.h:191
bool operator!=(Scalar const &x) const
Definition: vnl_finite.h:482
Base & operator++()
Pre-increment (++r).
Definition: vnl_finite.h:157
Base pow(int r)
Return the r-th power of this number.
Definition: vnl_finite.h:224
bool is_zero_divisor() const
Return true only when x is a zero divisor, i.e., is not a unit.
Definition: vnl_finite.h:188
Base & operator/=(Base const &r)
Divide&assign. Uses r.reciproc() for efficient computation.
Definition: vnl_finite.h:151
vnl_bignum operator/(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the division of two bignum numbers.
Definition: vnl_bignum.h:349
static unsigned int totient()
Return the Euler totient function, i.e., the number of units of this ring.
Definition: vnl_finite.h:122
bool operator==(int x) const
Definition: vnl_finite.h:86
vnl_bignum operator *(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the product of two bignum numbers.
Definition: vnl_bignum.h:302
std::size_t deg() const
Formal degree of this polynomial.
Definition: vnl_finite.h:456
vnl_finite_int_poly(std::vector< Scalar > const &p)
Creates a general finite_int_poly.
Definition: vnl_finite.h:445
vnl_bignum sqr(vnl_bignum const &x)
Definition: vnl_bignum.h:434
bool operator!() const
Unary not - returns true if finite int number is equal to zero.
Definition: vnl_finite.h:94
static unsigned int cardinality()
The number of different finite_int polynomials of this type.
Definition: vnl_finite.h:442
Base & operator *=(int r)
Multiply&assign: replace lhs by lhs * rhs.
Definition: vnl_finite.h:103
bool operator==(Scalar const &x) const
Definition: vnl_finite.h:477