File indexing completed on 2025-01-18 09:27:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
0016 #define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
0017
0018 #include <algorithm>
0019 #include <cstdint>
0020 #include <iostream>
0021 #include <string>
0022
0023 #include "absl/base/config.h"
0024 #include "absl/strings/ascii.h"
0025 #include "absl/strings/internal/charconv_parse.h"
0026 #include "absl/strings/string_view.h"
0027
0028 namespace absl {
0029 ABSL_NAMESPACE_BEGIN
0030 namespace strings_internal {
0031
0032
0033 constexpr int kMaxSmallPowerOfFive = 13;
0034
0035 constexpr int kMaxSmallPowerOfTen = 9;
0036
0037 ABSL_DLL extern const uint32_t
0038 kFiveToNth[kMaxSmallPowerOfFive + 1];
0039 ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 template <int max_words>
0057 class BigUnsigned {
0058 public:
0059 static_assert(max_words == 4 || max_words == 84,
0060 "unsupported max_words value");
0061
0062 BigUnsigned() : size_(0), words_{} {}
0063 explicit constexpr BigUnsigned(uint64_t v)
0064 : size_((v >> 32) ? 2 : v ? 1 : 0),
0065 words_{static_cast<uint32_t>(v & 0xffffffffu),
0066 static_cast<uint32_t>(v >> 32)} {}
0067
0068
0069
0070
0071 explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {
0072
0073
0074 if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() ||
0075 sv.empty()) {
0076 return;
0077 }
0078 int exponent_adjust =
0079 ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1);
0080 if (exponent_adjust > 0) {
0081 MultiplyByTenToTheNth(exponent_adjust);
0082 }
0083 }
0084
0085
0086
0087
0088
0089 int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits);
0090
0091
0092
0093
0094
0095
0096 static constexpr int Digits10() {
0097
0098 return static_cast<uint64_t>(max_words) * 9975007 / 1035508;
0099 }
0100
0101
0102 void ShiftLeft(int count) {
0103 if (count > 0) {
0104 const int word_shift = count / 32;
0105 if (word_shift >= max_words) {
0106 SetToZero();
0107 return;
0108 }
0109 size_ = (std::min)(size_ + word_shift, max_words);
0110 count %= 32;
0111 if (count == 0) {
0112
0113
0114
0115 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(14, 0)
0116 #pragma GCC diagnostic push
0117 #pragma GCC diagnostic ignored "-Warray-bounds"
0118 #endif
0119 std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
0120 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(14, 0)
0121 #pragma GCC diagnostic pop
0122 #endif
0123 } else {
0124 for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {
0125 words_[i] = (words_[i - word_shift] << count) |
0126 (words_[i - word_shift - 1] >> (32 - count));
0127 }
0128 words_[word_shift] = words_[0] << count;
0129
0130 if (size_ < max_words && words_[size_]) {
0131 ++size_;
0132 }
0133 }
0134 std::fill_n(words_, word_shift, 0u);
0135 }
0136 }
0137
0138
0139
0140 void MultiplyBy(uint32_t v) {
0141 if (size_ == 0 || v == 1) {
0142 return;
0143 }
0144 if (v == 0) {
0145 SetToZero();
0146 return;
0147 }
0148 const uint64_t factor = v;
0149 uint64_t window = 0;
0150 for (int i = 0; i < size_; ++i) {
0151 window += factor * words_[i];
0152 words_[i] = window & 0xffffffff;
0153 window >>= 32;
0154 }
0155
0156 if (window && size_ < max_words) {
0157 words_[size_] = window & 0xffffffff;
0158 ++size_;
0159 }
0160 }
0161
0162 void MultiplyBy(uint64_t v) {
0163 uint32_t words[2];
0164 words[0] = static_cast<uint32_t>(v);
0165 words[1] = static_cast<uint32_t>(v >> 32);
0166 if (words[1] == 0) {
0167 MultiplyBy(words[0]);
0168 } else {
0169 MultiplyBy(2, words);
0170 }
0171 }
0172
0173
0174 void MultiplyByFiveToTheNth(int n) {
0175 while (n >= kMaxSmallPowerOfFive) {
0176 MultiplyBy(kFiveToNth[kMaxSmallPowerOfFive]);
0177 n -= kMaxSmallPowerOfFive;
0178 }
0179 if (n > 0) {
0180 MultiplyBy(kFiveToNth[n]);
0181 }
0182 }
0183
0184
0185 void MultiplyByTenToTheNth(int n) {
0186 if (n > kMaxSmallPowerOfTen) {
0187
0188
0189 MultiplyByFiveToTheNth(n);
0190 ShiftLeft(n);
0191 } else if (n > 0) {
0192
0193
0194 MultiplyBy(kTenToNth[n]);
0195 }
0196 }
0197
0198
0199
0200
0201 static BigUnsigned FiveToTheNth(int n);
0202
0203
0204 template <int M>
0205 void MultiplyBy(const BigUnsigned<M>& other) {
0206 MultiplyBy(other.size(), other.words());
0207 }
0208
0209 void SetToZero() {
0210 std::fill_n(words_, size_, 0u);
0211 size_ = 0;
0212 }
0213
0214
0215
0216 uint32_t GetWord(int index) const {
0217 if (index < 0 || index >= size_) {
0218 return 0;
0219 }
0220 return words_[index];
0221 }
0222
0223
0224
0225 std::string ToString() const;
0226
0227 int size() const { return size_; }
0228 const uint32_t* words() const { return words_; }
0229
0230 private:
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 int ReadDigits(const char* begin, const char* end, int significant_digits);
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 void MultiplyStep(int original_size, const uint32_t* other_words,
0278 int other_size, int step);
0279
0280 void MultiplyBy(int other_size, const uint32_t* other_words) {
0281 const int original_size = size_;
0282 const int first_step =
0283 (std::min)(original_size + other_size - 2, max_words - 1);
0284 for (int step = first_step; step >= 0; --step) {
0285 MultiplyStep(original_size, other_words, other_size, step);
0286 }
0287 }
0288
0289
0290 void AddWithCarry(int index, uint32_t value) {
0291 if (value) {
0292 while (index < max_words && value > 0) {
0293 words_[index] += value;
0294
0295 if (value > words_[index]) {
0296 value = 1;
0297 ++index;
0298 } else {
0299 value = 0;
0300 }
0301 }
0302 size_ = (std::min)(max_words, (std::max)(index + 1, size_));
0303 }
0304 }
0305
0306 void AddWithCarry(int index, uint64_t value) {
0307 if (value && index < max_words) {
0308 uint32_t high = value >> 32;
0309 uint32_t low = value & 0xffffffff;
0310 words_[index] += low;
0311 if (words_[index] < low) {
0312 ++high;
0313 if (high == 0) {
0314
0315
0316 AddWithCarry(index + 2, static_cast<uint32_t>(1));
0317 return;
0318 }
0319 }
0320 if (high > 0) {
0321 AddWithCarry(index + 1, high);
0322 } else {
0323
0324
0325 size_ = (std::min)(max_words, (std::max)(index + 1, size_));
0326 }
0327 }
0328 }
0329
0330
0331
0332 template <uint32_t divisor>
0333 uint32_t DivMod() {
0334 uint64_t accumulator = 0;
0335 for (int i = size_ - 1; i >= 0; --i) {
0336 accumulator <<= 32;
0337 accumulator += words_[i];
0338
0339 words_[i] = static_cast<uint32_t>(accumulator / divisor);
0340 accumulator = accumulator % divisor;
0341 }
0342 while (size_ > 0 && words_[size_ - 1] == 0) {
0343 --size_;
0344 }
0345 return static_cast<uint32_t>(accumulator);
0346 }
0347
0348
0349
0350
0351
0352
0353
0354
0355 int size_;
0356 uint32_t words_[max_words];
0357 };
0358
0359
0360
0361
0362 template <int N, int M>
0363 int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
0364 int limit = (std::max)(lhs.size(), rhs.size());
0365 for (int i = limit - 1; i >= 0; --i) {
0366 const uint32_t lhs_word = lhs.GetWord(i);
0367 const uint32_t rhs_word = rhs.GetWord(i);
0368 if (lhs_word < rhs_word) {
0369 return -1;
0370 } else if (lhs_word > rhs_word) {
0371 return 1;
0372 }
0373 }
0374 return 0;
0375 }
0376
0377 template <int N, int M>
0378 bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
0379 int limit = (std::max)(lhs.size(), rhs.size());
0380 for (int i = 0; i < limit; ++i) {
0381 if (lhs.GetWord(i) != rhs.GetWord(i)) {
0382 return false;
0383 }
0384 }
0385 return true;
0386 }
0387
0388 template <int N, int M>
0389 bool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
0390 return !(lhs == rhs);
0391 }
0392
0393 template <int N, int M>
0394 bool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
0395 return Compare(lhs, rhs) == -1;
0396 }
0397
0398 template <int N, int M>
0399 bool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
0400 return rhs < lhs;
0401 }
0402 template <int N, int M>
0403 bool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
0404 return !(rhs < lhs);
0405 }
0406 template <int N, int M>
0407 bool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
0408 return !(lhs < rhs);
0409 }
0410
0411
0412 template <int N>
0413 std::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) {
0414 return os << num.ToString();
0415 }
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426 extern template class BigUnsigned<4>;
0427 extern template class BigUnsigned<84>;
0428
0429 }
0430 ABSL_NAMESPACE_END
0431 }
0432
0433 #endif