8
//===========================================================================
10
//===========================================================================
13
unsigned long gIntDefaultNumberOfBits = 256;
15
std::vector<char>& intString()
17
static std::vector<char> str;
22
//===========================================================================
24
//===========================================================================
25
struct GmpInt::GmpIntData
28
GmpIntData* nextFreeNode;
31
GmpIntData(): mRefCount(1), nextFreeNode(0) {}
34
class GmpInt::GmpIntDataContainer
36
std::deque<GmpInt::GmpIntData> mData;
37
GmpInt::GmpIntData* mFirstFreeNode;
38
GmpInt::GmpIntData* mConst_0;
41
GmpIntDataContainer(): mFirstFreeNode(0), mConst_0(0) {}
43
~GmpIntDataContainer()
45
for(size_t i = 0; i < mData.size(); ++i)
46
mpz_clear(mData[i].mInteger);
49
GmpInt::GmpIntData* allocateGmpIntData(unsigned long numberOfBits,
54
GmpInt::GmpIntData* node = mFirstFreeNode;
55
mFirstFreeNode = node->nextFreeNode;
56
if(initToZero) mpz_set_si(node->mInteger, 0);
61
mData.push_back(GmpInt::GmpIntData());
63
mpz_init2(mData.back().mInteger, numberOfBits);
65
mpz_init(mData.back().mInteger);
69
void releaseGmpIntData(GmpIntData* data)
71
if(--(data->mRefCount) == 0)
73
data->nextFreeNode = mFirstFreeNode;
74
mFirstFreeNode = data;
78
GmpInt::GmpIntData* const_0()
81
mConst_0 = allocateGmpIntData(gIntDefaultNumberOfBits, true);
87
GmpInt::GmpIntDataContainer& GmpInt::gmpIntDataContainer()
89
static GmpIntDataContainer container;
93
//===========================================================================
94
// Auxiliary functions
95
//===========================================================================
96
void GmpInt::setDefaultNumberOfBits(unsigned long value)
98
gIntDefaultNumberOfBits = value;
101
unsigned long GmpInt::getDefaultNumberOfBits()
103
return gIntDefaultNumberOfBits;
106
inline void GmpInt::copyIfShared()
108
if(mData->mRefCount > 1)
110
--(mData->mRefCount);
111
GmpIntData* oldData = mData;
112
mData = gmpIntDataContainer().allocateGmpIntData(0, false);
113
mpz_set(mData->mInteger, oldData->mInteger);
118
//===========================================================================
119
// Constructors, destructor, assignment
120
//===========================================================================
121
GmpInt::GmpInt(DummyType):
122
mData(gmpIntDataContainer().allocateGmpIntData(0, false))
127
mData = gmpIntDataContainer().const_0();
128
++(mData->mRefCount);
131
GmpInt::GmpInt(long value)
135
mData = gmpIntDataContainer().const_0();
136
++(mData->mRefCount);
140
mData = gmpIntDataContainer().allocateGmpIntData
141
(gIntDefaultNumberOfBits, false);
142
mpz_set_si(mData->mInteger, value);
146
GmpInt::GmpInt(unsigned long value)
150
mData = gmpIntDataContainer().const_0();
151
++(mData->mRefCount);
155
mData = gmpIntDataContainer().allocateGmpIntData
156
(gIntDefaultNumberOfBits, false);
157
mpz_set_ui(mData->mInteger, value);
161
GmpInt::GmpInt(int value)
165
mData = gmpIntDataContainer().const_0();
166
++(mData->mRefCount);
170
mData = gmpIntDataContainer().allocateGmpIntData
171
(gIntDefaultNumberOfBits, false);
172
mpz_set_si(mData->mInteger, value);
176
GmpInt::GmpInt(double value)
178
const double absValue = value >= 0.0 ? value : -value;
181
mData = gmpIntDataContainer().const_0();
182
++(mData->mRefCount);
186
mData = gmpIntDataContainer().allocateGmpIntData
187
(gIntDefaultNumberOfBits, false);
188
mpz_set_d(mData->mInteger, value);
192
GmpInt::GmpInt(long double value)
194
const long double absValue = value >= 0.0L ? value : -value;
197
mData = gmpIntDataContainer().const_0();
198
++(mData->mRefCount);
202
mData = gmpIntDataContainer().allocateGmpIntData
203
(gIntDefaultNumberOfBits, false);
204
mpz_set_d(mData->mInteger, double(value));
208
GmpInt::GmpInt(const GmpInt& rhs):
211
++(mData->mRefCount);
214
GmpInt& GmpInt::operator=(const GmpInt& rhs)
216
if(mData != rhs.mData)
218
gmpIntDataContainer().releaseGmpIntData(mData);
220
++(mData->mRefCount);
225
GmpInt& GmpInt::operator=(signed long value)
229
gmpIntDataContainer().releaseGmpIntData(mData);
230
mData = gmpIntDataContainer().const_0();
231
++(mData->mRefCount);
235
if(mData->mRefCount > 1)
237
--(mData->mRefCount);
238
mData = gmpIntDataContainer().allocateGmpIntData
239
(gIntDefaultNumberOfBits, false);
241
mpz_set_si(mData->mInteger, value);
248
gmpIntDataContainer().releaseGmpIntData(mData);
252
//===========================================================================
254
//===========================================================================
256
void GmpInt::get_raw_mpfr_data<mpz_t>(mpz_t& dest_mpz_t)
258
std::memcpy(&dest_mpz_t, mData->mInteger, sizeof(mpz_t));
261
const char* GmpInt::getAsString(int base) const
263
intString().resize(mpz_sizeinbase(mData->mInteger, base) + 2);
264
return mpz_get_str(&intString()[0], base, mData->mInteger);
267
long GmpInt::toInt() const
269
return mpz_get_si(mData->mInteger);
273
//===========================================================================
274
// Modifying operators
275
//===========================================================================
276
GmpInt& GmpInt::operator+=(const GmpInt& rhs)
279
mpz_add(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
283
GmpInt& GmpInt::operator+=(long value)
287
mpz_add_ui(mData->mInteger, mData->mInteger, value);
289
mpz_sub_ui(mData->mInteger, mData->mInteger, -value);
293
GmpInt& GmpInt::operator-=(const GmpInt& rhs)
296
mpz_sub(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
300
GmpInt& GmpInt::operator-=(long value)
304
mpz_sub_ui(mData->mInteger, mData->mInteger, value);
306
mpz_add_ui(mData->mInteger, mData->mInteger, -value);
310
GmpInt& GmpInt::operator*=(const GmpInt& rhs)
313
mpz_mul(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
317
GmpInt& GmpInt::operator*=(long value)
320
mpz_mul_si(mData->mInteger, mData->mInteger, value);
324
GmpInt& GmpInt::operator/=(const GmpInt& rhs)
327
mpz_tdiv_q(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
331
GmpInt& GmpInt::operator/=(long value)
335
mpz_tdiv_q_ui(mData->mInteger, mData->mInteger, value);
338
mpz_neg(mData->mInteger, mData->mInteger);
339
mpz_tdiv_q_ui(mData->mInteger, mData->mInteger, -value);
344
GmpInt& GmpInt::operator%=(const GmpInt& rhs)
350
mpz_mod(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
355
mpz_mod(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
360
GmpInt& GmpInt::operator%=(long value)
363
if(value < 0) value = -value;
367
mpz_mod_ui(mData->mInteger, mData->mInteger, value);
372
mpz_mod_ui(mData->mInteger, mData->mInteger, value);
377
GmpInt& GmpInt::operator<<=(unsigned long bits)
380
mpz_mul_2exp(mData->mInteger, mData->mInteger, bits);
384
GmpInt& GmpInt::operator>>=(unsigned long bits)
387
mpz_tdiv_q_2exp(mData->mInteger, mData->mInteger, bits);
392
//===========================================================================
393
// Modifying functions
394
//===========================================================================
395
void GmpInt::addProduct(const GmpInt& value1, const GmpInt& value2)
398
mpz_addmul(mData->mInteger, value1.mData->mInteger, value2.mData->mInteger);
401
void GmpInt::addProduct(const GmpInt& value1, unsigned long value2)
404
mpz_addmul_ui(mData->mInteger, value1.mData->mInteger, value2);
407
void GmpInt::subProduct(const GmpInt& value1, const GmpInt& value2)
410
mpz_submul(mData->mInteger, value1.mData->mInteger, value2.mData->mInteger);
413
void GmpInt::subProduct(const GmpInt& value1, unsigned long value2)
416
mpz_submul_ui(mData->mInteger, value1.mData->mInteger, value2);
419
void GmpInt::negate()
422
mpz_neg(mData->mInteger, mData->mInteger);
428
mpz_abs(mData->mInteger, mData->mInteger);
431
GmpInt GmpInt::abs(const GmpInt& value)
433
GmpInt retval(kNoInitialization);
434
mpz_abs(retval.mData->mInteger, value.mData->mInteger);
439
//===========================================================================
440
// Non-modifying operators
441
//===========================================================================
442
GmpInt GmpInt::operator+(const GmpInt& rhs) const
444
GmpInt retval(kNoInitialization);
445
mpz_add(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
449
GmpInt GmpInt::operator+(long value) const
451
GmpInt retval(kNoInitialization);
453
mpz_add_ui(retval.mData->mInteger, mData->mInteger, value);
455
mpz_sub_ui(retval.mData->mInteger, mData->mInteger, -value);
459
GmpInt GmpInt::operator-(const GmpInt& rhs) const
461
GmpInt retval(kNoInitialization);
462
mpz_sub(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
466
GmpInt GmpInt::operator-(long value) const
468
GmpInt retval(kNoInitialization);
470
mpz_sub_ui(retval.mData->mInteger, mData->mInteger, value);
472
mpz_add_ui(retval.mData->mInteger, mData->mInteger, -value);
476
GmpInt GmpInt::operator*(const GmpInt& rhs) const
478
GmpInt retval(kNoInitialization);
479
mpz_mul(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
483
GmpInt GmpInt::operator*(long value) const
485
GmpInt retval(kNoInitialization);
486
mpz_mul_si(retval.mData->mInteger, mData->mInteger, value);
490
GmpInt GmpInt::operator/(const GmpInt& rhs) const
492
GmpInt retval(kNoInitialization);
493
mpz_tdiv_q(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
497
GmpInt GmpInt::operator/(long value) const
499
GmpInt retval(kNoInitialization);
501
mpz_tdiv_q_ui(retval.mData->mInteger, mData->mInteger, value);
504
mpz_neg(retval.mData->mInteger, mData->mInteger);
505
mpz_tdiv_q_ui(retval.mData->mInteger, retval.mData->mInteger, -value);
510
GmpInt GmpInt::operator%(const GmpInt& rhs) const
512
GmpInt retval(kNoInitialization);
515
mpz_neg(retval.mData->mInteger, mData->mInteger);
516
mpz_mod(retval.mData->mInteger,
517
retval.mData->mInteger, rhs.mData->mInteger);
522
mpz_mod(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
527
GmpInt GmpInt::operator%(long value) const
529
GmpInt retval(kNoInitialization);
530
if(value < 0) value = -value;
533
mpz_neg(retval.mData->mInteger, mData->mInteger);
534
mpz_mod_ui(retval.mData->mInteger, retval.mData->mInteger, value);
539
mpz_mod_ui(retval.mData->mInteger, mData->mInteger, value);
544
GmpInt GmpInt::operator-() const
546
GmpInt retval(kNoInitialization);
547
mpz_neg(retval.mData->mInteger, mData->mInteger);
551
GmpInt GmpInt::operator<<(unsigned long bits) const
553
GmpInt retval(kNoInitialization);
554
mpz_mul_2exp(retval.mData->mInteger, mData->mInteger, bits);
558
GmpInt GmpInt::operator>>(unsigned long bits) const
560
GmpInt retval(kNoInitialization);
561
mpz_tdiv_q_2exp(retval.mData->mInteger, mData->mInteger, bits);
566
//===========================================================================
567
// Comparison operators
568
//===========================================================================
569
bool GmpInt::operator<(const GmpInt& rhs) const
571
return mpz_cmp(mData->mInteger, rhs.mData->mInteger) < 0;
574
bool GmpInt::operator<(long value) const
576
return mpz_cmp_si(mData->mInteger, value) < 0;
579
bool GmpInt::operator<=(const GmpInt& rhs) const
581
return mpz_cmp(mData->mInteger, rhs.mData->mInteger) <= 0;
584
bool GmpInt::operator<=(long value) const
586
return mpz_cmp_si(mData->mInteger, value) <= 0;
589
bool GmpInt::operator>(const GmpInt& rhs) const
591
return mpz_cmp(mData->mInteger, rhs.mData->mInteger) > 0;
594
bool GmpInt::operator>(long value) const
596
return mpz_cmp_si(mData->mInteger, value) > 0;
599
bool GmpInt::operator>=(const GmpInt& rhs) const
601
return mpz_cmp(mData->mInteger, rhs.mData->mInteger) >= 0;
604
bool GmpInt::operator>=(long value) const
606
return mpz_cmp_si(mData->mInteger, value) >= 0;
609
bool GmpInt::operator==(const GmpInt& rhs) const
611
return mpz_cmp(mData->mInteger, rhs.mData->mInteger) == 0;
614
bool GmpInt::operator==(long value) const
616
return mpz_cmp_si(mData->mInteger, value) == 0;
619
bool GmpInt::operator!=(const GmpInt& rhs) const
621
return mpz_cmp(mData->mInteger, rhs.mData->mInteger) != 0;
624
bool GmpInt::operator!=(long value) const
626
return mpz_cmp_si(mData->mInteger, value) != 0;
629
void GmpInt::parseValue(const char* value)
631
mpz_set_str(mData->mInteger, value, 10);
634
void GmpInt::parseValue(const char* value, char** endptr)
636
static std::vector<char> str;
638
unsigned startIndex = 0;
639
while(value[startIndex] && std::isspace(value[startIndex])) ++startIndex;
640
if(!value[startIndex]) { *endptr = const_cast<char*>(value); return; }
642
unsigned endIndex = startIndex;
643
if(value[endIndex] == '-') ++endIndex;
644
if(!std::isdigit(value[endIndex]))
645
{ *endptr = const_cast<char*>(value); return; }
646
if(value[endIndex] == '0' && value[endIndex+1] == 'x')
649
while(std::isxdigit(value[++endIndex])) {}
653
while(std::isdigit(value[++endIndex])) {}
656
str.reserve(endIndex - startIndex + 1);
657
str.assign(value + startIndex, value + endIndex);
660
mpz_set_str(mData->mInteger, &str[0], 0);
661
*endptr = const_cast<char*>(value + endIndex);
664
GmpInt GmpInt::parseString(const char* str, char** endptr)
666
GmpInt retval(kNoInitialization);
667
retval.parseValue(str, endptr);
671
//===========================================================================
672
// Operator functions
673
//===========================================================================
674
GmpInt operator+(long lhs, const GmpInt& rhs)
676
GmpInt retval(GmpInt::kNoInitialization);
678
mpz_add_ui(retval.mData->mInteger, rhs.mData->mInteger, lhs);
680
mpz_sub_ui(retval.mData->mInteger, rhs.mData->mInteger, -lhs);
684
GmpInt operator-(long lhs, const GmpInt& rhs)
686
GmpInt retval(GmpInt::kNoInitialization);
688
mpz_ui_sub(retval.mData->mInteger, lhs, rhs.mData->mInteger);
691
mpz_add_ui(retval.mData->mInteger, rhs.mData->mInteger, -lhs);
692
mpz_neg(retval.mData->mInteger, retval.mData->mInteger);
697
GmpInt operator*(long lhs, const GmpInt& rhs)
702
GmpInt operator/(long lhs, const GmpInt& rhs)
704
return GmpInt(lhs) / rhs;
707
GmpInt operator%(long lhs, const GmpInt& rhs)
709
return GmpInt(lhs) % rhs;