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;