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 *****************************************************************************/
19 template<mp_size_t n> bigint<n>::bigint(const unsigned long x)
21 assert(8 * sizeof(x) <= GMP_NUMB_BITS);
25 template<mp_size_t n> bigint<n>::bigint(const char *s)
28 unsigned char *s_copy = new unsigned char[l];
30 for (size_t i = 0; i < l; ++i) {
31 assert(s[i] >= '0' && s[i] <= '9');
32 s_copy[i] = s[i] - '0';
35 mp_size_t limbs_written = mpn_set_str(this->data, s_copy, l, 10);
36 assert(limbs_written <= n);
37 UNUSED(limbs_written);
42 template<mp_size_t n> bigint<n>::bigint(const mpz_t r)
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);
52 assert(mpz_sgn(k) == 0);
56 template<mp_size_t n> void bigint<n>::print() const
58 gmp_printf("%Nd\n", this->data, n);
61 template<mp_size_t n> void bigint<n>::print_hex() const
63 gmp_printf("%Nx\n", this->data, n);
66 template<mp_size_t n> bool bigint<n>::operator==(const bigint<n> &other) const
68 return (mpn_cmp(this->data, other.data, n) == 0);
71 template<mp_size_t n> bool bigint<n>::operator!=(const bigint<n> &other) const
73 return !(operator==(other));
76 template<mp_size_t n> void bigint<n>::clear() { mpn_zero(this->data, n); }
78 template<mp_size_t n> bool bigint<n>::is_zero() const
80 for (size_t i = 0; i < n; ++i) {
89 template<mp_size_t n> size_t bigint<n>::num_bits() const
92 for (long i = max_bits(); i >= 0; --i) {
93 if (this->test_bit(i)) {
100 for (long i = n - 1; i >= 0; --i) {
101 mp_limb_t x = this->data[i];
105 return ((i + 1) * GMP_NUMB_BITS) - __builtin_clzl(x);
111 template<mp_size_t n> unsigned long bigint<n>::as_ulong() const
113 return this->data[0];
116 template<mp_size_t n> void bigint<n>::to_mpz(mpz_t r) const
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]);
126 template<mp_size_t n> bool bigint<n>::test_bit(const std::size_t bitno) const
128 if (bitno >= n * GMP_NUMB_BITS) {
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;
138 template<mp_size_t n> bigint<n> &bigint<n>::randomize()
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);
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();
154 template<mp_size_t n>
155 std::ostream &operator<<(std::ostream &out, const bigint<n> &b)
158 out.write((char *)b.data, sizeof(b.data[0]) * n);
171 template<mp_size_t n> std::istream &operator>>(std::istream &in, bigint<n> &b)
174 in.read((char *)b.data, sizeof(b.data[0]) * n);
180 unsigned char *s_copy = new unsigned char[l];
182 for (size_t i = 0; i < l; ++i) {
183 assert(s[i] >= '0' && s[i] <= '9');
184 s_copy[i] = s[i] - '0';
187 mp_size_t limbs_written = mpn_set_str(b.data, s_copy, l, 10);
188 assert(limbs_written <= n);
189 UNUSED(limbs_written);
197 #endif // BIGINT_TCC_