mfbt/double-conversion/bignum.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mfbt/double-conversion/bignum.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,763 @@
     1.4 +// Copyright 2010 the V8 project authors. All rights reserved.
     1.5 +// Redistribution and use in source and binary forms, with or without
     1.6 +// modification, are permitted provided that the following conditions are
     1.7 +// met:
     1.8 +//
     1.9 +//     * Redistributions of source code must retain the above copyright
    1.10 +//       notice, this list of conditions and the following disclaimer.
    1.11 +//     * Redistributions in binary form must reproduce the above
    1.12 +//       copyright notice, this list of conditions and the following
    1.13 +//       disclaimer in the documentation and/or other materials provided
    1.14 +//       with the distribution.
    1.15 +//     * Neither the name of Google Inc. nor the names of its
    1.16 +//       contributors may be used to endorse or promote products derived
    1.17 +//       from this software without specific prior written permission.
    1.18 +//
    1.19 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.20 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.21 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.22 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.23 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.24 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.25 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.26 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.27 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.28 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.29 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.30 +
    1.31 +#include "bignum.h"
    1.32 +#include "utils.h"
    1.33 +
    1.34 +namespace double_conversion {
    1.35 +
    1.36 +Bignum::Bignum()
    1.37 +    : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
    1.38 +  for (int i = 0; i < kBigitCapacity; ++i) {
    1.39 +    bigits_[i] = 0;
    1.40 +  }
    1.41 +}
    1.42 +
    1.43 +
    1.44 +template<typename S>
    1.45 +static int BitSize(S value) {
    1.46 +  return 8 * sizeof(value);
    1.47 +}
    1.48 +
    1.49 +// Guaranteed to lie in one Bigit.
    1.50 +void Bignum::AssignUInt16(uint16_t value) {
    1.51 +  ASSERT(kBigitSize >= BitSize(value));
    1.52 +  Zero();
    1.53 +  if (value == 0) return;
    1.54 +
    1.55 +  EnsureCapacity(1);
    1.56 +  bigits_[0] = value;
    1.57 +  used_digits_ = 1;
    1.58 +}
    1.59 +
    1.60 +
    1.61 +void Bignum::AssignUInt64(uint64_t value) {
    1.62 +  const int kUInt64Size = 64;
    1.63 +
    1.64 +  Zero();
    1.65 +  if (value == 0) return;
    1.66 +
    1.67 +  int needed_bigits = kUInt64Size / kBigitSize + 1;
    1.68 +  EnsureCapacity(needed_bigits);
    1.69 +  for (int i = 0; i < needed_bigits; ++i) {
    1.70 +    bigits_[i] = value & kBigitMask;
    1.71 +    value = value >> kBigitSize;
    1.72 +  }
    1.73 +  used_digits_ = needed_bigits;
    1.74 +  Clamp();
    1.75 +}
    1.76 +
    1.77 +
    1.78 +void Bignum::AssignBignum(const Bignum& other) {
    1.79 +  exponent_ = other.exponent_;
    1.80 +  for (int i = 0; i < other.used_digits_; ++i) {
    1.81 +    bigits_[i] = other.bigits_[i];
    1.82 +  }
    1.83 +  // Clear the excess digits (if there were any).
    1.84 +  for (int i = other.used_digits_; i < used_digits_; ++i) {
    1.85 +    bigits_[i] = 0;
    1.86 +  }
    1.87 +  used_digits_ = other.used_digits_;
    1.88 +}
    1.89 +
    1.90 +
    1.91 +static uint64_t ReadUInt64(Vector<const char> buffer,
    1.92 +                           int from,
    1.93 +                           int digits_to_read) {
    1.94 +  uint64_t result = 0;
    1.95 +  for (int i = from; i < from + digits_to_read; ++i) {
    1.96 +    int digit = buffer[i] - '0';
    1.97 +    ASSERT(0 <= digit && digit <= 9);
    1.98 +    result = result * 10 + digit;
    1.99 +  }
   1.100 +  return result;
   1.101 +}
   1.102 +
   1.103 +
   1.104 +void Bignum::AssignDecimalString(Vector<const char> value) {
   1.105 +  // 2^64 = 18446744073709551616 > 10^19
   1.106 +  const int kMaxUint64DecimalDigits = 19;
   1.107 +  Zero();
   1.108 +  int length = value.length();
   1.109 +  int pos = 0;
   1.110 +  // Let's just say that each digit needs 4 bits.
   1.111 +  while (length >= kMaxUint64DecimalDigits) {
   1.112 +    uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
   1.113 +    pos += kMaxUint64DecimalDigits;
   1.114 +    length -= kMaxUint64DecimalDigits;
   1.115 +    MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
   1.116 +    AddUInt64(digits);
   1.117 +  }
   1.118 +  uint64_t digits = ReadUInt64(value, pos, length);
   1.119 +  MultiplyByPowerOfTen(length);
   1.120 +  AddUInt64(digits);
   1.121 +  Clamp();
   1.122 +}
   1.123 +
   1.124 +
   1.125 +static int HexCharValue(char c) {
   1.126 +  if ('0' <= c && c <= '9') return c - '0';
   1.127 +  if ('a' <= c && c <= 'f') return 10 + c - 'a';
   1.128 +  if ('A' <= c && c <= 'F') return 10 + c - 'A';
   1.129 +  UNREACHABLE();
   1.130 +  return 0;  // To make compiler happy.
   1.131 +}
   1.132 +
   1.133 +
   1.134 +void Bignum::AssignHexString(Vector<const char> value) {
   1.135 +  Zero();
   1.136 +  int length = value.length();
   1.137 +
   1.138 +  int needed_bigits = length * 4 / kBigitSize + 1;
   1.139 +  EnsureCapacity(needed_bigits);
   1.140 +  int string_index = length - 1;
   1.141 +  for (int i = 0; i < needed_bigits - 1; ++i) {
   1.142 +    // These bigits are guaranteed to be "full".
   1.143 +    Chunk current_bigit = 0;
   1.144 +    for (int j = 0; j < kBigitSize / 4; j++) {
   1.145 +      current_bigit += HexCharValue(value[string_index--]) << (j * 4);
   1.146 +    }
   1.147 +    bigits_[i] = current_bigit;
   1.148 +  }
   1.149 +  used_digits_ = needed_bigits - 1;
   1.150 +
   1.151 +  Chunk most_significant_bigit = 0;  // Could be = 0;
   1.152 +  for (int j = 0; j <= string_index; ++j) {
   1.153 +    most_significant_bigit <<= 4;
   1.154 +    most_significant_bigit += HexCharValue(value[j]);
   1.155 +  }
   1.156 +  if (most_significant_bigit != 0) {
   1.157 +    bigits_[used_digits_] = most_significant_bigit;
   1.158 +    used_digits_++;
   1.159 +  }
   1.160 +  Clamp();
   1.161 +}
   1.162 +
   1.163 +
   1.164 +void Bignum::AddUInt64(uint64_t operand) {
   1.165 +  if (operand == 0) return;
   1.166 +  Bignum other;
   1.167 +  other.AssignUInt64(operand);
   1.168 +  AddBignum(other);
   1.169 +}
   1.170 +
   1.171 +
   1.172 +void Bignum::AddBignum(const Bignum& other) {
   1.173 +  ASSERT(IsClamped());
   1.174 +  ASSERT(other.IsClamped());
   1.175 +
   1.176 +  // If this has a greater exponent than other append zero-bigits to this.
   1.177 +  // After this call exponent_ <= other.exponent_.
   1.178 +  Align(other);
   1.179 +
   1.180 +  // There are two possibilities:
   1.181 +  //   aaaaaaaaaaa 0000  (where the 0s represent a's exponent)
   1.182 +  //     bbbbb 00000000
   1.183 +  //   ----------------
   1.184 +  //   ccccccccccc 0000
   1.185 +  // or
   1.186 +  //    aaaaaaaaaa 0000
   1.187 +  //  bbbbbbbbb 0000000
   1.188 +  //  -----------------
   1.189 +  //  cccccccccccc 0000
   1.190 +  // In both cases we might need a carry bigit.
   1.191 +
   1.192 +  EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_);
   1.193 +  Chunk carry = 0;
   1.194 +  int bigit_pos = other.exponent_ - exponent_;
   1.195 +  ASSERT(bigit_pos >= 0);
   1.196 +  for (int i = 0; i < other.used_digits_; ++i) {
   1.197 +    Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry;
   1.198 +    bigits_[bigit_pos] = sum & kBigitMask;
   1.199 +    carry = sum >> kBigitSize;
   1.200 +    bigit_pos++;
   1.201 +  }
   1.202 +
   1.203 +  while (carry != 0) {
   1.204 +    Chunk sum = bigits_[bigit_pos] + carry;
   1.205 +    bigits_[bigit_pos] = sum & kBigitMask;
   1.206 +    carry = sum >> kBigitSize;
   1.207 +    bigit_pos++;
   1.208 +  }
   1.209 +  used_digits_ = Max(bigit_pos, used_digits_);
   1.210 +  ASSERT(IsClamped());
   1.211 +}
   1.212 +
   1.213 +
   1.214 +void Bignum::SubtractBignum(const Bignum& other) {
   1.215 +  ASSERT(IsClamped());
   1.216 +  ASSERT(other.IsClamped());
   1.217 +  // We require this to be bigger than other.
   1.218 +  ASSERT(LessEqual(other, *this));
   1.219 +
   1.220 +  Align(other);
   1.221 +
   1.222 +  int offset = other.exponent_ - exponent_;
   1.223 +  Chunk borrow = 0;
   1.224 +  int i;
   1.225 +  for (i = 0; i < other.used_digits_; ++i) {
   1.226 +    ASSERT((borrow == 0) || (borrow == 1));
   1.227 +    Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow;
   1.228 +    bigits_[i + offset] = difference & kBigitMask;
   1.229 +    borrow = difference >> (kChunkSize - 1);
   1.230 +  }
   1.231 +  while (borrow != 0) {
   1.232 +    Chunk difference = bigits_[i + offset] - borrow;
   1.233 +    bigits_[i + offset] = difference & kBigitMask;
   1.234 +    borrow = difference >> (kChunkSize - 1);
   1.235 +    ++i;
   1.236 +  }
   1.237 +  Clamp();
   1.238 +}
   1.239 +
   1.240 +
   1.241 +void Bignum::ShiftLeft(int shift_amount) {
   1.242 +  if (used_digits_ == 0) return;
   1.243 +  exponent_ += shift_amount / kBigitSize;
   1.244 +  int local_shift = shift_amount % kBigitSize;
   1.245 +  EnsureCapacity(used_digits_ + 1);
   1.246 +  BigitsShiftLeft(local_shift);
   1.247 +}
   1.248 +
   1.249 +
   1.250 +void Bignum::MultiplyByUInt32(uint32_t factor) {
   1.251 +  if (factor == 1) return;
   1.252 +  if (factor == 0) {
   1.253 +    Zero();
   1.254 +    return;
   1.255 +  }
   1.256 +  if (used_digits_ == 0) return;
   1.257 +
   1.258 +  // The product of a bigit with the factor is of size kBigitSize + 32.
   1.259 +  // Assert that this number + 1 (for the carry) fits into double chunk.
   1.260 +  ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
   1.261 +  DoubleChunk carry = 0;
   1.262 +  for (int i = 0; i < used_digits_; ++i) {
   1.263 +    DoubleChunk product = static_cast<DoubleChunk>(factor) * bigits_[i] + carry;
   1.264 +    bigits_[i] = static_cast<Chunk>(product & kBigitMask);
   1.265 +    carry = (product >> kBigitSize);
   1.266 +  }
   1.267 +  while (carry != 0) {
   1.268 +    EnsureCapacity(used_digits_ + 1);
   1.269 +    bigits_[used_digits_] = carry & kBigitMask;
   1.270 +    used_digits_++;
   1.271 +    carry >>= kBigitSize;
   1.272 +  }
   1.273 +}
   1.274 +
   1.275 +
   1.276 +void Bignum::MultiplyByUInt64(uint64_t factor) {
   1.277 +  if (factor == 1) return;
   1.278 +  if (factor == 0) {
   1.279 +    Zero();
   1.280 +    return;
   1.281 +  }
   1.282 +  ASSERT(kBigitSize < 32);
   1.283 +  uint64_t carry = 0;
   1.284 +  uint64_t low = factor & 0xFFFFFFFF;
   1.285 +  uint64_t high = factor >> 32;
   1.286 +  for (int i = 0; i < used_digits_; ++i) {
   1.287 +    uint64_t product_low = low * bigits_[i];
   1.288 +    uint64_t product_high = high * bigits_[i];
   1.289 +    uint64_t tmp = (carry & kBigitMask) + product_low;
   1.290 +    bigits_[i] = tmp & kBigitMask;
   1.291 +    carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
   1.292 +        (product_high << (32 - kBigitSize));
   1.293 +  }
   1.294 +  while (carry != 0) {
   1.295 +    EnsureCapacity(used_digits_ + 1);
   1.296 +    bigits_[used_digits_] = carry & kBigitMask;
   1.297 +    used_digits_++;
   1.298 +    carry >>= kBigitSize;
   1.299 +  }
   1.300 +}
   1.301 +
   1.302 +
   1.303 +void Bignum::MultiplyByPowerOfTen(int exponent) {
   1.304 +  const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d);
   1.305 +  const uint16_t kFive1 = 5;
   1.306 +  const uint16_t kFive2 = kFive1 * 5;
   1.307 +  const uint16_t kFive3 = kFive2 * 5;
   1.308 +  const uint16_t kFive4 = kFive3 * 5;
   1.309 +  const uint16_t kFive5 = kFive4 * 5;
   1.310 +  const uint16_t kFive6 = kFive5 * 5;
   1.311 +  const uint32_t kFive7 = kFive6 * 5;
   1.312 +  const uint32_t kFive8 = kFive7 * 5;
   1.313 +  const uint32_t kFive9 = kFive8 * 5;
   1.314 +  const uint32_t kFive10 = kFive9 * 5;
   1.315 +  const uint32_t kFive11 = kFive10 * 5;
   1.316 +  const uint32_t kFive12 = kFive11 * 5;
   1.317 +  const uint32_t kFive13 = kFive12 * 5;
   1.318 +  const uint32_t kFive1_to_12[] =
   1.319 +      { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6,
   1.320 +        kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 };
   1.321 +
   1.322 +  ASSERT(exponent >= 0);
   1.323 +  if (exponent == 0) return;
   1.324 +  if (used_digits_ == 0) return;
   1.325 +
   1.326 +  // We shift by exponent at the end just before returning.
   1.327 +  int remaining_exponent = exponent;
   1.328 +  while (remaining_exponent >= 27) {
   1.329 +    MultiplyByUInt64(kFive27);
   1.330 +    remaining_exponent -= 27;
   1.331 +  }
   1.332 +  while (remaining_exponent >= 13) {
   1.333 +    MultiplyByUInt32(kFive13);
   1.334 +    remaining_exponent -= 13;
   1.335 +  }
   1.336 +  if (remaining_exponent > 0) {
   1.337 +    MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]);
   1.338 +  }
   1.339 +  ShiftLeft(exponent);
   1.340 +}
   1.341 +
   1.342 +
   1.343 +void Bignum::Square() {
   1.344 +  ASSERT(IsClamped());
   1.345 +  int product_length = 2 * used_digits_;
   1.346 +  EnsureCapacity(product_length);
   1.347 +
   1.348 +  // Comba multiplication: compute each column separately.
   1.349 +  // Example: r = a2a1a0 * b2b1b0.
   1.350 +  //    r =  1    * a0b0 +
   1.351 +  //        10    * (a1b0 + a0b1) +
   1.352 +  //        100   * (a2b0 + a1b1 + a0b2) +
   1.353 +  //        1000  * (a2b1 + a1b2) +
   1.354 +  //        10000 * a2b2
   1.355 +  //
   1.356 +  // In the worst case we have to accumulate nb-digits products of digit*digit.
   1.357 +  //
   1.358 +  // Assert that the additional number of bits in a DoubleChunk are enough to
   1.359 +  // sum up used_digits of Bigit*Bigit.
   1.360 +  if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) {
   1.361 +    UNIMPLEMENTED();
   1.362 +  }
   1.363 +  DoubleChunk accumulator = 0;
   1.364 +  // First shift the digits so we don't overwrite them.
   1.365 +  int copy_offset = used_digits_;
   1.366 +  for (int i = 0; i < used_digits_; ++i) {
   1.367 +    bigits_[copy_offset + i] = bigits_[i];
   1.368 +  }
   1.369 +  // We have two loops to avoid some 'if's in the loop.
   1.370 +  for (int i = 0; i < used_digits_; ++i) {
   1.371 +    // Process temporary digit i with power i.
   1.372 +    // The sum of the two indices must be equal to i.
   1.373 +    int bigit_index1 = i;
   1.374 +    int bigit_index2 = 0;
   1.375 +    // Sum all of the sub-products.
   1.376 +    while (bigit_index1 >= 0) {
   1.377 +      Chunk chunk1 = bigits_[copy_offset + bigit_index1];
   1.378 +      Chunk chunk2 = bigits_[copy_offset + bigit_index2];
   1.379 +      accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
   1.380 +      bigit_index1--;
   1.381 +      bigit_index2++;
   1.382 +    }
   1.383 +    bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
   1.384 +    accumulator >>= kBigitSize;
   1.385 +  }
   1.386 +  for (int i = used_digits_; i < product_length; ++i) {
   1.387 +    int bigit_index1 = used_digits_ - 1;
   1.388 +    int bigit_index2 = i - bigit_index1;
   1.389 +    // Invariant: sum of both indices is again equal to i.
   1.390 +    // Inner loop runs 0 times on last iteration, emptying accumulator.
   1.391 +    while (bigit_index2 < used_digits_) {
   1.392 +      Chunk chunk1 = bigits_[copy_offset + bigit_index1];
   1.393 +      Chunk chunk2 = bigits_[copy_offset + bigit_index2];
   1.394 +      accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
   1.395 +      bigit_index1--;
   1.396 +      bigit_index2++;
   1.397 +    }
   1.398 +    // The overwritten bigits_[i] will never be read in further loop iterations,
   1.399 +    // because bigit_index1 and bigit_index2 are always greater
   1.400 +    // than i - used_digits_.
   1.401 +    bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
   1.402 +    accumulator >>= kBigitSize;
   1.403 +  }
   1.404 +  // Since the result was guaranteed to lie inside the number the
   1.405 +  // accumulator must be 0 now.
   1.406 +  ASSERT(accumulator == 0);
   1.407 +
   1.408 +  // Don't forget to update the used_digits and the exponent.
   1.409 +  used_digits_ = product_length;
   1.410 +  exponent_ *= 2;
   1.411 +  Clamp();
   1.412 +}
   1.413 +
   1.414 +
   1.415 +void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
   1.416 +  ASSERT(base != 0);
   1.417 +  ASSERT(power_exponent >= 0);
   1.418 +  if (power_exponent == 0) {
   1.419 +    AssignUInt16(1);
   1.420 +    return;
   1.421 +  }
   1.422 +  Zero();
   1.423 +  int shifts = 0;
   1.424 +  // We expect base to be in range 2-32, and most often to be 10.
   1.425 +  // It does not make much sense to implement different algorithms for counting
   1.426 +  // the bits.
   1.427 +  while ((base & 1) == 0) {
   1.428 +    base >>= 1;
   1.429 +    shifts++;
   1.430 +  }
   1.431 +  int bit_size = 0;
   1.432 +  int tmp_base = base;
   1.433 +  while (tmp_base != 0) {
   1.434 +    tmp_base >>= 1;
   1.435 +    bit_size++;
   1.436 +  }
   1.437 +  int final_size = bit_size * power_exponent;
   1.438 +  // 1 extra bigit for the shifting, and one for rounded final_size.
   1.439 +  EnsureCapacity(final_size / kBigitSize + 2);
   1.440 +
   1.441 +  // Left to Right exponentiation.
   1.442 +  int mask = 1;
   1.443 +  while (power_exponent >= mask) mask <<= 1;
   1.444 +
   1.445 +  // The mask is now pointing to the bit above the most significant 1-bit of
   1.446 +  // power_exponent.
   1.447 +  // Get rid of first 1-bit;
   1.448 +  mask >>= 2;
   1.449 +  uint64_t this_value = base;
   1.450 +
   1.451 +  bool delayed_multipliciation = false;
   1.452 +  const uint64_t max_32bits = 0xFFFFFFFF;
   1.453 +  while (mask != 0 && this_value <= max_32bits) {
   1.454 +    this_value = this_value * this_value;
   1.455 +    // Verify that there is enough space in this_value to perform the
   1.456 +    // multiplication.  The first bit_size bits must be 0.
   1.457 +    if ((power_exponent & mask) != 0) {
   1.458 +      uint64_t base_bits_mask =
   1.459 +          ~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
   1.460 +      bool high_bits_zero = (this_value & base_bits_mask) == 0;
   1.461 +      if (high_bits_zero) {
   1.462 +        this_value *= base;
   1.463 +      } else {
   1.464 +        delayed_multipliciation = true;
   1.465 +      }
   1.466 +    }
   1.467 +    mask >>= 1;
   1.468 +  }
   1.469 +  AssignUInt64(this_value);
   1.470 +  if (delayed_multipliciation) {
   1.471 +    MultiplyByUInt32(base);
   1.472 +  }
   1.473 +
   1.474 +  // Now do the same thing as a bignum.
   1.475 +  while (mask != 0) {
   1.476 +    Square();
   1.477 +    if ((power_exponent & mask) != 0) {
   1.478 +      MultiplyByUInt32(base);
   1.479 +    }
   1.480 +    mask >>= 1;
   1.481 +  }
   1.482 +
   1.483 +  // And finally add the saved shifts.
   1.484 +  ShiftLeft(shifts * power_exponent);
   1.485 +}
   1.486 +
   1.487 +
   1.488 +// Precondition: this/other < 16bit.
   1.489 +uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
   1.490 +  ASSERT(IsClamped());
   1.491 +  ASSERT(other.IsClamped());
   1.492 +  ASSERT(other.used_digits_ > 0);
   1.493 +
   1.494 +  // Easy case: if we have less digits than the divisor than the result is 0.
   1.495 +  // Note: this handles the case where this == 0, too.
   1.496 +  if (BigitLength() < other.BigitLength()) {
   1.497 +    return 0;
   1.498 +  }
   1.499 +
   1.500 +  Align(other);
   1.501 +
   1.502 +  uint16_t result = 0;
   1.503 +
   1.504 +  // Start by removing multiples of 'other' until both numbers have the same
   1.505 +  // number of digits.
   1.506 +  while (BigitLength() > other.BigitLength()) {
   1.507 +    // This naive approach is extremely inefficient if `this` divided by other
   1.508 +    // is big. This function is implemented for doubleToString where
   1.509 +    // the result should be small (less than 10).
   1.510 +    ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16));
   1.511 +    // Remove the multiples of the first digit.
   1.512 +    // Example this = 23 and other equals 9. -> Remove 2 multiples.
   1.513 +    result += bigits_[used_digits_ - 1];
   1.514 +    SubtractTimes(other, bigits_[used_digits_ - 1]);
   1.515 +  }
   1.516 +
   1.517 +  ASSERT(BigitLength() == other.BigitLength());
   1.518 +
   1.519 +  // Both bignums are at the same length now.
   1.520 +  // Since other has more than 0 digits we know that the access to
   1.521 +  // bigits_[used_digits_ - 1] is safe.
   1.522 +  Chunk this_bigit = bigits_[used_digits_ - 1];
   1.523 +  Chunk other_bigit = other.bigits_[other.used_digits_ - 1];
   1.524 +
   1.525 +  if (other.used_digits_ == 1) {
   1.526 +    // Shortcut for easy (and common) case.
   1.527 +    int quotient = this_bigit / other_bigit;
   1.528 +    bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;
   1.529 +    result += quotient;
   1.530 +    Clamp();
   1.531 +    return result;
   1.532 +  }
   1.533 +
   1.534 +  int division_estimate = this_bigit / (other_bigit + 1);
   1.535 +  result += division_estimate;
   1.536 +  SubtractTimes(other, division_estimate);
   1.537 +
   1.538 +  if (other_bigit * (division_estimate + 1) > this_bigit) {
   1.539 +    // No need to even try to subtract. Even if other's remaining digits were 0
   1.540 +    // another subtraction would be too much.
   1.541 +    return result;
   1.542 +  }
   1.543 +
   1.544 +  while (LessEqual(other, *this)) {
   1.545 +    SubtractBignum(other);
   1.546 +    result++;
   1.547 +  }
   1.548 +  return result;
   1.549 +}
   1.550 +
   1.551 +
   1.552 +template<typename S>
   1.553 +static int SizeInHexChars(S number) {
   1.554 +  ASSERT(number > 0);
   1.555 +  int result = 0;
   1.556 +  while (number != 0) {
   1.557 +    number >>= 4;
   1.558 +    result++;
   1.559 +  }
   1.560 +  return result;
   1.561 +}
   1.562 +
   1.563 +
   1.564 +static char HexCharOfValue(int value) {
   1.565 +  ASSERT(0 <= value && value <= 16);
   1.566 +  if (value < 10) return value + '0';
   1.567 +  return value - 10 + 'A';
   1.568 +}
   1.569 +
   1.570 +
   1.571 +bool Bignum::ToHexString(char* buffer, int buffer_size) const {
   1.572 +  ASSERT(IsClamped());
   1.573 +  // Each bigit must be printable as separate hex-character.
   1.574 +  ASSERT(kBigitSize % 4 == 0);
   1.575 +  const int kHexCharsPerBigit = kBigitSize / 4;
   1.576 +
   1.577 +  if (used_digits_ == 0) {
   1.578 +    if (buffer_size < 2) return false;
   1.579 +    buffer[0] = '0';
   1.580 +    buffer[1] = '\0';
   1.581 +    return true;
   1.582 +  }
   1.583 +  // We add 1 for the terminating '\0' character.
   1.584 +  int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
   1.585 +      SizeInHexChars(bigits_[used_digits_ - 1]) + 1;
   1.586 +  if (needed_chars > buffer_size) return false;
   1.587 +  int string_index = needed_chars - 1;
   1.588 +  buffer[string_index--] = '\0';
   1.589 +  for (int i = 0; i < exponent_; ++i) {
   1.590 +    for (int j = 0; j < kHexCharsPerBigit; ++j) {
   1.591 +      buffer[string_index--] = '0';
   1.592 +    }
   1.593 +  }
   1.594 +  for (int i = 0; i < used_digits_ - 1; ++i) {
   1.595 +    Chunk current_bigit = bigits_[i];
   1.596 +    for (int j = 0; j < kHexCharsPerBigit; ++j) {
   1.597 +      buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);
   1.598 +      current_bigit >>= 4;
   1.599 +    }
   1.600 +  }
   1.601 +  // And finally the last bigit.
   1.602 +  Chunk most_significant_bigit = bigits_[used_digits_ - 1];
   1.603 +  while (most_significant_bigit != 0) {
   1.604 +    buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
   1.605 +    most_significant_bigit >>= 4;
   1.606 +  }
   1.607 +  return true;
   1.608 +}
   1.609 +
   1.610 +
   1.611 +Bignum::Chunk Bignum::BigitAt(int index) const {
   1.612 +  if (index >= BigitLength()) return 0;
   1.613 +  if (index < exponent_) return 0;
   1.614 +  return bigits_[index - exponent_];
   1.615 +}
   1.616 +
   1.617 +
   1.618 +int Bignum::Compare(const Bignum& a, const Bignum& b) {
   1.619 +  ASSERT(a.IsClamped());
   1.620 +  ASSERT(b.IsClamped());
   1.621 +  int bigit_length_a = a.BigitLength();
   1.622 +  int bigit_length_b = b.BigitLength();
   1.623 +  if (bigit_length_a < bigit_length_b) return -1;
   1.624 +  if (bigit_length_a > bigit_length_b) return +1;
   1.625 +  for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) {
   1.626 +    Chunk bigit_a = a.BigitAt(i);
   1.627 +    Chunk bigit_b = b.BigitAt(i);
   1.628 +    if (bigit_a < bigit_b) return -1;
   1.629 +    if (bigit_a > bigit_b) return +1;
   1.630 +    // Otherwise they are equal up to this digit. Try the next digit.
   1.631 +  }
   1.632 +  return 0;
   1.633 +}
   1.634 +
   1.635 +
   1.636 +int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
   1.637 +  ASSERT(a.IsClamped());
   1.638 +  ASSERT(b.IsClamped());
   1.639 +  ASSERT(c.IsClamped());
   1.640 +  if (a.BigitLength() < b.BigitLength()) {
   1.641 +    return PlusCompare(b, a, c);
   1.642 +  }
   1.643 +  if (a.BigitLength() + 1 < c.BigitLength()) return -1;
   1.644 +  if (a.BigitLength() > c.BigitLength()) return +1;
   1.645 +  // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than
   1.646 +  // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one
   1.647 +  // of 'a'.
   1.648 +  if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) {
   1.649 +    return -1;
   1.650 +  }
   1.651 +
   1.652 +  Chunk borrow = 0;
   1.653 +  // Starting at min_exponent all digits are == 0. So no need to compare them.
   1.654 +  int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_);
   1.655 +  for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {
   1.656 +    Chunk chunk_a = a.BigitAt(i);
   1.657 +    Chunk chunk_b = b.BigitAt(i);
   1.658 +    Chunk chunk_c = c.BigitAt(i);
   1.659 +    Chunk sum = chunk_a + chunk_b;
   1.660 +    if (sum > chunk_c + borrow) {
   1.661 +      return +1;
   1.662 +    } else {
   1.663 +      borrow = chunk_c + borrow - sum;
   1.664 +      if (borrow > 1) return -1;
   1.665 +      borrow <<= kBigitSize;
   1.666 +    }
   1.667 +  }
   1.668 +  if (borrow == 0) return 0;
   1.669 +  return -1;
   1.670 +}
   1.671 +
   1.672 +
   1.673 +void Bignum::Clamp() {
   1.674 +  while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) {
   1.675 +    used_digits_--;
   1.676 +  }
   1.677 +  if (used_digits_ == 0) {
   1.678 +    // Zero.
   1.679 +    exponent_ = 0;
   1.680 +  }
   1.681 +}
   1.682 +
   1.683 +
   1.684 +bool Bignum::IsClamped() const {
   1.685 +  return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0;
   1.686 +}
   1.687 +
   1.688 +
   1.689 +void Bignum::Zero() {
   1.690 +  for (int i = 0; i < used_digits_; ++i) {
   1.691 +    bigits_[i] = 0;
   1.692 +  }
   1.693 +  used_digits_ = 0;
   1.694 +  exponent_ = 0;
   1.695 +}
   1.696 +
   1.697 +
   1.698 +void Bignum::Align(const Bignum& other) {
   1.699 +  if (exponent_ > other.exponent_) {
   1.700 +    // If "X" represents a "hidden" digit (by the exponent) then we are in the
   1.701 +    // following case (a == this, b == other):
   1.702 +    // a:  aaaaaaXXXX   or a:   aaaaaXXX
   1.703 +    // b:     bbbbbbX      b: bbbbbbbbXX
   1.704 +    // We replace some of the hidden digits (X) of a with 0 digits.
   1.705 +    // a:  aaaaaa000X   or a:   aaaaa0XX
   1.706 +    int zero_digits = exponent_ - other.exponent_;
   1.707 +    EnsureCapacity(used_digits_ + zero_digits);
   1.708 +    for (int i = used_digits_ - 1; i >= 0; --i) {
   1.709 +      bigits_[i + zero_digits] = bigits_[i];
   1.710 +    }
   1.711 +    for (int i = 0; i < zero_digits; ++i) {
   1.712 +      bigits_[i] = 0;
   1.713 +    }
   1.714 +    used_digits_ += zero_digits;
   1.715 +    exponent_ -= zero_digits;
   1.716 +    ASSERT(used_digits_ >= 0);
   1.717 +    ASSERT(exponent_ >= 0);
   1.718 +  }
   1.719 +}
   1.720 +
   1.721 +
   1.722 +void Bignum::BigitsShiftLeft(int shift_amount) {
   1.723 +  ASSERT(shift_amount < kBigitSize);
   1.724 +  ASSERT(shift_amount >= 0);
   1.725 +  Chunk carry = 0;
   1.726 +  for (int i = 0; i < used_digits_; ++i) {
   1.727 +    Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount);
   1.728 +    bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask;
   1.729 +    carry = new_carry;
   1.730 +  }
   1.731 +  if (carry != 0) {
   1.732 +    bigits_[used_digits_] = carry;
   1.733 +    used_digits_++;
   1.734 +  }
   1.735 +}
   1.736 +
   1.737 +
   1.738 +void Bignum::SubtractTimes(const Bignum& other, int factor) {
   1.739 +  ASSERT(exponent_ <= other.exponent_);
   1.740 +  if (factor < 3) {
   1.741 +    for (int i = 0; i < factor; ++i) {
   1.742 +      SubtractBignum(other);
   1.743 +    }
   1.744 +    return;
   1.745 +  }
   1.746 +  Chunk borrow = 0;
   1.747 +  int exponent_diff = other.exponent_ - exponent_;
   1.748 +  for (int i = 0; i < other.used_digits_; ++i) {
   1.749 +    DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i];
   1.750 +    DoubleChunk remove = borrow + product;
   1.751 +    Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask);
   1.752 +    bigits_[i + exponent_diff] = difference & kBigitMask;
   1.753 +    borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) +
   1.754 +                                (remove >> kBigitSize));
   1.755 +  }
   1.756 +  for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) {
   1.757 +    if (borrow == 0) return;
   1.758 +    Chunk difference = bigits_[i] - borrow;
   1.759 +    bigits_[i] = difference & kBigitMask;
   1.760 +    borrow = difference >> (kChunkSize - 1);
   1.761 +  }
   1.762 +  Clamp();
   1.763 +}
   1.764 +
   1.765 +
   1.766 +}  // namespace double_conversion

mercurial