The bliss C++ API
bignum.hh
1 #pragma once
2 
3 /*
4  Copyright (c) 2003-2021 Tommi Junttila
5  Released under the GNU Lesser General Public License version 3.
6 
7  This file is part of bliss.
8 
9  bliss is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, version 3 of the License.
12 
13  bliss is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License
19  along with bliss. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #if defined(BLISS_USE_GMP)
23 #include <gmp.h>
24 #else
25 #include <vector>
26 #include <string>
27 #endif
28 
29 #include <cstdlib>
30 #include <cstdio>
31 #include "defs.hh"
32 
33 
34 namespace bliss {
35 
48 #if defined(BLISS_USE_GMP)
49 
50 class BigNum
51 {
52  mpz_t v;
53 public:
57  BigNum() {mpz_init(v); }
58 
62  ~BigNum() {mpz_clear(v); }
63 
67  void assign(unsigned int n) {mpz_set_ui(v, n); }
68 
72  void multiply(unsigned int n) {mpz_mul_ui(v, v, n); }
73 
77  size_t print(FILE* const fp) const {return mpz_out_str(fp, 10, v); }
78 
84  void get(mpz_t& result) const {mpz_set(result, v); }
85 };
86 
87 #elif defined(BLISS_BIGNUM_APPROX)
88 
89 class BigNum
90 {
91  long double v;
92 public:
96  BigNum(): v(0.0) {}
97 
101  void assign(unsigned int n) {v = (long double)n; }
102 
106  void multiply(unsigned int n) {v *= (long double)n; }
107 
111  size_t print(FILE* const fp) const {return fprintf(fp, "%Lg", v); }
112 };
113 
114 #else
115 
116 
117 class BigNum
118 {
119  /* This is a version that does not actually compute the number
120  * but rather only stores the factor integers.
121  */
122  std::vector<unsigned int> factors;
123 public:
127  BigNum() {
128  factors.push_back(0);
129  }
130 
134  ~BigNum() {}
135 
139  void assign(unsigned int n) {
140  factors.clear();
141  factors.push_back(n);
142  }
143 
147  void multiply(unsigned int n) {
148  factors.push_back(n);
149  }
150 
156  size_t print(FILE* const fp) const {
157  assert(not factors.empty());
158  size_t r = 0;
159  /*
160  const char* sep = "";
161  for(int v: factors) {
162  r += fprintf(fp, "%s%d", sep, v);
163  sep = "*";
164  }
165  */
166  for(char d: to_string())
167  r += fprintf(fp, "%c", d);
168  return r;
169  }
170 
174  const std::vector<unsigned int>& get_factors() const {
175  return factors;
176  }
177 
182  std::string to_string() const {
183  // Base 100 result, in reverse order
184  std::vector<unsigned int> result;
185  result.push_back(1);
186  for(unsigned int factor: factors) {
187  std::vector<unsigned int> summand;
188  unsigned int offset = 0;
189  while(factor != 0) {
190  const unsigned int multiplier = factor % 100;
191  // Multiplication by a "digit"
192  std::vector<unsigned int> product;
193  for(unsigned int i = 0; i < offset; i++)
194  product.push_back(0);
195  unsigned int carry = 0;
196  for(unsigned int digit: result) {
197  unsigned int v = digit * multiplier + carry;
198  product.push_back(v % 100);
199  carry = v / 100;
200  }
201  if(carry > 0)
202  product.push_back(carry);
203  // Addition
204  add(summand, product);
205  // Next "digit" in factor
206  factor = factor / 100;
207  offset++;
208  }
209  result = summand;
210  }
211  return _string(result);
212  }
213 
214 protected:
215  static void add(std::vector<unsigned int>& num, const std::vector<unsigned int>& summand) {
216  unsigned int carry = 0;
217  unsigned int i = 0;
218  while(i < num.size() and i < summand.size()) {
219  const unsigned int v = carry + num[i] + summand[i];
220  num[i] = v % 100;
221  carry = v / 100;
222  i++;
223  }
224  while(i < summand.size()) {
225  const unsigned int v = carry + summand[i];
226  num.push_back(v % 100);
227  carry = v / 100;
228  i++;
229  }
230  while(i < num.size()) {
231  const unsigned int v = carry + num[i];
232  num[i] = v % 100;
233  carry = v / 100;
234  i++;
235  }
236  if(carry != 0)
237  num.push_back(carry);
238  }
239 
240 
241  static std::string _string(const std::vector<unsigned int> n) {
242  const char digits[] = {'0','1','2','3','4','5','6','7','8','9'};
243  std::string r;
244  bool first = true;
245  for(auto it = n.crbegin(); it != n.crend(); it++) {
246  unsigned int digit = *it;
247  unsigned int high = digit / 10;
248  if(not first or high > 0)
249  r.push_back(digits[high]);
250  first = false;
251  r.push_back(digits[digit % 10]);
252  }
253  return r;
254  }
255 
256 };
257 
258 #endif
259 
260 } //namespace bliss
A simple wrapper class for non-negative big integers (or approximation of them).
Definition: bignum.hh:117
Definition: abstractgraph.cc:35
void assign(unsigned int n)
Definition: bignum.hh:139
void multiply(unsigned int n)
Definition: bignum.hh:147
~BigNum()
Definition: bignum.hh:134
BigNum()
Definition: bignum.hh:127
size_t print(FILE *const fp) const
Definition: bignum.hh:156
Some common definitions.
const std::vector< unsigned int > & get_factors() const
Definition: bignum.hh:174
std::string to_string() const
Definition: bignum.hh:182