SeComLib
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros Pages
big_integer_gmp.cpp
Go to the documentation of this file.
1 /*
2 SeComLib
3 Copyright 2012-2013 TU Delft, Information Security & Privacy Lab (http://isplab.tudelft.nl/)
4 
5 Contributors:
6 Inald Lagendijk (R.L.Lagendijk@TUDelft.nl)
7 Mihai Todor (todormihai@gmail.com)
8 Thijs Veugen (P.J.M.Veugen@tudelft.nl)
9 Zekeriya Erkin (z.erkin@tudelft.nl)
10 
11 Licensed under the Apache License, Version 2.0 (the "License");
12 you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at
14 
15 http://www.apache.org/licenses/LICENSE-2.0
16 
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
29 #include "big_integer_gmp.h"
30 
31 namespace SeComLib {
32 namespace Core {
43  mpz_init(input.data);
44  }
45 
51  mpz_init_set(input.data, value.data);
52  }
53 
58  void BigIntegerGmp::Initialize (BigIntegerBase<BigIntegerGmp> &input, const long value) {
59  mpz_init_set_si(input.data, value);
60  }
61 
66  void BigIntegerGmp::Initialize (BigIntegerBase<BigIntegerGmp> &input, const unsigned long value) {
67  mpz_init_set_ui(input.data, value);
68  }
69 
80  void BigIntegerGmp::Initialize (BigIntegerBase<BigIntegerGmp> &input, const double value, const BigIntegerBase<BigIntegerGmp> &scaling, const bool truncate) {
81  mpz_init(input.data);
82 
83  mpf_set_default_prec(1024);//1024 is the default value and it should be more than enough
84 
85  //auxiliary big float used for applying scaling and rounding before exporting it to input.data
86  mpf_t tempFloat;
87  //we can't multiply mpf_t with mpz_t, so we need a temporary mpf_t for the scaling
88  mpf_t tempScaling;
89  //contains the value 0.5, used for the rounding procedure
90  mpf_t zeroPointFive;
91 
92  //set the value
93  mpf_init_set_d(tempFloat, value);
94 
95  //gmp_printf ("Value: %.*Ff\r\n", 30, tempFloat);
96 
97  //set the scaling
98  mpf_init(tempScaling);
99  mpf_set_z(tempScaling, scaling.data);
100 
101  //set 0.5
102  mpf_init_set_d(zeroPointFive, 0.5);
103 
104  //apply the scaling
105  mpf_mul(tempFloat, tempFloat, tempScaling);
106 
107  if (truncate) {
108  //discard decimals
109  mpf_trunc(tempFloat, tempFloat);
110  }
111  else {
112  //round the value to the nearest (positive or negative) integer
113  //input < 0.0 ? ceil(input - 0.5) : floor(input + 0.5));
114  if (-1 == mpf_sgn(tempFloat)) {
115  mpf_sub(tempFloat, tempFloat, zeroPointFive);
116  mpf_ceil(tempFloat, tempFloat);
117  }
118  else {
119  mpf_add(tempFloat, tempFloat, zeroPointFive);
120  mpf_floor(tempFloat, tempFloat);
121  }
122  }
123 
124  //gmp_printf ("Value: %.*Ff\r\n", 30, tempFloat);
125 
126  //finally, transfer the value to our internal data
127  mpz_set_f(input.data, tempFloat);
128 
129  //gmp_printf ("%Zd\r\n", this->data);
130 
131  //don't forget to clean up the memory
132  mpf_clear(tempFloat);
133  mpf_clear(tempScaling);
134  mpf_clear(zeroPointFive);
135  }
136 
147  void BigIntegerGmp::Initialize (BigIntegerBase<BigIntegerGmp> &input, const double value, const unsigned int numberOfDigits, const bool truncate) {
148  mpz_init(input.data);
149 
150  mpf_set_default_prec(1024);//1024 is the default value and it should be more than enough
151 
152  //auxiliary big float used for applying scaling and rounding before exporting it to input.data
153  mpf_t tempFloat;
154  //we can't multiply mpf_t with mpz_t, so we need a temporary mpf_t for the scaling
155  mpf_t tempScaling;
156  //contains the value 0.5, used for the rounding procedure
157  mpf_t zeroPointFive;
158 
159  //set the value
160  mpf_init_set_d(tempFloat, value);
161 
162  //gmp_printf ("Value: %.*Ff\r\n", 30, tempFloat);
163 
164  //set the scaling
165  if (numberOfDigits > 0) {
166  mpf_init_set_si(tempScaling, 10);
167  mpf_pow_ui(tempScaling, tempScaling, numberOfDigits);
168  }
169  else {
170  mpf_init_set_si(tempScaling, 1);
171  }
172 
173  //set 0.5
174  mpf_init_set_d(zeroPointFive, 0.5);
175 
176  //apply the scaling
177  mpf_mul(tempFloat, tempFloat, tempScaling);
178 
179  if (truncate) {
180  //discard decimals
181  mpf_trunc(tempFloat, tempFloat);
182  }
183  else {
184  //round the value to the nearest (positive or negative) integer
185  //input < 0.0 ? ceil(input - 0.5) : floor(input + 0.5));
186  if (-1 == mpf_sgn(tempFloat)) {
187  mpf_sub(tempFloat, tempFloat, zeroPointFive);
188  mpf_ceil(tempFloat, tempFloat);
189  }
190  else {
191  mpf_add(tempFloat, tempFloat, zeroPointFive);
192  mpf_floor(tempFloat, tempFloat);
193  }
194  }
195 
196  //gmp_printf ("Value: %.*Ff\r\n", 30, tempFloat);
197 
198  //finally, transfer the value to our internal data
199  mpz_set_f(input.data, tempFloat);
200 
201  //gmp_printf ("%Zd\r\n", this->data);
202 
203  //don't forget to clean up the memory
204  mpf_clear(tempFloat);
205  mpf_clear(tempScaling);
206  mpf_clear(zeroPointFive);
207  }
208 
232  void BigIntegerGmp::Initialize (BigIntegerBase<BigIntegerGmp> &input, const std::string &value, const int base) {
233  if (0 != mpz_init_set_str(input.data, value.c_str(), base)) {
234  throw std::runtime_error("The input string is not a valid number in the specified base.");
235  }
236  }
237 
242  mpz_clear(input.data);
243  }
244 
250  mpz_set(input.data, value.data);
251  }
252 
257  void BigIntegerGmp::Set (BigIntegerBase<BigIntegerGmp> &input, const long value) {
258  mpz_set_si(input.data, value);
259  }
260 
265  void BigIntegerGmp::Set (BigIntegerBase<BigIntegerGmp> &input, const unsigned long value) {
266  mpz_set_ui(input.data, value);
267  }
268 
274  mpz_neg(output.data, input.data);
275  }
276 
283  mpz_add(output.data, lhs.data, rhs.data);
284  }
285 
292  if (rhs < 0) {
293  mpz_sub_ui(output.data, lhs.data, -rhs);
294  }
295  else {
296  mpz_add_ui(output.data, lhs.data, rhs);
297  }
298  }
299 
305  void BigIntegerGmp::Add (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &lhs, const unsigned long rhs) {
306  mpz_add_ui(output.data, lhs.data, rhs);
307  }
308 
315  mpz_sub(output.data, lhs.data, rhs.data);
316  }
317 
324  if (rhs < 0) {
325  mpz_add_ui(output.data, lhs.data, -rhs);
326  }
327  else {
328  mpz_sub_ui(output.data, lhs.data, rhs);
329  }
330  }
331 
337  void BigIntegerGmp::Subtract (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &lhs, const unsigned long rhs) {
338  mpz_sub_ui(output.data, lhs.data, rhs);
339  }
340 
347  mpz_mul(output.data, lhs.data, rhs.data);
348  }
349 
356  mpz_mul_si(output.data, lhs.data, rhs);
357  }
358 
364  void BigIntegerGmp::Multiply (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &lhs, const unsigned long rhs) {
365  mpz_mul_ui(output.data, lhs.data, rhs);
366  }
367 
376  mpz_tdiv_q(output.data, lhs.data, rhs.data);
377  }
378 
387  if (rhs < 0) {
388  mpz_tdiv_q_ui(output.data, lhs.data, -rhs);
389  mpz_neg(output.data, output.data);
390  }
391  else {
392  mpz_tdiv_q_ui(output.data, lhs.data, rhs);
393  }
394  }
395 
403  void BigIntegerGmp::Divide (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &lhs, const unsigned long rhs) {
404  mpz_tdiv_q_ui(output.data, lhs.data, rhs);
405  }
406 
418  mpz_mod(output.data, lhs.data, rhs.data);
419  }
420 
432  if (rhs < 0) {
433  mpz_mod_ui(output.data, lhs.data, -rhs);
434  mpz_neg(output.data, output.data);
435  }
436  else {
437  mpz_mod_ui(output.data, lhs.data, rhs);
438  }
439  }
440 
451  void BigIntegerGmp::Modulo (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &lhs, const unsigned long rhs) {
452  mpz_mod_ui(output.data, lhs.data, rhs);
453  }
454 
462  void BigIntegerGmp::RightShift (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &input, const unsigned long numberOfBits) {
463  mpz_tdiv_q_2exp(output.data, input.data, numberOfBits);
464  }
465 
471  void BigIntegerGmp::LeftShift (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &input, const unsigned long numberOfBits) {
472  mpz_mul_2exp(output.data, input.data, numberOfBits);
473  }
474 
481  return mpz_cmp(lhs.data, rhs.data);
482  }
483 
489  int BigIntegerGmp::Compare (const BigIntegerBase<BigIntegerGmp> &lhs, const long rhs) {
490  return mpz_cmp_si(lhs.data, rhs);
491  }
492 
498  int BigIntegerGmp::Compare (const BigIntegerBase<BigIntegerGmp> &lhs, const unsigned long rhs) {
499  return mpz_cmp_ui(lhs.data, rhs);
500  }
501 
507  mpz_com(output.data, input.data);
508  }
509 
516  mpz_and(output.data, lhs.data, rhs.data);
517  }
518 
525  mpz_ior(output.data, lhs.data, rhs.data);
526  }
527 
534  mpz_xor(output.data, lhs.data, rhs.data);
535  }
536 
549  mpz_nextprime(output.data, input.data);
550  }
551 
576  if (0 != mpz_probab_prime_p(input.data, MILLER_RABIN_PRIMALITY_TEST_COUNT)) {
577  return true;
578  }
579 
580  return false;
581  }
582 
587  void BigIntegerGmp::SetBit (BigIntegerBase<BigIntegerGmp> &input, const size_t index) {
588  mpz_setbit(input.data, index);
589  }
590 
598  int BigIntegerGmp::GetBit (const BigIntegerBase<BigIntegerGmp> &input, const size_t index) {
599  return mpz_tstbit(input.data, index);
600  }
601 
625  size_t BigIntegerGmp::GetSize (const BigIntegerBase<BigIntegerGmp> &input, const unsigned int base) {
626  return mpz_sizeinbase(input.data, base);
627  }
628 
635  mpz_abs(output.data, input.data);
636  }
637 
647  mpz_pow_ui(output.data, input.data, power.ToUnsignedLong());
648  }
649 
661  void BigIntegerGmp::Pow (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &input, const long power) {
662  if (power < 0) {
663  mpz_set_si(output.data, 0);
664  }
665  else {
666  mpz_pow_ui(output.data, input.data, power);
667  }
668  }
669 
679  void BigIntegerGmp::Pow (BigIntegerBase<BigIntegerGmp> &output, const BigIntegerBase<BigIntegerGmp> &input, const unsigned long power) {
680  mpz_pow_ui(output.data, input.data, power);
681  }
682 
703  mpz_powm(output.data, input.data, power.data, n.data);
704  }
705 
727  if (power < 0) {
728  BigIntegerGmp::PowModN (output, input, BigIntegerBase<BigIntegerGmp>(power), n);
729  }
730  else {
731  mpz_powm_ui(output.data, input.data, power, n.data);
732  }
733  }
734 
754  mpz_powm_ui(output.data, input.data, power, n.data);
755  }
756 
772  if (0 == mpz_invert(output.data, input.data, n.data)) {
773  throw std::runtime_error("Failed to compute inverse modulo n.");
774  }
775  }
776 
782  mpz_swap(lhs.data, rhs.data);
783  }
784 
799  mpz_gcd(output.data, lhs.data, rhs.data);
800  }
801 
815  mpz_lcm(output.data, lhs.data, rhs.data);
816  }
817 
842  std::string BigIntegerGmp::ToString (const BigIntegerBase<BigIntegerGmp> &input, const unsigned int base) {
843  //get a pointer to GMP's internal memory deallocator function
844  void (*deallocator)(void *, size_t);
845  mp_get_memory_functions(NULL, NULL, &deallocator);
846 
847  //get the string representation of input
848  char *data = mpz_get_str(NULL, base, input.data);
849 
850  std::string output(data);
851 
852  //deallocate data, including the terminator character
853  //calling std::free on the char * returned by mpz_get_str is dangerous, because it is initialized internally by GMP
854  (*deallocator)((void *)data, std::char_traits<char>::length(data) + 1);
855 
856  return output;
857  }
858 
871  //if (0 == mpz_fits_ulong_p(input.data))
872  //{
873  // throw std::runtime_error("The integer does not fit in an unsigned long.");
874  //}
875 
876  return mpz_get_ui(input.data);
877  }
878 
879 }//namespace Core
880 }//namespace SeComLib
static void Modulo(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input, const BigIntegerBase< BigIntegerGmp > &n)
Computes input mod n.
static void Lcm(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Computes the least common multiple of lhs and rhs.
static void LeftShift(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input, const unsigned long numberOfBits)
Bitwise left shift input by numberOfBits.
static void Gcd(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Computes the greatest common divisor of lhs and rhs.
static void Swap(BigIntegerBase< BigIntegerGmp > &lhs, BigIntegerBase< BigIntegerGmp > &rhs)
Swaps lhs with rhs efficiently.
unsigned long ToUnsignedLong() const
Convert to unsigned long.
static void InvertModN(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input, const BigIntegerBase< BigIntegerGmp > &n)
Inverts input modulo n.
static void Destroy(BigIntegerBase< BigIntegerGmp > &input)
Destroys the underlying data from input.
static int GetBit(const BigIntegerBase< BigIntegerGmp > &input, const size_t index)
Returns the bit specified by index.
static void Subtract(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Subtracts rhs from lhs.
static void Pow(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input, const BigIntegerBase< BigIntegerGmp > &power)
Raises input to the specified power.
static void Initialize(BigIntegerBase< BigIntegerGmp > &input)
Initializes the underlying data from input.
static void BitwiseXor(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Computes lhs bitwise exclusive OR rhs.
static void BitwiseOr(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Computes lhs bitwise inclusive OR rhs.
static void InvertSign(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input)
Inverts the sign of input.
static void RightShift(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input, const unsigned long numberOfBits)
Bitwise right shift input by numberOfBits.
static void Abs(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input)
Computes the absolute value of input.
static size_t GetSize(const BigIntegerBase< BigIntegerGmp > &input, const unsigned int base=2)
Gets the length of the integer in the specified base.
static bool IsPrime(const BigIntegerBase< BigIntegerGmp > &input)
Tests if input is a prime number.
static void InvertBits(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input)
Computes one's complement of input.
static void Add(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Adds lhs and rhs.
static std::string ToString(const BigIntegerBase< BigIntegerGmp > &input, const unsigned int base=2)
Convert input to std::string in the specified base.
static void PowModN(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input, const BigIntegerBase< BigIntegerGmp > &power, const BigIntegerBase< BigIntegerGmp > &n)
Raises input to the specified power modulo n.
#define MILLER_RABIN_PRIMALITY_TEST_COUNT
The number of Miller-Rabin probabilistic primality tests to execute before a number is considered pri...
static void Multiply(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Multiplies lhs with rhs.
static void Divide(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Divides lhs by rhs.
T_Impl::BigIntegerType data
Implementation-defined big integer variable.
Definition of class BigIntegerGmp.
static void Set(BigIntegerBase< BigIntegerGmp > &input, const BigIntegerBase< BigIntegerGmp > &value)
Sets input to the specified BigInteger value.
static void GetNextPrime(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &input)
Computes the first prime greater than the current instance.
static void BitwiseAnd(BigIntegerBase< BigIntegerGmp > &output, const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Computes lhs bitwise AND rhs.
Template class which adds syntactic sugar to big integer operations.
static unsigned long ToUnsignedLong(const BigIntegerBase< BigIntegerGmp > &input)
Convert input to unsigned long.
static int Compare(const BigIntegerBase< BigIntegerGmp > &lhs, const BigIntegerBase< BigIntegerGmp > &rhs)
Compares lhs to rhs.
static void SetBit(BigIntegerBase< BigIntegerGmp > &input, const size_t index)
Sets a bit in input at the specified index.