-- fe689b30f9a3a614e8a577997cc340043d01c2f1 by Abseil Team <absl-team@google.com>: Change arm32 linux backtrace to use the generic implementation. PiperOrigin-RevId: 218386158 -- 86f8678d055d32edc989e6a4d1dc49c3a15cd350 by Abseil Team <absl-team@google.com>: Update documentation on SHARED_LOCKS_REQUIRED and EXCLUSIVE_LOCKS_REQUIRED so that users know the differences between them. PiperOrigin-RevId: 218365545 -- 22947b48ce4a1ba71ad4794f762235dac3a1df12 by Greg Falcon <gfalcon@google.com>: The from_chars implementation incorrectly assumed `uint32_t` was `unsigned int`. `strings_internal::BigUnsigned` had `uint32_t` and `uint64_t` constructors; when both of these types differ from `unsigned int`, `BigUnsigned(1u)` is ambiguous (neither conversion is better). Fix this by removing the `uint32_t` constructor. When the `uint64_t` constructor is called with a literal or type that is 32 bits or narrower, the compiler is smart enough to optimize away the two-word case, so this fix is free. PiperOrigin-RevId: 218346935 -- 7201ab430bb90ca0e30b102915d02564f61353eb by Abseil Team <absl-team@google.com>: Fix formatting errors discovered during merge conflict. PiperOrigin-RevId: 218229891 GitOrigin-RevId: fe689b30f9a3a614e8a577997cc340043d01c2f1 Change-Id: I5d382482ad227d48ffe57b243ce11b1eb44a1314
		
			
				
	
	
		
			419 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			419 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright 2018 The Abseil Authors.
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//      http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
 | 
						|
#define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
#include <cstdint>
 | 
						|
#include <iostream>
 | 
						|
#include <string>
 | 
						|
 | 
						|
#include "absl/strings/ascii.h"
 | 
						|
#include "absl/strings/internal/charconv_parse.h"
 | 
						|
#include "absl/strings/string_view.h"
 | 
						|
 | 
						|
