1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Aina Niemetz, Tim King, Gereon Kremer |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* A multiprecision integer constant; wraps a CLN multiprecision integer. |
14 |
|
*/ |
15 |
|
#include <sstream> |
16 |
|
#include <string> |
17 |
|
|
18 |
|
#include "base/cvc5config.h" |
19 |
|
#include "util/integer.h" |
20 |
|
|
21 |
|
#ifndef CVC5_CLN_IMP |
22 |
|
#error "This source should only ever be built if CVC5_CLN_IMP is on !" |
23 |
|
#endif /* CVC5_CLN_IMP */ |
24 |
|
|
25 |
|
#include "base/check.h" |
26 |
|
|
27 |
|
using namespace std; |
28 |
|
|
29 |
|
namespace cvc5 { |
30 |
|
|
31 |
|
signed int Integer::s_fastSignedIntMin = -(1 << 29); |
32 |
|
signed int Integer::s_fastSignedIntMax = (1 << 29) - 1; |
33 |
|
signed long Integer::s_slowSignedIntMin = |
34 |
|
(signed long)std::numeric_limits<signed int>::min(); |
35 |
|
signed long Integer::s_slowSignedIntMax = |
36 |
|
(signed long)std::numeric_limits<signed int>::max(); |
37 |
|
|
38 |
|
unsigned int Integer::s_fastUnsignedIntMax = (1 << 29) - 1; |
39 |
|
unsigned long Integer::s_slowUnsignedIntMax = |
40 |
|
(unsigned long)std::numeric_limits<unsigned int>::max(); |
41 |
|
|
42 |
|
unsigned long Integer::s_signedLongMin = |
43 |
|
std::numeric_limits<signed long>::min(); |
44 |
|
unsigned long Integer::s_signedLongMax = |
45 |
|
std::numeric_limits<signed long>::max(); |
46 |
|
unsigned long Integer::s_unsignedLongMax = |
47 |
|
std::numeric_limits<unsigned long>::max(); |
48 |
|
|
49 |
22909651 |
Integer& Integer::operator=(const Integer& x) |
50 |
|
{ |
51 |
22909651 |
if (this == &x) return *this; |
52 |
22909651 |
d_value = x.d_value; |
53 |
22909651 |
return *this; |
54 |
|
} |
55 |
|
|
56 |
220024278 |
bool Integer::operator==(const Integer& y) const |
57 |
|
{ |
58 |
220024278 |
return d_value == y.d_value; |
59 |
|
} |
60 |
|
|
61 |
639278 |
Integer Integer::operator-() const { return Integer(-(d_value)); } |
62 |
|
|
63 |
887599 |
bool Integer::operator!=(const Integer& y) const |
64 |
|
{ |
65 |
887599 |
return d_value != y.d_value; |
66 |
|
} |
67 |
|
|
68 |
921058 |
bool Integer::operator<(const Integer& y) const { return d_value < y.d_value; } |
69 |
|
|
70 |
180128 |
bool Integer::operator<=(const Integer& y) const |
71 |
|
{ |
72 |
180128 |
return d_value <= y.d_value; |
73 |
|
} |
74 |
|
|
75 |
457474 |
bool Integer::operator>(const Integer& y) const { return d_value > y.d_value; } |
76 |
|
|
77 |
682104 |
bool Integer::operator>=(const Integer& y) const |
78 |
|
{ |
79 |
682104 |
return d_value >= y.d_value; |
80 |
|
} |
81 |
|
|
82 |
2754224 |
Integer Integer::operator+(const Integer& y) const |
83 |
|
{ |
84 |
2754224 |
return Integer(d_value + y.d_value); |
85 |
|
} |
86 |
|
|
87 |
66256 |
Integer& Integer::operator+=(const Integer& y) |
88 |
|
{ |
89 |
66256 |
d_value += y.d_value; |
90 |
66256 |
return *this; |
91 |
|
} |
92 |
|
|
93 |
1353549 |
Integer Integer::operator-(const Integer& y) const |
94 |
|
{ |
95 |
1353549 |
return Integer(d_value - y.d_value); |
96 |
|
} |
97 |
|
|
98 |
9193 |
Integer& Integer::operator-=(const Integer& y) |
99 |
|
{ |
100 |
9193 |
d_value -= y.d_value; |
101 |
9193 |
return *this; |
102 |
|
} |
103 |
|
|
104 |
1298881 |
Integer Integer::operator*(const Integer& y) const |
105 |
|
{ |
106 |
1298881 |
return Integer(d_value * y.d_value); |
107 |
|
} |
108 |
|
|
109 |
9602 |
Integer& Integer::operator*=(const Integer& y) |
110 |
|
{ |
111 |
9602 |
d_value *= y.d_value; |
112 |
9602 |
return *this; |
113 |
|
} |
114 |
|
|
115 |
328503 |
Integer Integer::bitwiseOr(const Integer& y) const |
116 |
|
{ |
117 |
328503 |
return Integer(cln::logior(d_value, y.d_value)); |
118 |
|
} |
119 |
|
|
120 |
209879 |
Integer Integer::bitwiseAnd(const Integer& y) const |
121 |
|
{ |
122 |
209879 |
return Integer(cln::logand(d_value, y.d_value)); |
123 |
|
} |
124 |
|
|
125 |
583 |
Integer Integer::bitwiseXor(const Integer& y) const |
126 |
|
{ |
127 |
583 |
return Integer(cln::logxor(d_value, y.d_value)); |
128 |
|
} |
129 |
|
|
130 |
1157781 |
Integer Integer::bitwiseNot() const { return Integer(cln::lognot(d_value)); } |
131 |
|
|
132 |
1512402 |
Integer Integer::multiplyByPow2(uint32_t pow) const |
133 |
|
{ |
134 |
3024804 |
cln::cl_I ipow(pow); |
135 |
3024804 |
return Integer(d_value << ipow); |
136 |
|
} |
137 |
|
|
138 |
59547 |
bool Integer::isBitSet(uint32_t i) const |
139 |
|
{ |
140 |
59547 |
return !extractBitRange(1, i).isZero(); |
141 |
|
} |
142 |
|
|
143 |
1969 |
void Integer::setBit(uint32_t i, bool value) |
144 |
|
{ |
145 |
3938 |
cln::cl_I mask(1); |
146 |
1969 |
mask = mask << i; |
147 |
1969 |
if (value) |
148 |
|
{ |
149 |
1941 |
d_value = cln::logior(d_value, mask); |
150 |
|
} |
151 |
|
else |
152 |
|
{ |
153 |
28 |
mask = cln::lognot(mask); |
154 |
28 |
d_value = cln::logand(d_value, mask); |
155 |
|
} |
156 |
1969 |
} |
157 |
|
|
158 |
628198 |
Integer Integer::oneExtend(uint32_t size, uint32_t amount) const |
159 |
|
{ |
160 |
628198 |
DebugCheckArgument((*this) < Integer(1).multiplyByPow2(size), size); |
161 |
628198 |
cln::cl_byte range(amount, size); |
162 |
1256396 |
cln::cl_I allones = (cln::cl_I(1) << (size + amount)) - 1; // 2^size - 1 |
163 |
1256396 |
Integer temp(allones); |
164 |
|
|
165 |
1256396 |
return Integer(cln::deposit_field(allones, d_value, range)); |
166 |
|
} |
167 |
|
|
168 |
1984405 |
uint32_t Integer::toUnsignedInt() const { return cln::cl_I_to_uint(d_value); } |
169 |
|
|
170 |
1750520 |
Integer Integer::extractBitRange(uint32_t bitCount, uint32_t low) const |
171 |
|
{ |
172 |
1750520 |
cln::cl_byte range(bitCount, low); |
173 |
1750520 |
return Integer(cln::ldb(d_value, range)); |
174 |
|
} |
175 |
|
|
176 |
26599 |
Integer Integer::floorDivideQuotient(const Integer& y) const |
177 |
|
{ |
178 |
26599 |
return Integer(cln::floor1(d_value, y.d_value)); |
179 |
|
} |
180 |
|
|
181 |
28840 |
Integer Integer::floorDivideRemainder(const Integer& y) const |
182 |
|
{ |
183 |
28840 |
return Integer(cln::floor2(d_value, y.d_value).remainder); |
184 |
|
} |
185 |
|
|
186 |
4662 |
void Integer::floorQR(Integer& q, |
187 |
|
Integer& r, |
188 |
|
const Integer& x, |
189 |
|
const Integer& y) |
190 |
|
{ |
191 |
9324 |
cln::cl_I_div_t res = cln::floor2(x.d_value, y.d_value); |
192 |
4662 |
q.d_value = res.quotient; |
193 |
4662 |
r.d_value = res.remainder; |
194 |
4662 |
} |
195 |
|
|
196 |
|
Integer Integer::ceilingDivideQuotient(const Integer& y) const |
197 |
|
{ |
198 |
|
return Integer(cln::ceiling1(d_value, y.d_value)); |
199 |
|
} |
200 |
|
|
201 |
|
Integer Integer::ceilingDivideRemainder(const Integer& y) const |
202 |
|
{ |
203 |
|
return Integer(cln::ceiling2(d_value, y.d_value).remainder); |
204 |
|
} |
205 |
|
|
206 |
3508 |
void Integer::euclidianQR(Integer& q, |
207 |
|
Integer& r, |
208 |
|
const Integer& x, |
209 |
|
const Integer& y) |
210 |
|
{ |
211 |
|
// compute the floor and then fix the value up if needed. |
212 |
3508 |
floorQR(q, r, x, y); |
213 |
|
|
214 |
3508 |
if (r.strictlyNegative()) |
215 |
|
{ |
216 |
|
// if r < 0 |
217 |
|
// abs(r) < abs(y) |
218 |
|
// - abs(y) < r < 0, then 0 < r + abs(y) < abs(y) |
219 |
|
// n = y * q + r |
220 |
|
// n = y * q - abs(y) + r + abs(y) |
221 |
8 |
if (r.sgn() >= 0) |
222 |
|
{ |
223 |
|
// y = abs(y) |
224 |
|
// n = y * q - y + r + y |
225 |
|
// n = y * (q-1) + (r+y) |
226 |
|
q -= 1; |
227 |
|
r += y; |
228 |
|
} |
229 |
|
else |
230 |
|
{ |
231 |
|
// y = -abs(y) |
232 |
|
// n = y * q + y + r - y |
233 |
|
// n = y * (q+1) + (r-y) |
234 |
8 |
q += 1; |
235 |
8 |
r -= y; |
236 |
|
} |
237 |
|
} |
238 |
3508 |
} |
239 |
|
|
240 |
684 |
Integer Integer::euclidianDivideQuotient(const Integer& y) const |
241 |
|
{ |
242 |
1368 |
Integer q, r; |
243 |
684 |
euclidianQR(q, r, *this, y); |
244 |
1368 |
return q; |
245 |
|
} |
246 |
|
|
247 |
2808 |
Integer Integer::euclidianDivideRemainder(const Integer& y) const |
248 |
|
{ |
249 |
5616 |
Integer q, r; |
250 |
2808 |
euclidianQR(q, r, *this, y); |
251 |
5616 |
return r; |
252 |
|
} |
253 |
|
|
254 |
|
Integer Integer::exactQuotient(const Integer& y) const |
255 |
|
{ |
256 |
|
DebugCheckArgument(y.divides(*this), y); |
257 |
|
return Integer(cln::exquo(d_value, y.d_value)); |
258 |
|
} |
259 |
|
|
260 |
11903525 |
Integer Integer::modByPow2(uint32_t exp) const |
261 |
|
{ |
262 |
11903525 |
cln::cl_byte range(exp, 0); |
263 |
11903525 |
return Integer(cln::ldb(d_value, range)); |
264 |
|
} |
265 |
|
|
266 |
7436 |
Integer Integer::divByPow2(uint32_t exp) const { return d_value >> exp; } |
267 |
|
|
268 |
26652 |
Integer Integer::pow(unsigned long int exp) const |
269 |
|
{ |
270 |
26652 |
if (exp == 0) |
271 |
|
{ |
272 |
174 |
return Integer(1); |
273 |
|
} |
274 |
|
else |
275 |
|
{ |
276 |
26478 |
Assert(exp > 0); |
277 |
52956 |
cln::cl_I result = cln::expt_pos(d_value, exp); |
278 |
26478 |
return Integer(result); |
279 |
|
} |
280 |
|
} |
281 |
|
|
282 |
3774768 |
Integer Integer::gcd(const Integer& y) const |
283 |
|
{ |
284 |
7549536 |
cln::cl_I result = cln::gcd(d_value, y.d_value); |
285 |
7549536 |
return Integer(result); |
286 |
|
} |
287 |
|
|
288 |
15145738 |
Integer Integer::lcm(const Integer& y) const |
289 |
|
{ |
290 |
30291476 |
cln::cl_I result = cln::lcm(d_value, y.d_value); |
291 |
30291476 |
return Integer(result); |
292 |
|
} |
293 |
|
|
294 |
2564 |
Integer Integer::modAdd(const Integer& y, const Integer& m) const |
295 |
|
{ |
296 |
5128 |
cln::cl_modint_ring ry = cln::find_modint_ring(m.d_value); |
297 |
5128 |
cln::cl_MI xm = ry->canonhom(d_value); |
298 |
5128 |
cln::cl_MI ym = ry->canonhom(y.d_value); |
299 |
5128 |
cln::cl_MI res = xm + ym; |
300 |
5128 |
return Integer(ry->retract(res)); |
301 |
|
} |
302 |
|
|
303 |
2558 |
Integer Integer::modMultiply(const Integer& y, const Integer& m) const |
304 |
|
{ |
305 |
5116 |
cln::cl_modint_ring ry = cln::find_modint_ring(m.d_value); |
306 |
5116 |
cln::cl_MI xm = ry->canonhom(d_value); |
307 |
5116 |
cln::cl_MI ym = ry->canonhom(y.d_value); |
308 |
5116 |
cln::cl_MI res = xm * ym; |
309 |
5116 |
return Integer(ry->retract(res)); |
310 |
|
} |
311 |
|
|
312 |
466 |
Integer Integer::modInverse(const Integer& m) const |
313 |
|
{ |
314 |
466 |
PrettyCheckArgument(m > 0, m, "m must be greater than zero"); |
315 |
932 |
cln::cl_modint_ring ry = cln::find_modint_ring(m.d_value); |
316 |
932 |
cln::cl_MI xm = ry->canonhom(d_value); |
317 |
|
/* normalize to modulo m for coprime check */ |
318 |
932 |
cln::cl_I x = ry->retract(xm); |
319 |
466 |
if (x == 0 || cln::gcd(x, m.d_value) != 1) |
320 |
|
{ |
321 |
26 |
return Integer(-1); |
322 |
|
} |
323 |
880 |
cln::cl_MI res = cln::recip(xm); |
324 |
440 |
return Integer(ry->retract(res)); |
325 |
|
} |
326 |
|
|
327 |
55136 |
bool Integer::divides(const Integer& y) const |
328 |
|
{ |
329 |
110272 |
cln::cl_I result = cln::rem(y.d_value, d_value); |
330 |
110272 |
return cln::zerop(result); |
331 |
|
} |
332 |
|
|
333 |
8326429 |
Integer Integer::abs() const { return d_value >= 0 ? *this : -*this; } |
334 |
|
|
335 |
4403 |
std::string Integer::toString(int base) const |
336 |
|
{ |
337 |
8806 |
std::stringstream ss; |
338 |
4403 |
switch (base) |
339 |
|
{ |
340 |
242 |
case 2: fprintbinary(ss, d_value); break; |
341 |
|
case 8: fprintoctal(ss, d_value); break; |
342 |
4139 |
case 10: fprintdecimal(ss, d_value); break; |
343 |
22 |
case 16: fprinthexadecimal(ss, d_value); break; |
344 |
|
default: throw Exception("Unhandled base in Integer::toString()"); |
345 |
|
} |
346 |
4403 |
std::string output = ss.str(); |
347 |
24211 |
for (unsigned i = 0; i <= output.length(); ++i) |
348 |
|
{ |
349 |
19808 |
if (isalpha(output[i])) |
350 |
|
{ |
351 |
18 |
output.replace(i, 1, 1, tolower(output[i])); |
352 |
|
} |
353 |
|
} |
354 |
|
|
355 |
8806 |
return output; |
356 |
|
} |
357 |
|
|
358 |
2023445 |
int Integer::sgn() const |
359 |
|
{ |
360 |
4046890 |
cln::cl_I sgn = cln::signum(d_value); |
361 |
4046890 |
return cln::cl_I_to_int(sgn); |
362 |
|
} |
363 |
|
|
364 |
28 |
bool Integer::strictlyPositive() const { return cln::plusp(d_value); } |
365 |
|
|
366 |
99309 |
bool Integer::strictlyNegative() const { return cln::minusp(d_value); } |
367 |
|
|
368 |
59613 |
bool Integer::isZero() const { return cln::zerop(d_value); } |
369 |
|
|
370 |
22050377 |
bool Integer::isOne() const { return d_value == 1; } |
371 |
|
|
372 |
|
bool Integer::isNegativeOne() const { return d_value == -1; } |
373 |
|
|
374 |
221690 |
void Integer::parseInt(const std::string& s, unsigned base) |
375 |
|
{ |
376 |
|
cln::cl_read_flags flags; |
377 |
221690 |
flags.syntax = cln::syntax_integer; |
378 |
221690 |
flags.lsyntax = cln::lsyntax_standard; |
379 |
221690 |
flags.rational_base = base; |
380 |
221690 |
if (base == 0) |
381 |
|
{ |
382 |
|
// infer base in a manner consistent with GMP |
383 |
16 |
if (s[0] == '0') |
384 |
|
{ |
385 |
10 |
flags.lsyntax = cln::lsyntax_commonlisp; |
386 |
20 |
std::string st = s; |
387 |
10 |
if (s[1] == 'X' || s[1] == 'x') |
388 |
|
{ |
389 |
4 |
st.replace(0, 2, "#x"); |
390 |
|
} |
391 |
6 |
else if (s[1] == 'B' || s[1] == 'b') |
392 |
|
{ |
393 |
4 |
st.replace(0, 2, "#b"); |
394 |
|
} |
395 |
|
else |
396 |
|
{ |
397 |
2 |
st.replace(0, 1, "#o"); |
398 |
|
} |
399 |
10 |
readInt(flags, st, base); |
400 |
8 |
return; |
401 |
|
} |
402 |
|
else |
403 |
|
{ |
404 |
6 |
flags.rational_base = 10; |
405 |
|
} |
406 |
|
} |
407 |
221680 |
readInt(flags, s, base); |
408 |
|
} |
409 |
|
|
410 |
221690 |
void Integer::readInt(const cln::cl_read_flags& flags, |
411 |
|
const std::string& s, |
412 |
|
unsigned base) |
413 |
|
{ |
414 |
|
try |
415 |
|
{ |
416 |
|
// Removing leading zeroes, CLN has a bug for these inputs up to and |
417 |
|
// including CLN v1.3.2. |
418 |
|
// See |
419 |
|
// http://www.ginac.de/CLN/cln.git/?a=commit;h=4a477b0cc3dd7fbfb23b25090ff8c8869c8fa21a |
420 |
|
// for details. |
421 |
221690 |
size_t pos = s.find_first_not_of('0'); |
422 |
221690 |
if (pos == std::string::npos) |
423 |
|
{ |
424 |
45855 |
d_value = cln::read_integer(flags, "0", NULL, NULL); |
425 |
|
} |
426 |
|
else |
427 |
|
{ |
428 |
175835 |
const char* cstr = s.c_str(); |
429 |
175835 |
const char* start = cstr + pos; |
430 |
175835 |
const char* end = cstr + s.length(); |
431 |
175835 |
d_value = cln::read_integer(flags, start, end, NULL); |
432 |
|
} |
433 |
|
} |
434 |
188 |
catch (...) |
435 |
|
{ |
436 |
188 |
std::stringstream ss; |
437 |
94 |
ss << "Integer() failed to parse value \"" << s << "\" in base " << base; |
438 |
94 |
throw std::invalid_argument(ss.str()); |
439 |
|
} |
440 |
221596 |
} |
441 |
|
|
442 |
48 |
bool Integer::fitsSignedInt() const |
443 |
|
{ |
444 |
|
// http://www.ginac.de/CLN/cln.html#Conversions |
445 |
|
// TODO improve performance |
446 |
48 |
Assert(s_slowSignedIntMin <= s_fastSignedIntMin); |
447 |
48 |
Assert(s_fastSignedIntMin <= s_fastSignedIntMax); |
448 |
48 |
Assert(s_fastSignedIntMax <= s_slowSignedIntMax); |
449 |
|
|
450 |
144 |
return (d_value <= s_fastSignedIntMax || d_value <= s_slowSignedIntMax) |
451 |
240 |
&& (d_value >= s_fastSignedIntMin || d_value >= s_slowSignedIntMax); |
452 |
|
} |
453 |
|
|
454 |
1745625 |
bool Integer::fitsUnsignedInt() const |
455 |
|
{ |
456 |
|
// TODO improve performance |
457 |
1745625 |
Assert(s_fastUnsignedIntMax <= s_slowUnsignedIntMax); |
458 |
1745625 |
return sgn() >= 0 |
459 |
6982500 |
&& (d_value <= s_fastUnsignedIntMax |
460 |
3491252 |
|| d_value <= s_slowUnsignedIntMax); |
461 |
|
} |
462 |
|
|
463 |
48 |
signed int Integer::getSignedInt() const |
464 |
|
{ |
465 |
|
// ensure there isn't overflow |
466 |
96 |
CheckArgument( |
467 |
48 |
fitsSignedInt(), this, "Overflow detected in Integer::getSignedInt()"); |
468 |
48 |
return cln::cl_I_to_int(d_value); |
469 |
|
} |
470 |
|
|
471 |
13080 |
unsigned int Integer::getUnsignedInt() const |
472 |
|
{ |
473 |
|
// ensure there isn't overflow |
474 |
13080 |
CheckArgument(fitsUnsignedInt(), |
475 |
|
this, |
476 |
|
"Overflow detected in Integer::getUnsignedInt()"); |
477 |
13080 |
return cln::cl_I_to_uint(d_value); |
478 |
|
} |
479 |
|
|
480 |
|
bool Integer::fitsSignedLong() const |
481 |
|
{ |
482 |
|
return d_value <= s_signedLongMax && d_value >= s_signedLongMin; |
483 |
|
} |
484 |
|
|
485 |
|
bool Integer::fitsUnsignedLong() const |
486 |
|
{ |
487 |
|
return sgn() >= 0 && d_value <= s_unsignedLongMax; |
488 |
|
} |
489 |
|
|
490 |
2129 |
long Integer::getLong() const |
491 |
|
{ |
492 |
|
// ensure there isn't overflow |
493 |
2131 |
CheckArgument(d_value <= std::numeric_limits<long>::max(), |
494 |
|
this, |
495 |
|
"Overflow detected in Integer::getLong()"); |
496 |
2127 |
CheckArgument(d_value >= std::numeric_limits<long>::min(), |
497 |
|
this, |
498 |
|
"Overflow detected in Integer::getLong()"); |
499 |
2127 |
return cln::cl_I_to_long(d_value); |
500 |
|
} |
501 |
|
|
502 |
400 |
unsigned long Integer::getUnsignedLong() const |
503 |
|
{ |
504 |
|
// ensure there isn't overflow |
505 |
402 |
CheckArgument(d_value <= std::numeric_limits<unsigned long>::max(), |
506 |
|
this, |
507 |
|
"Overflow detected in Integer::getUnsignedLong()"); |
508 |
398 |
CheckArgument(d_value >= std::numeric_limits<unsigned long>::min(), |
509 |
|
this, |
510 |
|
"Overflow detected in Integer::getUnsignedLong()"); |
511 |
398 |
return cln::cl_I_to_ulong(d_value); |
512 |
|
} |
513 |
|
|
514 |
3042913 |
size_t Integer::hash() const { return equal_hashcode(d_value); } |
515 |
|
|
516 |
94 |
bool Integer::testBit(unsigned n) const { return cln::logbitp(n, d_value); } |
517 |
|
|
518 |
406773 |
unsigned Integer::isPow2() const |
519 |
|
{ |
520 |
406773 |
if (d_value <= 0) return 0; |
521 |
|
// power2p returns n such that d_value = 2^(n-1) |
522 |
396041 |
return cln::power2p(d_value); |
523 |
|
} |
524 |
|
|
525 |
275530 |
size_t Integer::length() const |
526 |
|
{ |
527 |
275530 |
int s = sgn(); |
528 |
275530 |
if (s == 0) |
529 |
|
{ |
530 |
39441 |
return 1; |
531 |
|
} |
532 |
236089 |
else if (s < 0) |
533 |
|
{ |
534 |
100925 |
size_t len = cln::integer_length(d_value); |
535 |
|
/*If this is -2^n, return len+1 not len to stay consistent with the |
536 |
|
* definition above! From CLN's documentation of integer_length: This is |
537 |
|
* the smallest n >= 0 such that -2^n <= x < 2^n. If x > 0, this is the |
538 |
|
* unique n > 0 such that 2^(n-1) <= x < 2^n. |
539 |
|
*/ |
540 |
100925 |
size_t ord2 = cln::ord2(d_value); |
541 |
100925 |
return (len == ord2) ? (len + 1) : len; |
542 |
|
} |
543 |
|
else |
544 |
|
{ |
545 |
135164 |
return cln::integer_length(d_value); |
546 |
|
} |
547 |
|
} |
548 |
|
|
549 |
46 |
void Integer::extendedGcd( |
550 |
|
Integer& g, Integer& s, Integer& t, const Integer& a, const Integer& b) |
551 |
|
{ |
552 |
46 |
g.d_value = cln::xgcd(a.d_value, b.d_value, &s.d_value, &t.d_value); |
553 |
46 |
} |
554 |
|
|
555 |
|
const Integer& Integer::min(const Integer& a, const Integer& b) |
556 |
|
{ |
557 |
|
return (a <= b) ? a : b; |
558 |
|
} |
559 |
|
|
560 |
|
const Integer& Integer::max(const Integer& a, const Integer& b) |
561 |
|
{ |
562 |
|
return (a >= b) ? a : b; |
563 |
|
} |
564 |
|
|
565 |
3415 |
std::ostream& operator<<(std::ostream& os, const Integer& n) |
566 |
|
{ |
567 |
3415 |
return os << n.toString(); |
568 |
|
} |
569 |
29340 |
} // namespace cvc5 |