The bliss C++ API 0.77 (Debian 0.77-3)
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 <bliss/defs.hh>
32
33
34namespace bliss {
35
48#if defined(BLISS_USE_GMP)
49
50class BigNum
51{
52 mpz_t v;
53public:
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
89class BigNum
90{
91 long double v;
92public:
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
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;
123public:
128 factors.push_back(0);
129 }
130
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
214protected:
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:118
std::string to_string() const
Definition: bignum.hh:182
~BigNum()
Definition: bignum.hh:134
BigNum()
Definition: bignum.hh:127
const std::vector< unsigned int > & get_factors() const
Definition: bignum.hh:174
void assign(unsigned int n)
Definition: bignum.hh:139
void multiply(unsigned int n)
Definition: bignum.hh:147
size_t print(FILE *const fp) const
Definition: bignum.hh:156
Definition: abstractgraph.cc:35