namespace absl {
 | 
						|
namespace strings_internal {
 | 
						|
 | 
						|
// The largest power that 5 that can be raised to, and still fit in a uint32_t.
 | 
						|
constexpr int kMaxSmallPowerOfFive = 13;
 | 
						|
// The largest power that 10 that can be raised to, and still fit in a uint32_t.
 | 
						|
constexpr int kMaxSmallPowerOfTen = 9;
 | 
						|
 | 
						|
extern const uint32_t kFiveToNth[kMaxSmallPowerOfFive + 1];
 | 
						|
extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
 | 
						|
 | 
						|
// Large, fixed-width unsigned integer.
 | 
						|
//
 | 
						|
// Exact rounding for decimal-to-binary floating point conversion requires very
 | 
						|
// large integer math, but a design goal of absl::from_chars is to avoid
 | 
						|
// allocating memory.  The integer precision needed for decimal-to-binary
 | 
						|
// conversions is large but bounded, so a huge fixed-width integer class
 | 
						|
// suffices.
 | 
						|
//
 | 
						|
// This is an intentionally limited big integer class.  Only needed operations
 | 
						|
// are implemented.  All storage lives in an array data member, and all
 | 
						|
// arithmetic is done in-place, to avoid requiring separate storage for operand
 | 
						|
// and result.
 | 
						|
//
 | 
						|
// This is an internal class.  Some methods live in the .cc file, and are
 | 
						|
// instantiated only for the values of max_words we need.
 | 
						|
template <int max_words>
 | 
						|
class BigUnsigned {
 | 
						|
 public:
 | 
						|
  static_assert(max_words == 4 || max_words == 84,
 | 
						|
                "unsupported max_words value");
 | 
						|
 | 
						|
  BigUnsigned() : size_(0), words_{} {}
 | 
						|
  explicit constexpr BigUnsigned(uint64_t v)
 | 
						|
      : size_((v >> 32) ? 2 : v ? 1 : 0),
 | 
						|
        words_{static_cast<uint32_t>(v & 0xffffffffu),
 | 
						|
               static_cast<uint32_t>(v >> 32)} {}
 | 
						|
 | 
						|
  // Constructs a BigUnsigned from the given string_view containing a decimal
 | 
						|
  // value.  If the input std::string is not a decimal integer, constructs a 0
 | 
						|
  // instead.
 | 
						|
  explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {
 | 
						|
    // Check for valid input, returning a 0 otherwise.  This is reasonable
 | 
						|
    // behavior only because this constructor is for unit tests.
 | 
						|
    if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() ||
 | 
						|
        sv.empty()) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    int exponent_adjust =
 | 
						|
        ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1);
 | 
						|
    if (exponent_adjust > 0) {
 | 
						|
      MultiplyByTenToTheNth(exponent_adjust);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Loads the mantissa value of a previously-parsed float.
 | 
						|
  //
 | 
						|
  // Returns the associated decimal exponent.  The value of the parsed float is
 | 
						|
  // exactly *this * 10**exponent.
 | 
						|
  int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits);
 | 
						|
 | 
						|
  // Returns the number of decimal digits of precision this type provides.  All
 | 
						|
  // numbers with this many decimal digits or fewer are representable by this
 | 
						|
  // type.
 | 
						|
  //
 | 
						|
  // Analagous to std::numeric_limits<BigUnsigned>::digits10.
 | 
						|
  static constexpr int Digits10() {
 | 
						|
    // 9975007/1035508 is very slightly less than log10(2**32).
 | 
						|
    return static_cast<uint64_t>(max_words) * 9975007 / 1035508;
 | 
						|
  }
 | 
						|
 | 
						|
  // Shifts left by the given number of bits.
 | 
						|
  void ShiftLeft(int count) {
 | 
						|
    if (count > 0) {
 | 
						|
      const int word_shift = count / 32;
 | 
						|
      if (word_shift >= max_words) {
 | 
						|
        SetToZero();
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      size_ = std::min(size_ + word_shift, max_words);
 | 
						|
      count %= 32;
 | 
						|
      if (count == 0) {
 | 
						|
        std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
 | 
						|
      } else {
 | 
						|
        for (int i = std::min(size_, max_words - 1); i > word_shift; --i) {
 | 
						|
          words_[i] = (words_[i - word_shift] << count) |
 | 
						|
                      (words_[i - word_shift - 1] >> (32 - count));
 | 
						|
        }
 | 
						|
        words_[word_shift] = words_[0] << count;
 | 
						|
        // Grow size_ if necessary.
 | 
						|
        if (size_ < max_words && words_[size_]) {
 | 
						|
          ++size_;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      std::fill(words_, words_ + word_shift, 0u);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Multiplies by v in-place.
 | 
						|
  void MultiplyBy(uint32_t v) {
 | 
						|
    if (size_ == 0 || v == 1) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    if (v == 0) {
 | 
						|
      SetToZero();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    const uint64_t factor = v;
 | 
						|
    uint64_t window = 0;
 | 
						|
    for (int i = 0; i < size_; ++i) {
 | 
						|
      window += factor * words_[i];
 | 
						|
      words_[i] = window & 0xffffffff;
 | 
						|
      window >>= 32;
 | 
						|
    }
 | 
						|
    // If carry bits remain and there's space for them, grow size_.
 | 
						|
    if (window && size_ < max_words) {
 | 
						|
      words_[size_] = window & 0xffffffff;
 | 
						|
      ++size_;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void MultiplyBy(uint64_t v) {
 | 
						|
    uint32_t words[2];
 | 
						|
    words[0] = static_cast<uint32_t>(v);
 | 
						|
    words[1] = static_cast<uint32_t>(v >> 32);
 | 
						|
    if (words[1] == 0) {
 | 
						|
      MultiplyBy(words[0]);
 | 
						|
    } else {
 | 
						|
      MultiplyBy(2, words);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Multiplies in place by 5 to the power of n.  n must be non-negative.
 | 
						|
  void MultiplyByFiveToTheNth(int n) {
 | 
						|
    while (n >= kMaxSmallPowerOfFive) {
 | 
						|
      MultiplyBy(kFiveToNth[kMaxSmallPowerOfFive]);
 | 
						|
      n -= kMaxSmallPowerOfFive;
 | 
						|
    }
 | 
						|
    if (n > 0) {
 | 
						|
      MultiplyBy(kFiveToNth[n]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Multiplies in place by 10 to the power of n.  n must be non-negative.
 | 
						|
  void MultiplyByTenToTheNth(int n) {
 | 
						|
    if (n > kMaxSmallPowerOfTen) {
 | 
						|
      // For large n, raise to a power of 5, then shift left by the same amount.
 | 
						|
      // (10**n == 5**n * 2**n.)  This requires fewer multiplications overall.
 | 
						|
      MultiplyByFiveToTheNth(n);
 | 
						|
      ShiftLeft(n);
 | 
						|
    } else if (n > 0) {
 | 
						|
      // We can do this more quickly for very small N by using a single
 | 
						|
      // multiplication.
 | 
						|
      MultiplyBy(kTenToNth[n]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Returns the value of 5**n, for non-negative n.  This implementation uses
 | 
						|
  // a lookup table, and is faster then seeding a BigUnsigned with 1 and calling
 | 
						|
  // MultiplyByFiveToTheNth().
 | 
						|
  static BigUnsigned FiveToTheNth(int n);
 | 
						|
 | 
						|
  // Multiplies by another BigUnsigned, in-place.
 | 
						|
  template <int M>
 | 
						|
  void MultiplyBy(const BigUnsigned<M>& other) {
 | 
						|
    MultiplyBy(other.size(), other.words());
 | 
						|
  }
 | 
						|
 | 
						|
  void SetToZero() {
 | 
						|
    std::fill(words_, words_ + size_, 0u);
 | 
						|
    size_ = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  // Returns the value of the nth word of this BigUnsigned.  This is
 | 
						|
  // range-checked, and returns 0 on out-of-bounds accesses.
 | 
						|
  uint32_t GetWord(int index) const {
 | 
						|
    if (index < 0 || index >= size_) {
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    return words_[index];
 | 
						|
  }
 | 
						|
 | 
						|
  // Returns this integer as a decimal std::string.  This is not used in the decimal-
 | 
						|
  // to-binary conversion; it is intended to aid in testing.
 | 
						|
  std::string ToString() const;
 | 
						|
 | 
						|
  int size() const { return size_; }
 | 
						|
  const uint32_t* words() const { return words_; }
 | 
						|
 | 
						|
 private:
 | 
						|
  // Reads the number between [begin, end), possibly containing a decimal point,
 | 
						|
  // into this BigUnsigned.
 | 
						|
  //
 | 
						|
  // Callers are required to ensure [begin, end) contains a valid number, with
 | 
						|
  // one or more decimal digits and at most one decimal point.  This routine
 | 
						|
  // will behave unpredictably if these preconditions are not met.
 | 
						|
  //
 | 
						|
  // Only the first `significant_digits` digits are read.  Digits beyond this
 | 
						|
  // limit are "sticky": If the final significant digit is 0 or 5, and if any
 | 
						|
  // dropped digit is nonzero, then that final significant digit is adjusted up
 | 
						|
  // to 1 or 6.  This adjustment allows for precise rounding.
 | 
						|
  //
 | 
						|
  // Returns `exponent_adjustment`, a power-of-ten exponent adjustment to
 | 
						|
  // account for the decimal point and for dropped significant digits.  After
 | 
						|
  // this function returns,
 | 
						|
  //   actual_value_of_parsed_string ~= *this * 10**exponent_adjustment.
 | 
						|
  int ReadDigits(const char* begin, const char* end, int significant_digits);
 | 
						|
 | 
						|
  // Performs a step of big integer multiplication.  This computes the full
 | 
						|
  // (64-bit-wide) values that should be added at the given index (step), and
 | 
						|
  // adds to that location in-place.
 | 
						|
  //
 | 
						|
  // Because our math all occurs in place, we must multiply starting from the
 | 
						|
  // highest word working downward.  (This is a bit more expensive due to the
 | 
						|
  // extra carries involved.)
 | 
						|
  //
 | 
						|
  // This must be called in steps, for each word to be calculated, starting from
 | 
						|
  // the high end and working down to 0.  The first value of `step` should be
 | 
						|
  //   `std::min(original_size + other.size_ - 2, max_words - 1)`.
 | 
						|
  // The reason for this expression is that multiplying the i'th word from one
 | 
						|
  // multiplicand and the j'th word of another multiplicand creates a
 | 
						|
  // two-word-wide value to be stored at the (i+j)'th element.  The highest
 | 
						|
  // word indices we will access are `original_size - 1` from this object, and
 | 
						|
  // `other.size_ - 1` from our operand.  Therefore,
 | 
						|
  // `original_size + other.size_ - 2` is the first step we should calculate,
 | 
						|
  // but limited on an upper bound by max_words.
 | 
						|
 | 
						|
  // Working from high-to-low ensures that we do not overwrite the portions of
 | 
						|
  // the initial value of *this which are still needed for later steps.
 | 
						|
  //
 | 
						|
  // Once called with step == 0, *this contains the result of the
 | 
						|
  // multiplication.
 | 
						|
  //
 | 
						|
  // `original_size` is the size_ of *this before the first call to
 | 
						|
  // MultiplyStep().  `other_words` and `other_size` are the contents of our
 | 
						|
  // operand.  `step` is the step to perform, as described above.
 | 
						|
  void MultiplyStep(int original_size, const uint32_t* other_words,
 | 
						|
                    int other_size, int step);
 | 
						|
 | 
						|
  void MultiplyBy(int other_size, const uint32_t* other_words) {
 | 
						|
    const int original_size = size_;
 | 
						|
    const int first_step =
 | 
						|
        std::min(original_size + other_size - 2, max_words - 1);
 | 
						|
    for (int step = first_step; step >= 0; --step) {
 | 
						|
      MultiplyStep(original_size, other_words, other_size, step);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Adds a 32-bit value to the index'th word, with carry.
 | 
						|
  void AddWithCarry(int index, uint32_t value) {
 | 
						|
    if (value) {
 | 
						|
      while (index < max_words && value > 0) {
 | 
						|
        words_[index] += value;
 | 
						|
        // carry if we overflowed in this word:
 | 
						|
        if (value > words_[index]) {
 | 
						|
          value = 1;
 | 
						|
          ++index;
 | 
						|
        } else {
 | 
						|
          value = 0;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      size_ = std::min(max_words, std::max(index + 1, size_));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void AddWithCarry(int index, uint64_t value) {
 | 
						|
    if (value && index < max_words) {
 | 
						|
      uint32_t high = value >> 32;
 | 
						|
      uint32_t low = value & 0xffffffff;
 | 
						|
      words_[index] += low;
 | 
						|
      if (words_[index] < low) {
 | 
						|
        ++high;
 | 
						|
        if (high == 0) {
 | 
						|
          // Carry from the low word caused our high word to overflow.
 | 
						|
          // Short circuit here to do the right thing.
 | 
						|
          AddWithCarry(index + 2, static_cast<uint32_t>(1));
 | 
						|
          return;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (high > 0) {
 | 
						|
        AddWithCarry(index + 1, high);
 | 
						|
      } else {
 | 
						|
        // Normally 32-bit AddWithCarry() sets size_, but since we don't call
 | 
						|
        // it when `high` is 0, do it ourselves here.
 | 
						|
        size_ = std::min(max_words, std::max(index + 1, size_));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Divide this in place by a constant divisor.  Returns the remainder of the
 | 
						|
  // division.
 | 
						|
  template <uint32_t divisor>
 | 
						|
  uint32_t DivMod() {
 | 
						|
    uint64_t accumulator = 0;
 | 
						|
    for (int i = size_ - 1; i >= 0; --i) {
 | 
						|
      accumulator <<= 32;
 | 
						|
      accumulator += words_[i];
 | 
						|
      // accumulator / divisor will never overflow an int32_t in this loop
 | 
						|
      words_[i] = static_cast<uint32_t>(accumulator / divisor);
 | 
						|
      accumulator = accumulator % divisor;
 | 
						|
    }
 | 
						|
    while (size_ > 0 && words_[size_ - 1] == 0) {
 | 
						|
      --size_;
 | 
						|
    }
 | 
						|
    return static_cast<uint32_t>(accumulator);
 | 
						|
  }
 | 
						|
 | 
						|
  // The number of elements in words_ that may carry significant values.
 | 
						|
  // All elements beyond this point are 0.
 | 
						|
  //
 | 
						|
  // When size_ is 0, this BigUnsigned stores the value 0.
 | 
						|
  // When size_ is nonzero, is *not* guaranteed that words_[size_ - 1] is
 | 
						|
  // nonzero.  This can occur due to overflow truncation.
 | 
						|
  // In particular, x.size_ != y.size_ does *not* imply x != y.
 | 
						|
  int size_;
 | 
						|
  uint32_t words_[max_words];
 | 
						|
};
 | 
						|
 | 
						|
// Compares two big integer instances.
 | 
						|
//
 | 
						|
// Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
 | 
						|
template <int N, int M>
 | 
						|
int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
 | 
						|
  int limit = std::max(lhs.size(), rhs.size());
 | 
						|
  for (int i = limit - 1; i >= 0; --i) {
 | 
						|
    const uint32_t lhs_word = lhs.GetWord(i);
 | 
						|
    const uint32_t rhs_word = rhs.GetWord(i);
 | 
						|
    if (lhs_word < rhs_word) {
 | 
						|
      return -1;
 | 
						|
    } else if (lhs_word > rhs_word) {
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
template <int N, int M>
 | 
						|
bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
 | 
						|
  int limit = std::max(lhs.size(), rhs.size());
 | 
						|
  for (int i = 0; i < limit; ++i) {
 | 
						|
    if (lhs.GetWord(i) != rhs.GetWord(i)) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
template <int N, int M>
 | 
						|
bool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
 | 
						|
  return !(lhs == rhs);
 | 
						|
}
 | 
						|
 | 
						|
template <int N, int M>
 | 
						|
bool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
 | 
						|
  return Compare(lhs, rhs) == -1;
 | 
						|
}
 | 
						|
 | 
						|
template <int N, int M>
 | 
						|
bool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
 | 
						|
  return rhs < lhs;
 | 
						|
}
 | 
						|
template <int N, int M>
 | 
						|
bool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
 | 
						|
  return !(rhs < lhs);
 | 
						|
}
 | 
						|
template <int N, int M>
 | 
						|
bool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
 | 
						|
  return !(lhs < rhs);
 | 
						|
}
 | 
						|
 | 
						|
// Output operator for BigUnsigned, for testing purposes only.
 | 
						|
template <int N>
 | 
						|
std::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) {
 | 
						|
  return os << num.ToString();
 | 
						|
}
 | 
						|
 | 
						|
// Explicit instantiation declarations for the sizes of BigUnsigned that we
 | 
						|
// are using.
 | 
						|
//
 | 
						|
// For now, the choices of 4 and 84 are arbitrary; 4 is a small value that is
 | 
						|
// still bigger than an int128, and 84 is a large value we will want to use
 | 
						|
// in the from_chars implementation.
 | 
						|
//
 | 
						|
// Comments justifying the use of 84 belong in the from_chars implementation,
 | 
						|
// and will be added in a follow-up CL.
 | 
						|
extern template class BigUnsigned<4>;
 | 
						|
extern template class BigUnsigned<84>;
 | 
						|
 | 
						|
}  // namespace strings_internal
 | 
						|
}  // namespace absl
 | 
						|
 | 
						|
#endif  // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
 |