11cb0ef41Sopenharmony_ci// Copyright 2021 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/bigint/bigint-internal.h"
61cb0ef41Sopenharmony_ci#include "src/bigint/vector-arithmetic.h"
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_cinamespace v8 {
91cb0ef41Sopenharmony_cinamespace bigint {
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci// The classic algorithm: for every part, multiply the accumulator with
121cb0ef41Sopenharmony_ci// the appropriate multiplier, and add the part. O(n²) overall.
131cb0ef41Sopenharmony_civoid ProcessorImpl::FromStringClassic(RWDigits Z,
141cb0ef41Sopenharmony_ci                                      FromStringAccumulator* accumulator) {
151cb0ef41Sopenharmony_ci  // We always have at least one part to process.
161cb0ef41Sopenharmony_ci  DCHECK(accumulator->stack_parts_used_ > 0);
171cb0ef41Sopenharmony_ci  Z[0] = accumulator->stack_parts_[0];
181cb0ef41Sopenharmony_ci  RWDigits already_set(Z, 0, 1);
191cb0ef41Sopenharmony_ci  for (int i = 1; i < Z.len(); i++) Z[i] = 0;
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  // The {FromStringAccumulator} uses stack-allocated storage for the first
221cb0ef41Sopenharmony_ci  // few parts; if heap storage is used at all then all parts are copied there.
231cb0ef41Sopenharmony_ci  int num_stack_parts = accumulator->stack_parts_used_;
241cb0ef41Sopenharmony_ci  if (num_stack_parts == 1) return;
251cb0ef41Sopenharmony_ci  const std::vector<digit_t>& heap_parts = accumulator->heap_parts_;
261cb0ef41Sopenharmony_ci  int num_heap_parts = static_cast<int>(heap_parts.size());
271cb0ef41Sopenharmony_ci  // All multipliers are the same, except possibly for the last.
281cb0ef41Sopenharmony_ci  const digit_t max_multiplier = accumulator->max_multiplier_;
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci  if (num_heap_parts == 0) {
311cb0ef41Sopenharmony_ci    for (int i = 1; i < num_stack_parts - 1; i++) {
321cb0ef41Sopenharmony_ci      MultiplySingle(Z, already_set, max_multiplier);
331cb0ef41Sopenharmony_ci      Add(Z, accumulator->stack_parts_[i]);
341cb0ef41Sopenharmony_ci      already_set.set_len(already_set.len() + 1);
351cb0ef41Sopenharmony_ci    }
361cb0ef41Sopenharmony_ci    MultiplySingle(Z, already_set, accumulator->last_multiplier_);
371cb0ef41Sopenharmony_ci    Add(Z, accumulator->stack_parts_[num_stack_parts - 1]);
381cb0ef41Sopenharmony_ci    return;
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci  // Parts are stored on the heap.
411cb0ef41Sopenharmony_ci  for (int i = 1; i < num_heap_parts - 1; i++) {
421cb0ef41Sopenharmony_ci    MultiplySingle(Z, already_set, max_multiplier);
431cb0ef41Sopenharmony_ci    Add(Z, accumulator->heap_parts_[i]);
441cb0ef41Sopenharmony_ci    already_set.set_len(already_set.len() + 1);
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci  MultiplySingle(Z, already_set, accumulator->last_multiplier_);
471cb0ef41Sopenharmony_ci  Add(Z, accumulator->heap_parts_.back());
481cb0ef41Sopenharmony_ci}
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci// The fast algorithm: combine parts in a balanced-binary-tree like order:
511cb0ef41Sopenharmony_ci// Multiply-and-add neighboring pairs of parts, then loop, until only one
521cb0ef41Sopenharmony_ci// part is left. The benefit is that the multiplications will have inputs of
531cb0ef41Sopenharmony_ci// similar sizes, which makes them amenable to fast multiplication algorithms.
541cb0ef41Sopenharmony_ci// We have to do more multiplications than the classic algorithm though,
551cb0ef41Sopenharmony_ci// because we also have to multiply the multipliers.
561cb0ef41Sopenharmony_ci// Optimizations:
571cb0ef41Sopenharmony_ci// - We can skip the multiplier for the first part, because we never need it.
581cb0ef41Sopenharmony_ci// - Most multipliers are the same; we can avoid repeated multiplications and
591cb0ef41Sopenharmony_ci//   just copy the previous result. (In theory we could even de-dupe them, but
601cb0ef41Sopenharmony_ci//   as the parts/multipliers grow, we'll need most of the memory anyway.)
611cb0ef41Sopenharmony_ci//   Copied results are marked with a * below.
621cb0ef41Sopenharmony_ci// - We can re-use memory using a system of three buffers whose usage rotates:
631cb0ef41Sopenharmony_ci//   - one is considered empty, and is overwritten with the new parts,
641cb0ef41Sopenharmony_ci//   - one holds the multipliers (and will be "empty" in the next round), and
651cb0ef41Sopenharmony_ci//   - one initially holds the parts and is overwritten with the new multipliers
661cb0ef41Sopenharmony_ci//   Parts and multipliers both grow in each iteration, and get fewer, so we
671cb0ef41Sopenharmony_ci//   use the space of two adjacent old chunks for one new chunk.
681cb0ef41Sopenharmony_ci//   Since the {heap_parts_} vectors has the right size, and so does the
691cb0ef41Sopenharmony_ci//   result {Z}, we can use that memory, and only need to allocate one scratch
701cb0ef41Sopenharmony_ci//   vector. If the final result ends up in the wrong bucket, we have to copy it
711cb0ef41Sopenharmony_ci//   to the correct one.
721cb0ef41Sopenharmony_ci// - We don't have to keep track of the positions and sizes of the chunks,
731cb0ef41Sopenharmony_ci//   because we can deduce their precise placement from the iteration index.
741cb0ef41Sopenharmony_ci//
751cb0ef41Sopenharmony_ci// Example, assuming digit_t is 4 bits, fitting one decimal digit:
761cb0ef41Sopenharmony_ci// Initial state:
771cb0ef41Sopenharmony_ci// parts_:        1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
781cb0ef41Sopenharmony_ci// multipliers_: 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
791cb0ef41Sopenharmony_ci// After the first iteration of the outer loop:
801cb0ef41Sopenharmony_ci// parts:         12    34    56    78    90    12    34    5
811cb0ef41Sopenharmony_ci// multipliers:        100  *100  *100  *100  *100  *100   10
821cb0ef41Sopenharmony_ci// After the second iteration:
831cb0ef41Sopenharmony_ci// parts:         1234        5678        9012        345
841cb0ef41Sopenharmony_ci// multipliers:              10000      *10000       1000
851cb0ef41Sopenharmony_ci// After the third iteration:
861cb0ef41Sopenharmony_ci// parts:         12345678                9012345
871cb0ef41Sopenharmony_ci// multipliers:                          10000000
881cb0ef41Sopenharmony_ci// And then there's an obvious last iteration.
891cb0ef41Sopenharmony_civoid ProcessorImpl::FromStringLarge(RWDigits Z,
901cb0ef41Sopenharmony_ci                                    FromStringAccumulator* accumulator) {
911cb0ef41Sopenharmony_ci  int num_parts = static_cast<int>(accumulator->heap_parts_.size());
921cb0ef41Sopenharmony_ci  DCHECK(num_parts >= 2);
931cb0ef41Sopenharmony_ci  DCHECK(Z.len() >= num_parts);
941cb0ef41Sopenharmony_ci  RWDigits parts(accumulator->heap_parts_.data(), num_parts);
951cb0ef41Sopenharmony_ci  Storage multipliers_storage(num_parts);
961cb0ef41Sopenharmony_ci  RWDigits multipliers(multipliers_storage.get(), num_parts);
971cb0ef41Sopenharmony_ci  RWDigits temp(Z, 0, num_parts);
981cb0ef41Sopenharmony_ci  // Unrolled and specialized first iteration: part_len == 1, so instead of
991cb0ef41Sopenharmony_ci  // Digits sub-vectors we have individual digit_t values, and the multipliers
1001cb0ef41Sopenharmony_ci  // are known up front.
1011cb0ef41Sopenharmony_ci  {
1021cb0ef41Sopenharmony_ci    digit_t max_multiplier = accumulator->max_multiplier_;
1031cb0ef41Sopenharmony_ci    digit_t last_multiplier = accumulator->last_multiplier_;
1041cb0ef41Sopenharmony_ci    RWDigits new_parts = temp;
1051cb0ef41Sopenharmony_ci    RWDigits new_multipliers = parts;
1061cb0ef41Sopenharmony_ci    int i = 0;
1071cb0ef41Sopenharmony_ci    for (; i + 1 < num_parts; i += 2) {
1081cb0ef41Sopenharmony_ci      digit_t p_in = parts[i];
1091cb0ef41Sopenharmony_ci      digit_t p_in2 = parts[i + 1];
1101cb0ef41Sopenharmony_ci      digit_t m_in = max_multiplier;
1111cb0ef41Sopenharmony_ci      digit_t m_in2 = i == num_parts - 2 ? last_multiplier : max_multiplier;
1121cb0ef41Sopenharmony_ci      // p[j] = p[i] * m[i+1] + p[i+1]
1131cb0ef41Sopenharmony_ci      digit_t p_high;
1141cb0ef41Sopenharmony_ci      digit_t p_low = digit_mul(p_in, m_in2, &p_high);
1151cb0ef41Sopenharmony_ci      digit_t carry;
1161cb0ef41Sopenharmony_ci      new_parts[i] = digit_add2(p_low, p_in2, &carry);
1171cb0ef41Sopenharmony_ci      new_parts[i + 1] = p_high + carry;
1181cb0ef41Sopenharmony_ci      // m[j] = m[i] * m[i+1]
1191cb0ef41Sopenharmony_ci      if (i > 0) {
1201cb0ef41Sopenharmony_ci        if (i > 2 && m_in2 != last_multiplier) {
1211cb0ef41Sopenharmony_ci          new_multipliers[i] = new_multipliers[i - 2];
1221cb0ef41Sopenharmony_ci          new_multipliers[i + 1] = new_multipliers[i - 1];
1231cb0ef41Sopenharmony_ci        } else {
1241cb0ef41Sopenharmony_ci          digit_t m_high;
1251cb0ef41Sopenharmony_ci          new_multipliers[i] = digit_mul(m_in, m_in2, &m_high);
1261cb0ef41Sopenharmony_ci          new_multipliers[i + 1] = m_high;
1271cb0ef41Sopenharmony_ci        }
1281cb0ef41Sopenharmony_ci      }
1291cb0ef41Sopenharmony_ci    }
1301cb0ef41Sopenharmony_ci    // Trailing last part (if {num_parts} was odd).
1311cb0ef41Sopenharmony_ci    if (i < num_parts) {
1321cb0ef41Sopenharmony_ci      new_parts[i] = parts[i];
1331cb0ef41Sopenharmony_ci      new_multipliers[i] = last_multiplier;
1341cb0ef41Sopenharmony_ci      i += 2;
1351cb0ef41Sopenharmony_ci    }
1361cb0ef41Sopenharmony_ci    num_parts = i >> 1;
1371cb0ef41Sopenharmony_ci    RWDigits new_temp = multipliers;
1381cb0ef41Sopenharmony_ci    parts = new_parts;
1391cb0ef41Sopenharmony_ci    multipliers = new_multipliers;
1401cb0ef41Sopenharmony_ci    temp = new_temp;
1411cb0ef41Sopenharmony_ci    AddWorkEstimate(num_parts);
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci  int part_len = 2;
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  // Remaining iterations.
1461cb0ef41Sopenharmony_ci  while (num_parts > 1) {
1471cb0ef41Sopenharmony_ci    RWDigits new_parts = temp;
1481cb0ef41Sopenharmony_ci    RWDigits new_multipliers = parts;
1491cb0ef41Sopenharmony_ci    int new_part_len = part_len * 2;
1501cb0ef41Sopenharmony_ci    int i = 0;
1511cb0ef41Sopenharmony_ci    for (; i + 1 < num_parts; i += 2) {
1521cb0ef41Sopenharmony_ci      int start = i * part_len;
1531cb0ef41Sopenharmony_ci      Digits p_in(parts, start, part_len);
1541cb0ef41Sopenharmony_ci      Digits p_in2(parts, start + part_len, part_len);
1551cb0ef41Sopenharmony_ci      Digits m_in(multipliers, start, part_len);
1561cb0ef41Sopenharmony_ci      Digits m_in2(multipliers, start + part_len, part_len);
1571cb0ef41Sopenharmony_ci      RWDigits p_out(new_parts, start, new_part_len);
1581cb0ef41Sopenharmony_ci      RWDigits m_out(new_multipliers, start, new_part_len);
1591cb0ef41Sopenharmony_ci      // p[j] = p[i] * m[i+1] + p[i+1]
1601cb0ef41Sopenharmony_ci      Multiply(p_out, p_in, m_in2);
1611cb0ef41Sopenharmony_ci      if (should_terminate()) return;
1621cb0ef41Sopenharmony_ci      digit_t overflow = AddAndReturnOverflow(p_out, p_in2);
1631cb0ef41Sopenharmony_ci      DCHECK(overflow == 0);
1641cb0ef41Sopenharmony_ci      USE(overflow);
1651cb0ef41Sopenharmony_ci      // m[j] = m[i] * m[i+1]
1661cb0ef41Sopenharmony_ci      if (i > 0) {
1671cb0ef41Sopenharmony_ci        bool copied = false;
1681cb0ef41Sopenharmony_ci        if (i > 2) {
1691cb0ef41Sopenharmony_ci          int prev_start = (i - 2) * part_len;
1701cb0ef41Sopenharmony_ci          Digits m_in_prev(multipliers, prev_start, part_len);
1711cb0ef41Sopenharmony_ci          Digits m_in2_prev(multipliers, prev_start + part_len, part_len);
1721cb0ef41Sopenharmony_ci          if (Compare(m_in, m_in_prev) == 0 &&
1731cb0ef41Sopenharmony_ci              Compare(m_in2, m_in2_prev) == 0) {
1741cb0ef41Sopenharmony_ci            copied = true;
1751cb0ef41Sopenharmony_ci            Digits m_out_prev(new_multipliers, prev_start, new_part_len);
1761cb0ef41Sopenharmony_ci            for (int k = 0; k < new_part_len; k++) m_out[k] = m_out_prev[k];
1771cb0ef41Sopenharmony_ci          }
1781cb0ef41Sopenharmony_ci        }
1791cb0ef41Sopenharmony_ci        if (!copied) {
1801cb0ef41Sopenharmony_ci          Multiply(m_out, m_in, m_in2);
1811cb0ef41Sopenharmony_ci          if (should_terminate()) return;
1821cb0ef41Sopenharmony_ci        }
1831cb0ef41Sopenharmony_ci      }
1841cb0ef41Sopenharmony_ci    }
1851cb0ef41Sopenharmony_ci    // Trailing last part (if {num_parts} was odd).
1861cb0ef41Sopenharmony_ci    if (i < num_parts) {
1871cb0ef41Sopenharmony_ci      Digits p_in(parts, i * part_len, part_len);
1881cb0ef41Sopenharmony_ci      Digits m_in(multipliers, i * part_len, part_len);
1891cb0ef41Sopenharmony_ci      RWDigits p_out(new_parts, i * part_len, new_part_len);
1901cb0ef41Sopenharmony_ci      RWDigits m_out(new_multipliers, i * part_len, new_part_len);
1911cb0ef41Sopenharmony_ci      int k = 0;
1921cb0ef41Sopenharmony_ci      for (; k < p_in.len(); k++) p_out[k] = p_in[k];
1931cb0ef41Sopenharmony_ci      for (; k < p_out.len(); k++) p_out[k] = 0;
1941cb0ef41Sopenharmony_ci      k = 0;
1951cb0ef41Sopenharmony_ci      for (; k < m_in.len(); k++) m_out[k] = m_in[k];
1961cb0ef41Sopenharmony_ci      for (; k < m_out.len(); k++) m_out[k] = 0;
1971cb0ef41Sopenharmony_ci      i += 2;
1981cb0ef41Sopenharmony_ci    }
1991cb0ef41Sopenharmony_ci    num_parts = i >> 1;
2001cb0ef41Sopenharmony_ci    part_len = new_part_len;
2011cb0ef41Sopenharmony_ci    RWDigits new_temp = multipliers;
2021cb0ef41Sopenharmony_ci    parts = new_parts;
2031cb0ef41Sopenharmony_ci    multipliers = new_multipliers;
2041cb0ef41Sopenharmony_ci    temp = new_temp;
2051cb0ef41Sopenharmony_ci  }
2061cb0ef41Sopenharmony_ci  // Copy the result to Z, if it doesn't happen to be there already.
2071cb0ef41Sopenharmony_ci  if (parts.digits() != Z.digits()) {
2081cb0ef41Sopenharmony_ci    int i = 0;
2091cb0ef41Sopenharmony_ci    for (; i < parts.len(); i++) Z[i] = parts[i];
2101cb0ef41Sopenharmony_ci    // Z might be bigger than we requested; be robust towards that.
2111cb0ef41Sopenharmony_ci    for (; i < Z.len(); i++) Z[i] = 0;
2121cb0ef41Sopenharmony_ci  }
2131cb0ef41Sopenharmony_ci}
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci// Specialized algorithms for power-of-two radixes. Designed to work with
2161cb0ef41Sopenharmony_ci// {ParsePowerTwo}: {max_multiplier_} isn't saved, but {radix_} is, and
2171cb0ef41Sopenharmony_ci// {last_multiplier_} has special meaning, namely the number of unpopulated bits
2181cb0ef41Sopenharmony_ci// in the last part.
2191cb0ef41Sopenharmony_ci// For these radixes, {parts} already is a list of correct bit sequences, we
2201cb0ef41Sopenharmony_ci// just have to put them together in the right way:
2211cb0ef41Sopenharmony_ci// - The parts are currently in reversed order. The highest-index parts[i]
2221cb0ef41Sopenharmony_ci//   will go into Z[0].
2231cb0ef41Sopenharmony_ci// - All parts, possibly except for the last, are maximally populated.
2241cb0ef41Sopenharmony_ci// - A maximally populated part stores a non-fractional number of characters,
2251cb0ef41Sopenharmony_ci//   i.e. the largest fitting multiple of {char_bits} of it is populated.
2261cb0ef41Sopenharmony_ci// - The populated bits in a part are at the low end.
2271cb0ef41Sopenharmony_ci// - The number of unused bits in the last part is stored in
2281cb0ef41Sopenharmony_ci//   {accumulator->last_multiplier_}.
2291cb0ef41Sopenharmony_ci//
2301cb0ef41Sopenharmony_ci// Example: Given the following parts vector, where letters are used to
2311cb0ef41Sopenharmony_ci// label bits, bit order is big endian (i.e. [00000101] encodes "5"),
2321cb0ef41Sopenharmony_ci// 'x' means "unpopulated", kDigitBits == 8, radix == 8, and char_bits == 3:
2331cb0ef41Sopenharmony_ci//
2341cb0ef41Sopenharmony_ci//     parts[0] -> [xxABCDEF][xxGHIJKL][xxMNOPQR][xxxxxSTU] <- parts[3]
2351cb0ef41Sopenharmony_ci//
2361cb0ef41Sopenharmony_ci// We have to assemble the following result:
2371cb0ef41Sopenharmony_ci//
2381cb0ef41Sopenharmony_ci//         Z[0] -> [NOPQRSTU][FGHIJKLM][xxxABCDE] <- Z[2]
2391cb0ef41Sopenharmony_ci//
2401cb0ef41Sopenharmony_civoid ProcessorImpl::FromStringBasePowerOfTwo(
2411cb0ef41Sopenharmony_ci    RWDigits Z, FromStringAccumulator* accumulator) {
2421cb0ef41Sopenharmony_ci  const int num_parts = accumulator->ResultLength();
2431cb0ef41Sopenharmony_ci  DCHECK(num_parts >= 1);
2441cb0ef41Sopenharmony_ci  DCHECK(Z.len() >= num_parts);
2451cb0ef41Sopenharmony_ci  Digits parts(accumulator->heap_parts_.size() > 0
2461cb0ef41Sopenharmony_ci                   ? accumulator->heap_parts_.data()
2471cb0ef41Sopenharmony_ci                   : accumulator->stack_parts_,
2481cb0ef41Sopenharmony_ci               num_parts);
2491cb0ef41Sopenharmony_ci  uint8_t radix = accumulator->radix_;
2501cb0ef41Sopenharmony_ci  DCHECK(radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32);
2511cb0ef41Sopenharmony_ci  const int char_bits = BitLength(radix - 1);
2521cb0ef41Sopenharmony_ci  const int unused_last_part_bits =
2531cb0ef41Sopenharmony_ci      static_cast<int>(accumulator->last_multiplier_);
2541cb0ef41Sopenharmony_ci  const int unused_part_bits = kDigitBits % char_bits;
2551cb0ef41Sopenharmony_ci  const int max_part_bits = kDigitBits - unused_part_bits;
2561cb0ef41Sopenharmony_ci  int z_index = 0;
2571cb0ef41Sopenharmony_ci  int part_index = num_parts - 1;
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci  // If the last part is fully populated, then all parts must be, and we can
2601cb0ef41Sopenharmony_ci  // simply copy them (in reversed order).
2611cb0ef41Sopenharmony_ci  if (unused_last_part_bits == 0) {
2621cb0ef41Sopenharmony_ci    DCHECK(kDigitBits % char_bits == 0);
2631cb0ef41Sopenharmony_ci    while (part_index >= 0) {
2641cb0ef41Sopenharmony_ci      Z[z_index++] = parts[part_index--];
2651cb0ef41Sopenharmony_ci    }
2661cb0ef41Sopenharmony_ci    for (; z_index < Z.len(); z_index++) Z[z_index] = 0;
2671cb0ef41Sopenharmony_ci    return;
2681cb0ef41Sopenharmony_ci  }
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  // Otherwise we have to shift parts contents around as needed.
2711cb0ef41Sopenharmony_ci  // Holds the next Z digit that we want to store...
2721cb0ef41Sopenharmony_ci  digit_t digit = parts[part_index--];
2731cb0ef41Sopenharmony_ci  // ...and the number of bits (at the right end) we already know.
2741cb0ef41Sopenharmony_ci  int digit_bits = kDigitBits - unused_last_part_bits;
2751cb0ef41Sopenharmony_ci  while (part_index >= 0) {
2761cb0ef41Sopenharmony_ci    // Holds the last part that we read from {parts}...
2771cb0ef41Sopenharmony_ci    digit_t part;
2781cb0ef41Sopenharmony_ci    // ...and the number of bits (at the right end) that we haven't used yet.
2791cb0ef41Sopenharmony_ci    int part_bits;
2801cb0ef41Sopenharmony_ci    while (digit_bits < kDigitBits) {
2811cb0ef41Sopenharmony_ci      part = parts[part_index--];
2821cb0ef41Sopenharmony_ci      part_bits = max_part_bits;
2831cb0ef41Sopenharmony_ci      digit |= part << digit_bits;
2841cb0ef41Sopenharmony_ci      int part_shift = kDigitBits - digit_bits;
2851cb0ef41Sopenharmony_ci      if (part_shift > part_bits) {
2861cb0ef41Sopenharmony_ci        digit_bits += part_bits;
2871cb0ef41Sopenharmony_ci        part = 0;
2881cb0ef41Sopenharmony_ci        part_bits = 0;
2891cb0ef41Sopenharmony_ci        if (part_index < 0) break;
2901cb0ef41Sopenharmony_ci      } else {
2911cb0ef41Sopenharmony_ci        digit_bits = kDigitBits;
2921cb0ef41Sopenharmony_ci        part >>= part_shift;
2931cb0ef41Sopenharmony_ci        part_bits -= part_shift;
2941cb0ef41Sopenharmony_ci      }
2951cb0ef41Sopenharmony_ci    }
2961cb0ef41Sopenharmony_ci    Z[z_index++] = digit;
2971cb0ef41Sopenharmony_ci    digit = part;
2981cb0ef41Sopenharmony_ci    digit_bits = part_bits;
2991cb0ef41Sopenharmony_ci  }
3001cb0ef41Sopenharmony_ci  if (digit_bits > 0) {
3011cb0ef41Sopenharmony_ci    Z[z_index++] = digit;
3021cb0ef41Sopenharmony_ci  }
3031cb0ef41Sopenharmony_ci  for (; z_index < Z.len(); z_index++) Z[z_index] = 0;
3041cb0ef41Sopenharmony_ci}
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_civoid ProcessorImpl::FromString(RWDigits Z, FromStringAccumulator* accumulator) {
3071cb0ef41Sopenharmony_ci  if (accumulator->inline_everything_) {
3081cb0ef41Sopenharmony_ci    int i = 0;
3091cb0ef41Sopenharmony_ci    for (; i < accumulator->stack_parts_used_; i++) {
3101cb0ef41Sopenharmony_ci      Z[i] = accumulator->stack_parts_[i];
3111cb0ef41Sopenharmony_ci    }
3121cb0ef41Sopenharmony_ci    for (; i < Z.len(); i++) Z[i] = 0;
3131cb0ef41Sopenharmony_ci  } else if (accumulator->stack_parts_used_ == 0) {
3141cb0ef41Sopenharmony_ci    for (int i = 0; i < Z.len(); i++) Z[i] = 0;
3151cb0ef41Sopenharmony_ci  } else if (IsPowerOfTwo(accumulator->radix_)) {
3161cb0ef41Sopenharmony_ci    FromStringBasePowerOfTwo(Z, accumulator);
3171cb0ef41Sopenharmony_ci  } else if (accumulator->ResultLength() < kFromStringLargeThreshold) {
3181cb0ef41Sopenharmony_ci    FromStringClassic(Z, accumulator);
3191cb0ef41Sopenharmony_ci  } else {
3201cb0ef41Sopenharmony_ci    FromStringLarge(Z, accumulator);
3211cb0ef41Sopenharmony_ci  }
3221cb0ef41Sopenharmony_ci}
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ciStatus Processor::FromString(RWDigits Z, FromStringAccumulator* accumulator) {
3251cb0ef41Sopenharmony_ci  ProcessorImpl* impl = static_cast<ProcessorImpl*>(this);
3261cb0ef41Sopenharmony_ci  impl->FromString(Z, accumulator);
3271cb0ef41Sopenharmony_ci  return impl->get_and_clear_status();
3281cb0ef41Sopenharmony_ci}
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci}  // namespace bigint
3311cb0ef41Sopenharmony_ci}  // namespace v8
332