abseil-cpp/absl/strings/internal/charconv_bigint.h
Go to the documentation of this file.
1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
16 #define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <iostream>
21 #include <string>
22 
23 #include "absl/base/config.h"
24 #include "absl/strings/ascii.h"
25 #include "absl/strings/internal/charconv_parse.h"
26 #include "absl/strings/string_view.h"
27 
28 namespace absl {
30 namespace strings_internal {
31 
32 // The largest power that 5 that can be raised to, and still fit in a uint32_t.
33 constexpr int kMaxSmallPowerOfFive = 13;
34 // The largest power that 10 that can be raised to, and still fit in a uint32_t.
35 constexpr int kMaxSmallPowerOfTen = 9;
36 
37 ABSL_DLL extern const uint32_t
40 
41 // Large, fixed-width unsigned integer.
42 //
43 // Exact rounding for decimal-to-binary floating point conversion requires very
44 // large integer math, but a design goal of absl::from_chars is to avoid
45 // allocating memory. The integer precision needed for decimal-to-binary
46 // conversions is large but bounded, so a huge fixed-width integer class
47 // suffices.
48 //
49 // This is an intentionally limited big integer class. Only needed operations
50 // are implemented. All storage lives in an array data member, and all
51 // arithmetic is done in-place, to avoid requiring separate storage for operand
52 // and result.
53 //
54 // This is an internal class. Some methods live in the .cc file, and are
55 // instantiated only for the values of max_words we need.
56 template <int max_words>
57 class BigUnsigned {
58  public:
59  static_assert(max_words == 4 || max_words == 84,
60  "unsupported max_words value");
61 
62  BigUnsigned() : size_(0), words_{} {}
63  explicit constexpr BigUnsigned(uint64_t v)
64  : size_((v >> 32) ? 2 : v ? 1 : 0),
65  words_{static_cast<uint32_t>(v & 0xffffffffu),
66  static_cast<uint32_t>(v >> 32)} {}
67 
68  // Constructs a BigUnsigned from the given string_view containing a decimal
69  // value. If the input string is not a decimal integer, constructs a 0
70  // instead.
71  explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {
72  // Check for valid input, returning a 0 otherwise. This is reasonable
73  // behavior only because this constructor is for unit tests.
74  if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() ||
75  sv.empty()) {
76  return;
77  }
78  int exponent_adjust =
79  ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1);
80  if (exponent_adjust > 0) {
81  MultiplyByTenToTheNth(exponent_adjust);
82  }
83  }
84 
85  // Loads the mantissa value of a previously-parsed float.
86  //
87  // Returns the associated decimal exponent. The value of the parsed float is
88  // exactly *this * 10**exponent.
89  int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits);
90 
91  // Returns the number of decimal digits of precision this type provides. All
92  // numbers with this many decimal digits or fewer are representable by this
93  // type.
94  //
95  // Analagous to std::numeric_limits<BigUnsigned>::digits10.
96  static constexpr int Digits10() {
97  // 9975007/1035508 is very slightly less than log10(2**32).
98  return static_cast<uint64_t>(max_words) * 9975007 / 1035508;
99  }
100 
101  // Shifts left by the given number of bits.
102  void ShiftLeft(int count) {
103  if (count > 0) {
104  const int word_shift = count / 32;
105  if (word_shift >= max_words) {
106  SetToZero();
107  return;
108  }
109  size_ = (std::min)(size_ + word_shift, max_words);
110  count %= 32;
111  if (count == 0) {
112  std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
113  } else {
114  for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {
115  words_[i] = (words_[i - word_shift] << count) |
116  (words_[i - word_shift - 1] >> (32 - count));
117  }
118  words_[word_shift] = words_[0] << count;
119  // Grow size_ if necessary.
120  if (size_ < max_words && words_[size_]) {
121  ++size_;
122  }
123  }
124  std::fill(words_, words_ + word_shift, 0u);
125  }
126  }
127 
128 
129  // Multiplies by v in-place.
131  if (size_ == 0 || v == 1) {
132  return;
133  }
134  if (v == 0) {
135  SetToZero();
136  return;
137  }
138  const uint64_t factor = v;
139  uint64_t window = 0;
140  for (int i = 0; i < size_; ++i) {
141  window += factor * words_[i];
142  words_[i] = window & 0xffffffff;
143  window >>= 32;
144  }
145  // If carry bits remain and there's space for them, grow size_.
146  if (window && size_ < max_words) {
147  words_[size_] = window & 0xffffffff;
148  ++size_;
149  }
150  }
151 
153  uint32_t words[2];
154  words[0] = static_cast<uint32_t>(v);
155  words[1] = static_cast<uint32_t>(v >> 32);
156  if (words[1] == 0) {
157  MultiplyBy(words[0]);
158  } else {
159  MultiplyBy(2, words);
160  }
161  }
162 
163  // Multiplies in place by 5 to the power of n. n must be non-negative.
165  while (n >= kMaxSmallPowerOfFive) {
168  }
169  if (n > 0) {
171  }
172  }
173 
174  // Multiplies in place by 10 to the power of n. n must be non-negative.
175  void MultiplyByTenToTheNth(int n) {
176  if (n > kMaxSmallPowerOfTen) {
177  // For large n, raise to a power of 5, then shift left by the same amount.
178  // (10**n == 5**n * 2**n.) This requires fewer multiplications overall.
180  ShiftLeft(n);
181  } else if (n > 0) {
182  // We can do this more quickly for very small N by using a single
183  // multiplication.
185  }
186  }
187 
188  // Returns the value of 5**n, for non-negative n. This implementation uses
189  // a lookup table, and is faster then seeding a BigUnsigned with 1 and calling
190  // MultiplyByFiveToTheNth().
191  static BigUnsigned FiveToTheNth(int n);
192 
193  // Multiplies by another BigUnsigned, in-place.
194  template <int M>
195  void MultiplyBy(const BigUnsigned<M>& other) {
196  MultiplyBy(other.size(), other.words());
197  }
198 
199  void SetToZero() {
200  std::fill(words_, words_ + size_, 0u);
201  size_ = 0;
202  }
203 
204  // Returns the value of the nth word of this BigUnsigned. This is
205  // range-checked, and returns 0 on out-of-bounds accesses.
206  uint32_t GetWord(int index) const {
207  if (index < 0 || index >= size_) {
208  return 0;
209  }
210  return words_[index];
211  }
212 
213  // Returns this integer as a decimal string. This is not used in the decimal-
214  // to-binary conversion; it is intended to aid in testing.
215  std::string ToString() const;
216 
217  int size() const { return size_; }
218  const uint32_t* words() const { return words_; }
219 
220  private:
221  // Reads the number between [begin, end), possibly containing a decimal point,
222  // into this BigUnsigned.
223  //
224  // Callers are required to ensure [begin, end) contains a valid number, with
225  // one or more decimal digits and at most one decimal point. This routine
226  // will behave unpredictably if these preconditions are not met.
227  //
228  // Only the first `significant_digits` digits are read. Digits beyond this
229  // limit are "sticky": If the final significant digit is 0 or 5, and if any
230  // dropped digit is nonzero, then that final significant digit is adjusted up
231  // to 1 or 6. This adjustment allows for precise rounding.
232  //
233  // Returns `exponent_adjustment`, a power-of-ten exponent adjustment to
234  // account for the decimal point and for dropped significant digits. After
235  // this function returns,
236  // actual_value_of_parsed_string ~= *this * 10**exponent_adjustment.
237  int ReadDigits(const char* begin, const char* end, int significant_digits);
238 
239  // Performs a step of big integer multiplication. This computes the full
240  // (64-bit-wide) values that should be added at the given index (step), and
241  // adds to that location in-place.
242  //
243  // Because our math all occurs in place, we must multiply starting from the
244  // highest word working downward. (This is a bit more expensive due to the
245  // extra carries involved.)
246  //
247  // This must be called in steps, for each word to be calculated, starting from
248  // the high end and working down to 0. The first value of `step` should be
249  // `std::min(original_size + other.size_ - 2, max_words - 1)`.
250  // The reason for this expression is that multiplying the i'th word from one
251  // multiplicand and the j'th word of another multiplicand creates a
252  // two-word-wide value to be stored at the (i+j)'th element. The highest
253  // word indices we will access are `original_size - 1` from this object, and
254  // `other.size_ - 1` from our operand. Therefore,
255  // `original_size + other.size_ - 2` is the first step we should calculate,
256  // but limited on an upper bound by max_words.
257 
258  // Working from high-to-low ensures that we do not overwrite the portions of
259  // the initial value of *this which are still needed for later steps.
260  //
261  // Once called with step == 0, *this contains the result of the
262  // multiplication.
263  //
264  // `original_size` is the size_ of *this before the first call to
265  // MultiplyStep(). `other_words` and `other_size` are the contents of our
266  // operand. `step` is the step to perform, as described above.
267  void MultiplyStep(int original_size, const uint32_t* other_words,
268  int other_size, int step);
269 
270  void MultiplyBy(int other_size, const uint32_t* other_words) {
271  const int original_size = size_;
272  const int first_step =
273  (std::min)(original_size + other_size - 2, max_words - 1);
274  for (int step = first_step; step >= 0; --step) {
275  MultiplyStep(original_size, other_words, other_size, step);
276  }
277  }
278 
279  // Adds a 32-bit value to the index'th word, with carry.
281  if (value) {
282  while (index < max_words && value > 0) {
283  words_[index] += value;
284  // carry if we overflowed in this word:
285  if (value > words_[index]) {
286  value = 1;
287  ++index;
288  } else {
289  value = 0;
290  }
291  }
292  size_ = (std::min)(max_words, (std::max)(index + 1, size_));
293  }
294  }
295 
297  if (value && index < max_words) {
298  uint32_t high = value >> 32;
299  uint32_t low = value & 0xffffffff;
300  words_[index] += low;
301  if (words_[index] < low) {
302  ++high;
303  if (high == 0) {
304  // Carry from the low word caused our high word to overflow.
305  // Short circuit here to do the right thing.
306  AddWithCarry(index + 2, static_cast<uint32_t>(1));
307  return;
308  }
309  }
310  if (high > 0) {
311  AddWithCarry(index + 1, high);
312  } else {
313  // Normally 32-bit AddWithCarry() sets size_, but since we don't call
314  // it when `high` is 0, do it ourselves here.
315  size_ = (std::min)(max_words, (std::max)(index + 1, size_));
316  }
317  }
318  }
319 
320  // Divide this in place by a constant divisor. Returns the remainder of the
321  // division.
322  template <uint32_t divisor>
324  uint64_t accumulator = 0;
325  for (int i = size_ - 1; i >= 0; --i) {
326  accumulator <<= 32;
327  accumulator += words_[i];
328  // accumulator / divisor will never overflow an int32_t in this loop
329  words_[i] = static_cast<uint32_t>(accumulator / divisor);
330  accumulator = accumulator % divisor;
331  }
332  while (size_ > 0 && words_[size_ - 1] == 0) {
333  --size_;
334  }
335  return static_cast<uint32_t>(accumulator);
336  }
337 
338  // The number of elements in words_ that may carry significant values.
339  // All elements beyond this point are 0.
340  //
341  // When size_ is 0, this BigUnsigned stores the value 0.
342  // When size_ is nonzero, is *not* guaranteed that words_[size_ - 1] is
343  // nonzero. This can occur due to overflow truncation.
344  // In particular, x.size_ != y.size_ does *not* imply x != y.
345  int size_;
346  uint32_t words_[max_words];
347 };
348 
349 // Compares two big integer instances.
350 //
351 // Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
352 template <int N, int M>
353 int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
354  int limit = (std::max)(lhs.size(), rhs.size());
355  for (int i = limit - 1; i >= 0; --i) {
356  const uint32_t lhs_word = lhs.GetWord(i);
357  const uint32_t rhs_word = rhs.GetWord(i);
358  if (lhs_word < rhs_word) {
359  return -1;
360  } else if (lhs_word > rhs_word) {
361  return 1;
362  }
363  }
364  return 0;
365 }
366 
367 template <int N, int M>
368 bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
369  int limit = (std::max)(lhs.size(), rhs.size());
370  for (int i = 0; i < limit; ++i) {
371  if (lhs.GetWord(i) != rhs.GetWord(i)) {
372  return false;
373  }
374  }
375  return true;
376 }
377 
378 template <int N, int M>
379 bool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
380  return !(lhs == rhs);
381 }
382 
383 template <int N, int M>
384 bool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
385  return Compare(lhs, rhs) == -1;
386 }
387 
388 template <int N, int M>
389 bool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
390  return rhs < lhs;
391 }
392 template <int N, int M>
393 bool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
394  return !(rhs < lhs);
395 }
396 template <int N, int M>
397 bool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
398  return !(lhs < rhs);
399 }
400 
401 // Output operator for BigUnsigned, for testing purposes only.
402 template <int N>
403 std::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) {
404  return os << num.ToString();
405 }
406 
407 // Explicit instantiation declarations for the sizes of BigUnsigned that we
408 // are using.
409 //
410 // For now, the choices of 4 and 84 are arbitrary; 4 is a small value that is
411 // still bigger than an int128, and 84 is a large value we will want to use
412 // in the from_chars implementation.
413 //
414 // Comments justifying the use of 84 belong in the from_chars implementation,
415 // and will be added in a follow-up CL.
416 extern template class BigUnsigned<4>;
417 extern template class BigUnsigned<84>;
418 
419 } // namespace strings_internal
421 } // namespace absl
422 
423 #endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
absl::strings_internal::operator==
bool operator==(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:368
begin
char * begin
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1007
absl::strings_internal::BigUnsigned::words
const uint32_t * words() const
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:218
absl::strings_internal::BigUnsigned::SetToZero
void SetToZero()
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:199
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
absl::strings_internal::BigUnsigned::ReadDigits
int ReadDigits(const char *begin, const char *end, int significant_digits)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.cc:193
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
absl::strings_internal::BigUnsigned::FiveToTheNth
static BigUnsigned FiveToTheNth(int n)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.cc:288
absl::strings_internal::BigUnsigned::words_
uint32_t words_[max_words]
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:346
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
absl::strings_internal::BigUnsigned::GetWord
uint32_t GetWord(int index) const
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:206
absl::strings_internal::operator<
bool operator<(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:384
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::strings_internal::operator>
bool operator>(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:389
absl::strings_internal::kFiveToNth
const ABSL_DLL uint32_t kFiveToNth[14]
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.cc:161
absl::strings_internal::kMaxSmallPowerOfFive
constexpr int kMaxSmallPowerOfFive
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:33
absl::strings_internal::BigUnsigned::MultiplyBy
void MultiplyBy(uint64_t v)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:152
absl::strings_internal::operator<=
bool operator<=(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:393
absl::strings_internal::operator<<
std::ostream & operator<<(std::ostream &os, const BigUnsigned< N > &num)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:403
absl::strings_internal::operator>=
bool operator>=(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:397
absl::strings_internal::BigUnsigned::MultiplyByTenToTheNth
void MultiplyByTenToTheNth(int n)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:175
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
absl::strings_internal::BigUnsigned::BigUnsigned
constexpr BigUnsigned(uint64_t v)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:63
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
absl::strings_internal::BigUnsigned
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:57
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
absl::strings_internal::BigUnsigned::MultiplyBy
void MultiplyBy(int other_size, const uint32_t *other_words)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:270
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::strings_internal::kMaxSmallPowerOfTen
constexpr int kMaxSmallPowerOfTen
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:35
absl::strings_internal::BigUnsigned::size_
int size_
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:345
absl::strings_internal::BigUnsigned::ReadFloatMantissa
int ReadFloatMantissa(const ParsedFloat &fp, int significant_digits)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.cc:171
min
#define min(a, b)
Definition: qsort.h:83
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
ABSL_DLL
#define ABSL_DLL
Definition: third_party/abseil-cpp/absl/base/config.h:746
value
const char * value
Definition: hpack_parser_table.cc:165
absl::strings_internal::BigUnsigned::MultiplyBy
void MultiplyBy(uint32_t v)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:130
absl::strings_internal::BigUnsigned::size
int size() const
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:217
absl::strings_internal::BigUnsigned::DivMod
uint32_t DivMod()
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:323
absl::strings_internal::BigUnsigned::AddWithCarry
void AddWithCarry(int index, uint64_t value)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:296
absl::strings_internal::BigUnsigned::MultiplyByFiveToTheNth
void MultiplyByFiveToTheNth(int n)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:164
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
absl::strings_internal::BigUnsigned::MultiplyStep
void MultiplyStep(int original_size, const uint32_t *other_words, int other_size, int step)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.cc:316
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
absl::strings_internal::BigUnsigned::ShiftLeft
void ShiftLeft(int count)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:102
absl::strings_internal::BigUnsigned::MultiplyBy
void MultiplyBy(const BigUnsigned< M > &other)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:195
step
static int step
Definition: test-mutexes.c:31
xds_manager.num
num
Definition: xds_manager.py:56
absl::strings_internal::BigUnsigned::Digits10
static constexpr int Digits10()
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:96
absl::strings_internal::operator!=
bool operator!=(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:379
fill
int fill
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:47
absl::strings_internal::Compare
int Compare(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:353
absl::strings_internal::BigUnsigned::BigUnsigned
BigUnsigned(absl::string_view sv)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:71
absl::strings_internal::BigUnsigned::AddWithCarry
void AddWithCarry(int index, uint32_t value)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:280
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::strings_internal::BigUnsigned::BigUnsigned
BigUnsigned()
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:62
absl::ascii_isdigit
bool ascii_isdigit(unsigned char c)
Definition: abseil-cpp/absl/strings/ascii.h:132
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
absl::strings_internal::BigUnsigned::ToString
std::string ToString() const
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.cc:339
absl::strings_internal::kTenToNth
const ABSL_DLL uint32_t kTenToNth[10]
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.cc:166


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:53