Minor optimizations in BigInteger

This commit is contained in:
Milo Yip 2014-09-16 19:23:28 +08:00
parent 299e9f1e32
commit 5171775d4c

View File

@ -30,6 +30,10 @@ class BigInteger {
public: public:
typedef uint64_t Type; typedef uint64_t Type;
BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
}
explicit BigInteger(uint64_t u) : count_(1) { explicit BigInteger(uint64_t u) : count_(1) {
digits_[0] = u; digits_[0] = u;
} }
@ -75,6 +79,8 @@ public:
BigInteger& operator*=(uint64_t u) { BigInteger& operator*=(uint64_t u) {
if (u == 0) return *this = 0; if (u == 0) return *this = 0;
if (u == 1) return *this; if (u == 1) return *this;
if (*this == 1) return *this = u;
uint64_t k = 0; uint64_t k = 0;
for (size_t i = 0; i < count_; i++) { for (size_t i = 0; i < count_; i++) {
uint64_t hi; uint64_t hi;
@ -91,6 +97,8 @@ public:
BigInteger& operator*=(uint32_t u) { BigInteger& operator*=(uint32_t u) {
if (u == 0) return *this = 0; if (u == 0) return *this = 0;
if (u == 1) return *this; if (u == 1) return *this;
if (*this == 1) return *this = u;
uint32_t k = 0; uint32_t k = 0;
for (size_t i = 0; i < count_; i++) { for (size_t i = 0; i < count_; i++) {
const uint64_t c = digits_[i] >> 32; const uint64_t c = digits_[i] >> 32;
@ -110,32 +118,27 @@ public:
} }
BigInteger& operator<<=(size_t shift) { BigInteger& operator<<=(size_t shift) {
if (IsZero()) return *this; if (IsZero() || shift == 0) return *this;
if (shift >= kTypeBit) { size_t offset = shift / kTypeBit;
size_t offset = shift / kTypeBit; size_t interShift = shift % kTypeBit;
RAPIDJSON_ASSERT(count_ + offset <= kCapacity); RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
for (size_t i = count_; i > 0; i--)
digits_[i - 1 + offset] = digits_[i - 1]; if (interShift == 0) {
for (size_t i = 0; i < offset; i++) std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
digits_[i] = 0;
count_ += offset; count_ += offset;
shift -= offset * kTypeBit; }
else {
digits_[count_] = 0;
for (size_t i = count_; i > 0; i--)
digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
digits_[offset] = digits_[0] << interShift;
count_ += offset;
if (digits_[count_])
count_++;
} }
if (shift > 0) { std::memset(digits_, 0, offset * sizeof(Type));
// Inter-digit shifts
Type carry = 0;
for (size_t i = 0; i < count_; i++) {
Type newCarry = digits_[i] >> (kTypeBit - shift);
digits_[i] = (digits_[i] << shift) | carry;
carry = newCarry;
}
// Last carry
if (carry)
PushBack(carry);
}
return *this; return *this;
} }
@ -144,6 +147,10 @@ public:
return count_ == rhs.count_ && memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; return count_ == rhs.count_ && memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
} }
bool operator==(const Type rhs) const {
return count_ == 1 && digits_[0] == rhs;
}
BigInteger& MultiplyPow5(unsigned exp) { BigInteger& MultiplyPow5(unsigned exp) {
static const uint32_t kPow5[12] = { static const uint32_t kPow5[12] = {
5, 5,
@ -160,10 +167,9 @@ public:
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
}; };
if (exp == 0) return *this; if (exp == 0) return *this;
unsigned e = exp; for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
for (; e >= 27; e -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 for (; exp >= 13; exp -= 13) *this *= 1220703125u; // 5^13
for (; e >= 13; e -= 13) *this *= 1220703125u; // 5^13 if (exp > 0) *this *= kPow5[exp - 1];
if (e > 0) *this *= kPow5[e - 1];
return *this; return *this;
} }
@ -277,6 +283,7 @@ private:
Type digits_[kCapacity]; Type digits_[kCapacity];
size_t count_; size_t count_;
}; };
} // namespace internal } // namespace internal
} // namespace rapidjson } // namespace rapidjson