Clearmatics Libff  0.1
C++ library for Finite Fields and Elliptic Curves
bigint.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3  Implementation of bigint wrapper class around GMP's MPZ long integers.
4  *****************************************************************************
5  * @author This file is part of libff, developed by SCIPR Lab
6  * and contributors (see AUTHORS).
7  * @copyright MIT license (see LICENSE file)
8  *****************************************************************************/
9 
10 #ifndef BIGINT_TCC_
11 #define BIGINT_TCC_
12 #include <cassert>
13 #include <cstring>
14 #include <random>
15 
16 namespace libff
17 {
18 
19 template<mp_size_t n> bigint<n>::bigint(const unsigned long x)
20 {
21  assert(8 * sizeof(x) <= GMP_NUMB_BITS);
22  this->data[0] = x;
23 }
24 
25 template<mp_size_t n> bigint<n>::bigint(const char *s)
26 {
27  size_t l = strlen(s);
28  unsigned char *s_copy = new unsigned char[l];
29 
30  for (size_t i = 0; i < l; ++i) {
31  assert(s[i] >= '0' && s[i] <= '9');
32  s_copy[i] = s[i] - '0';
33  }
34 
35  mp_size_t limbs_written = mpn_set_str(this->data, s_copy, l, 10);
36  assert(limbs_written <= n);
37  UNUSED(limbs_written);
38 
39  delete[] s_copy;
40 }
41 
42 template<mp_size_t n> bigint<n>::bigint(const mpz_t r)
43 {
44  mpz_t k;
45  mpz_init_set(k, r);
46 
47  for (size_t i = 0; i < n; ++i) {
48  data[i] = mpz_get_ui(k);
49  mpz_fdiv_q_2exp(k, k, GMP_NUMB_BITS);
50  }
51 
52  assert(mpz_sgn(k) == 0);
53  mpz_clear(k);
54 }
55 
56 template<mp_size_t n> void bigint<n>::print() const
57 {
58  gmp_printf("%Nd\n", this->data, n);
59 }
60 
61 template<mp_size_t n> void bigint<n>::print_hex() const
62 {
63  gmp_printf("%Nx\n", this->data, n);
64 }
65 
66 template<mp_size_t n> bool bigint<n>::operator==(const bigint<n> &other) const
67 {
68  return (mpn_cmp(this->data, other.data, n) == 0);
69 }
70 
71 template<mp_size_t n> bool bigint<n>::operator!=(const bigint<n> &other) const
72 {
73  return !(operator==(other));
74 }
75 
76 template<mp_size_t n> void bigint<n>::clear() { mpn_zero(this->data, n); }
77 
78 template<mp_size_t n> bool bigint<n>::is_zero() const
79 {
80  for (size_t i = 0; i < n; ++i) {
81  if (this->data[i]) {
82  return false;
83  }
84  }
85 
86  return true;
87 }
88 
89 template<mp_size_t n> size_t bigint<n>::num_bits() const
90 {
91  /*
92  for (long i = max_bits(); i >= 0; --i) {
93  if (this->test_bit(i)) {
94  return i+1;
95  }
96  }
97 
98  return 0;
99  */
100  for (long i = n - 1; i >= 0; --i) {
101  mp_limb_t x = this->data[i];
102  if (x == 0) {
103  continue;
104  } else {
105  return ((i + 1) * GMP_NUMB_BITS) - __builtin_clzl(x);
106  }
107  }
108  return 0;
109 }
110 
111 template<mp_size_t n> unsigned long bigint<n>::as_ulong() const
112 {
113  return this->data[0];
114 }
115 
116 template<mp_size_t n> void bigint<n>::to_mpz(mpz_t r) const
117 {
118  mpz_set_ui(r, 0);
119 
120  for (int i = n - 1; i >= 0; --i) {
121  mpz_mul_2exp(r, r, GMP_NUMB_BITS);
122  mpz_add_ui(r, r, this->data[i]);
123  }
124 }
125 
126 template<mp_size_t n> bool bigint<n>::test_bit(const std::size_t bitno) const
127 {
128  if (bitno >= n * GMP_NUMB_BITS) {
129  return false;
130  } else {
131  const std::size_t part = bitno / GMP_NUMB_BITS;
132  const std::size_t bit = bitno - (GMP_NUMB_BITS * part);
133  const mp_limb_t one = 1;
134  return (this->data[part] & (one << bit)) != 0;
135  }
136 }
137 
138 template<mp_size_t n> bigint<n> &bigint<n>::randomize()
139 {
140  static_assert(
141  GMP_NUMB_BITS == sizeof(mp_limb_t) * 8, "Wrong GMP_NUMB_BITS value");
142  std::random_device rd;
143  constexpr size_t num_random_words =
144  sizeof(mp_limb_t) * n / sizeof(std::random_device::result_type);
145  auto random_words =
146  reinterpret_cast<std::random_device::result_type *>(this->data);
147  for (size_t i = 0; i < num_random_words; ++i) {
148  random_words[i] = rd();
149  }
150 
151  return (*this);
152 }
153 
154 template<mp_size_t n>
155 std::ostream &operator<<(std::ostream &out, const bigint<n> &b)
156 {
157 #ifdef BINARY_OUTPUT
158  out.write((char *)b.data, sizeof(b.data[0]) * n);
159 #else
160  mpz_t t;
161  mpz_init(t);
162  b.to_mpz(t);
163 
164  out << t;
165 
166  mpz_clear(t);
167 #endif
168  return out;
169 }
170 
171 template<mp_size_t n> std::istream &operator>>(std::istream &in, bigint<n> &b)
172 {
173 #ifdef BINARY_OUTPUT
174  in.read((char *)b.data, sizeof(b.data[0]) * n);
175 #else
176  std::string s;
177  in >> s;
178 
179  size_t l = s.size();
180  unsigned char *s_copy = new unsigned char[l];
181 
182  for (size_t i = 0; i < l; ++i) {
183  assert(s[i] >= '0' && s[i] <= '9');
184  s_copy[i] = s[i] - '0';
185  }
186 
187  mp_size_t limbs_written = mpn_set_str(b.data, s_copy, l, 10);
188  assert(limbs_written <= n);
189  UNUSED(limbs_written);
190 
191  delete[] s_copy;
192 #endif
193  return in;
194 }
195 
196 } // namespace libff
197 #endif // BIGINT_TCC_