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