The ChainCon Software (Release 0.03)
ringzp.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 ///
3 /// \file
4 ///
5 /// Elements of the ring Z_p.
6 ///
7 /////////////////////////////////////////////////////////////////////////////
8 
9 // Copyright (C) 2009-2016 by Pawel Pilarczyk.
10 //
11 // This file is part of my research software package. This is free software:
12 // you can redistribute it and/or modify it under the terms of the GNU
13 // General Public License as published by the Free Software Foundation,
14 // either version 3 of the License, or (at your option) any later version.
15 //
16 // This software is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this software; see the file "license.txt". If not,
23 // please, see <http://www.gnu.org/licenses/>.
24 
25 // Started on March 24, 2009. Last revision: June 20, 2012.
26 
27 
28 #ifndef _CHAINCON_RINGZP_H_
29 #define _CHAINCON_RINGZP_H_
30 
31 
32 // include some standard C++ header files
33 #include <istream>
34 #include <ostream>
35 #include <sstream>
36 #include <string>
37 
38 // include selected header files from the CHomP library
39 #include "chomp/system/config.h"
40 
41 
42 // --------------------------------------------------
43 // --------- selected features of integers ----------
44 // --------------------------------------------------
45 
46 /// A collection of selected features of integer numbers.
47 template <class intType>
49 {
50 }; /* IntFeatures */
51 
52 // --------------------------------------------------
53 
54 /// Specific features of the type 'int'.
55 template <>
56 class IntFeatures<int>
57 {
58 public:
59  /// The name of a twice longer integer type.
60  typedef long LongerInt;
61 
62 }; /* IntFeatures<int> */
63 
64 // --------------------------------------------------
65 
66 /// Specific features of the type 'short'.
67 template <>
68 class IntFeatures<short>
69 {
70 public:
71  /// The name of a twice longer integer type.
72  typedef int LongerInt;
73 
74 }; /* IntFeatures<short> */
75 
76 // --------------------------------------------------
77 
78 /// Specific features of the type 'char' (use with caution!).
79 template <>
80 class IntFeatures<char>
81 {
82 public:
83  /// The name of a twice longer integer type.
84  typedef short LongerInt;
85 
86 }; /* IntFeatures<char> */
87 
88 // --------------------------------------------------
89 
90 /// Inverts a number in the modulo 'p' arithmetic,
91 /// provided that 'p' is a prime number.
92 /// This procedure is good for large values of 'p'
93 /// and uses a longer type of integers for multiplication.
94 template <class intType>
95 intType invertModuloLargeP (const intType &n, const intType &q)
96 {
97  if ((n == 1) || (n == (q - 1)))
98  return n;
99 
100  typedef typename IntFeatures<intType>::LongerInt LongerInt;
101  LongerInt result (1);
102  LongerInt nLonger (n);
103  intType i (q - 2);
104 
105  while (i)
106  {
107  if (i & 1)
108  {
109  result = (result * nLonger) % q;
110  -- i;
111  }
112  else
113  {
114  nLonger = (nLonger * nLonger) % q;
115  i >>= 1;
116  }
117  }
118 
119  return (static_cast<intType> (result));
120 } /* invertModuloLargeP */
121 
122 /// Inverts a number in the modulo 'p' arithmetic,
123 /// provided that 'p' is a prime number.
124 /// This procedure is good for small values of 'p',
125 /// such that 'p' squared still fits in the same integer type.
126 template <class intType>
127 intType invertModuloSmallP (const intType &n, const intType &q)
128 {
129  if ((n == 1) || (n == (q - 1)))
130  return n;
131 
132  intType result (1);
133  intType m (n);
134  intType i (q - 2);
135 
136  while (i)
137  {
138  if (i & 1)
139  {
140  result = (result * m) % q;
141  -- i;
142  }
143  else
144  {
145  m = (m * m) % q;
146  i >>= 1;
147  }
148  }
149 
150  return result;
151 } /* invertModuloSmallP */
152 
153 /// Verifies if the given number is a positive prime number.
154 template <class intType>
155 bool numberIsPrime (const intType &n)
156 {
157  if (n < 2)
158  return 0;
159 
160  typedef typename IntFeatures<intType>::LongerInt LongerInt;
161  LongerInt i (2);
162 
163  while (1)
164  {
165  if (i * i > n)
166  return true;
167  if (!(n % i))
168  return false;
169  ++ i;
170  }
171 } /* numberIsPrime */
172 
173 
174 // --------------------------------------------------
175 // ----- division with reminder in the ring Z_p -----
176 // --------------------------------------------------
177 
178 template <class intType>
179 class tZp;
180 
181 template <class intType>
182 inline bool divide (const tZp<intType> &a, const tZp<intType> &b,
183  tZp<intType> &quotient, tZp<intType> &remainder)
184 {
185  if (!b. _n)
186  throw "Division by zero in the ring Z_p.";
187  if (tZp<intType>::_p)
188  {
189  quotient = b;
190  quotient. invert ();
191  quotient *= a;
192  remainder = tZp<intType> (static_cast<intType> (0));
193  return true;
194  }
195  else
196  {
197  intType q = a. _n / b. _n;
198  intType r = a. _n % b. _n;
199  quotient = tZp<intType> (q);
200  remainder = tZp<intType> (r);
201  return !r;
202  }
203 } /* divide */
204 
205 
206 // --------------------------------------------------
207 // ------------ elements of the ring Z_p ------------
208 // --------------------------------------------------
209 
210 /// An element of the ring Z_p, where p is globally set.
211 /// Set p=0 for the ring Z (note the limited range of valid values).
212 /// In this implementation, p must be set smaller than the square root
213 /// of the largest positive number that can be encoded in the underlying
214 /// integer type.
215 template <class intType>
216 class tZp
217 {
218 public:
219  /// Default constructor of a ring element.
220  /// Note: The default copy constructor, destructor,
221  /// and assignment operators are fine.
222  tZp ();
223 
224  /// Constructor from an integer number
225  /// (to be used mainly for 0 or 1).
226  explicit tZp (const intType &n);
227 
228  /// Conversion to an integer.
229  /// Note that in some rings this conversion may not be valid.
230  operator intType () const;
231 
232  /// The delta function.
233  intType delta () const;
234 
235  /// Negates the ring element.
236  tZp<intType> &negate ();
237 
238  /// Inverts the ring element. Assumes that 'p' is a prime number.
239  tZp<intType> &invert ();
240 
241  /// Adds another ring element.
242  tZp<intType> &operator += (const tZp<intType> &another);
243 
244  /// Multiplies by another ring element.
245  tZp<intType> &operator *= (const tZp<intType> &another);
246 
247  /// Swaps the internal data with another ring element.
248  void swap (tZp<intType> &another);
249 
250  /// Sets the number p for the ring.
251  static void setp (const intType &p);
252 
253  /// Gets the currently set number p for the ring.
254  static const intType &getp ();
255 
256  /// Returns the symbol of the ring.
257  static std::string ringsymbol ();
258 
259  /// Performs the division with remainder in the ring.
260  /// Returns true if the remainer is zero, false otherwise.
261  friend bool divide<intType>
262  (const tZp<intType> &a, const tZp<intType> &b,
263  tZp<intType> &quotient, tZp<intType> &remainder);
264 
265 private:
266  /// The number corresponding to the ring element.
267  intType _n;
268 
269  /// The number that defines the ring.
270  static intType _p;
271 
272 }; /* class tZp */
273 
274 // --------------------------------------------------
275 
276 template <class intType>
277 intType tZp<intType>::_p = 2;
278 
279 // --------------------------------------------------
280 
281 template <class intType>
283 {
284  return;
285 } /* tZp::tZp */
286 
287 template <class intType>
288 inline tZp<intType>::tZp (const intType &n)
289 {
290  if (_p)
291  {
292  if (n < 0)
293  {
294  if (n > -_p)
295  {
296  _n = n + _p;
297  }
298  else
299  {
300  intType r = (-n) % _p;
301  _n = r ? (_p - r) : 0;
302  }
303  }
304  else if (n < _p)
305  _n = n;
306  else if (n - _p < _p)
307  _n = n - _p;
308  else
309  _n = n % _p;
310  }
311  else
312  {
313  _n = n;
314  }
315  return;
316 } /* tZp::tZp */
317 
318 template <class intType>
319 inline tZp<intType>::operator intType () const
320 {
321  return _n;
322 } /* tZp::operator intType */
323 
324 template <class intType>
325 inline intType tZp<intType>::delta () const
326 {
327  if (_p)
328  return (_n ? 1 : 0);
329  else
330  return (_n >= 0) ? _n : -_n;
331 } /* tZp::delta */
332 
333 template <class intType>
335 {
336  if (_n)
337  {
338  if (!_p)
339  _n = -_n;
340  else
341  _n = _p - _n;
342  }
343  return *this;
344 } /* tZp::negate */
345 
346 template <class intType>
348 {
349  if (_p)
350  {
351  // _n = invertModuloLargeP (_n, _p);
352  _n = invertModuloSmallP (_n, _p);
353  }
354  else if ((_n != -1) && (_n != 1))
355  throw "Trying to invert a noninvertible integer number.";
356  return *this;
357 } /* tZp::invert */
358 
359 template <class intType>
361 {
362  _n += another. _n;
363  if (_p && (_n >= _p))
364  _n -= _p;
365  return *this;
366 } /* tZp::operator += */
367 
368 template <class intType>
370 {
371  _n *= another. _n;
372  if (_p && (_n >= _p))
373  _n = _n % _p;
374  return *this;
375 } /* tZp::operator *= */
376 
377 template <class intType>
378 inline void tZp<intType>::swap (tZp<intType> &another)
379 {
380  intType tmp (_n);
381  _n = another. _n;
382  another. _n = tmp;
383  return;
384 } /* tZp::swap */
385 
386 // --------------------------------------------------
387 
388 template <class intType>
389 inline void tZp<intType>::setp (const intType &p)
390 {
391  // the number cannot be negative
392  if (p < 0)
393  throw "Trying to set p < 0 for the ring Z_p.";
394 
395  // if the number is positive...
396  if (p)
397  {
398  // increase the number to the nearest prime
399  if (!numberIsPrime (p))
400  {
401  intType q (p);
402  do
403  {
404  ++ q;
405  } while ((q > 0) && !numberIsPrime (q));
406  if (q <= 0)
407  {
408  throw "Can't increase p to a prime number "
409  "for Z_p.";
410  }
411  _p = q;
412  }
413  else
414  {
415  _p = p;
416  }
417 
418  // make sure that the number is not too large
419  typename IntFeatures<intType>::LongerInt p2long (_p);
420  p2long *= _p;
421  intType p2 (_p);
422  p2 *= _p;
423  if (p2long != p2)
424  throw "Int type too small for p requested in Z_p.";
425  }
426  else
427  {
428  _p = p;
429  }
430 
431  return;
432 } /* tZp::setp */
433 
434 template <class intType>
435 inline const intType &tZp<intType>::getp ()
436 {
437  return _p;
438 } /* tZp::getp */
439 
440 template <class intType>
441 inline std::string tZp<intType>::ringsymbol ()
442 {
443  std::ostringstream out;
444  out << 'Z';
445  if (_p)
446  out << '_' << _p;
447  return out. str ();
448 } /* tZp::ringsymbol */
449 
450 // --------------------------------------------------
451 
452 /// Generates a hashing key no. 1 for an element of the Zp ring.
453 /// This key is to be used in a hashed set.
454 template <class intType>
455 inline int_t hashkey1 (const tZp<intType> &n)
456 {
457  return static_cast<int_t> (static_cast<intType> (n));
458 } /* hashkey1 */
459 
460 /// Generates a hashing key no. 2 for a general pair of elements,
461 /// based on hashing keys of the elements.
462 /// This key is to be used in a hashed set.
463 template <class intType>
464 inline int_t hashkey2 (const tZp<intType> &n)
465 {
466  return static_cast<int_t> (static_cast<intType> (n)) ^ 0xA5A5;
467 } /* hashkey2 */
468 
469 // --------------------------------------------------
470 
471 /// Reads an element from an input stream.
472 template <class intType>
473 inline std::istream &operator >> (std::istream &in, tZp<intType> &n)
474 {
475  intType number;
476  in >> number;
477  n = tZp<intType> (number);
478  return in;
479 } /* operator >> */
480 
481 /// Writes an element to an output stream.
482 template <class intType>
483 inline std::ostream &operator << (std::ostream &out, const tZp<intType> &n)
484 {
485  out << static_cast<intType> (n);
486  return out;
487 } /* operator << */
488 
489 // --------------------------------------------------
490 
491 /// Operator == for checking whether two elements of possibly different rings
492 /// are equal.
493 template <class intType1, class intType2>
494 inline bool operator == (const tZp<intType1> &n1, const tZp<intType2> &n2)
495 {
496  return (static_cast<intType1> (n1) == static_cast<intType2> (n2));
497 } /* operator == */
498 
499 /// Operator == for checking whether a ring element is equivalent
500 /// to an integer number. Intended to compare with 0 and 1 only.
501 template <class intType1, class intType2>
502 inline bool operator == (const tZp<intType1> &n1, const intType2 &n2)
503 {
504  return (static_cast<intType1> (n1) == n2);
505 } /* operator == */
506 
507 /// Operator == for checking whether a ring element is equivalent
508 /// to an integer number. Intended to compare with 0 and 1 only.
509 template <class intType1, class intType2>
510 inline bool operator == (const intType1 &n1, const tZp<intType2> &n2)
511 {
512  return (n1 == static_cast<intType2> (n2));
513 } /* operator == */
514 
515 
516 #endif // _CHAINCON_RINGZP_H_
517 
tZp< intType > & operator*=(const tZp< intType > &another)
Multiplies by another ring element.
Definition: ringzp.h:369
void swap(tZp< intType > &another)
Swaps the internal data with another ring element.
Definition: ringzp.h:378
short LongerInt
The name of a twice longer integer type.
Definition: ringzp.h:84
int_t hashkey2(const tZp< intType > &n)
Generates a hashing key no.
Definition: ringzp.h:464
A collection of selected features of integer numbers.
Definition: ringzp.h:48
tZp< intType > & invert()
Inverts the ring element. Assumes that &#39;p&#39; is a prime number.
Definition: ringzp.h:347
tZp< intType > & operator+=(const tZp< intType > &another)
Adds another ring element.
Definition: ringzp.h:360
static const intType & getp()
Gets the currently set number p for the ring.
Definition: ringzp.h:435
bool operator==(const tZp< intType1 > &n1, const tZp< intType2 > &n2)
Operator == for checking whether two elements of possibly different rings are equal.
Definition: ringzp.h:494
bool numberIsPrime(const intType &n)
Verifies if the given number is a positive prime number.
Definition: ringzp.h:155
bool divide(const tZp< intType > &a, const tZp< intType > &b, tZp< intType > &quotient, tZp< intType > &remainder)
Definition: ringzp.h:182
int LongerInt
The name of a twice longer integer type.
Definition: ringzp.h:72
tZp()
Default constructor of a ring element.
Definition: ringzp.h:282
intType delta() const
The delta function.
Definition: ringzp.h:325
long LongerInt
The name of a twice longer integer type.
Definition: ringzp.h:60
int_t hashkey1(const tZp< intType > &n)
Generates a hashing key no.
Definition: ringzp.h:455
tZp< intType > & negate()
Negates the ring element.
Definition: ringzp.h:334
static std::string ringsymbol()
Returns the symbol of the ring.
Definition: ringzp.h:441
intType invertModuloSmallP(const intType &n, const intType &q)
Inverts a number in the modulo &#39;p&#39; arithmetic, provided that &#39;p&#39; is a prime number.
Definition: ringzp.h:127
static intType _p
The number that defines the ring.
Definition: ringzp.h:270
An element of the ring Z_p, where p is globally set.
Definition: ringzp.h:179
intType _n
The number corresponding to the ring element.
Definition: ringzp.h:267
std::istream & operator>>(std::istream &in, tZp< intType > &n)
Reads an element from an input stream.
Definition: ringzp.h:473
intType invertModuloLargeP(const intType &n, const intType &q)
Inverts a number in the modulo &#39;p&#39; arithmetic, provided that &#39;p&#39; is a prime number.
Definition: ringzp.h:95
static void setp(const intType &p)
Sets the number p for the ring.
Definition: ringzp.h:389