• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <cstring>
6 #include <limits>
7 
8 #include "src/bigint/bigint-internal.h"
9 #include "src/bigint/digit-arithmetic.h"
10 #include "src/bigint/div-helpers.h"
11 #include "src/bigint/util.h"
12 #include "src/bigint/vector-arithmetic.h"
13 
14 namespace v8 {
15 namespace bigint {
16 
17 namespace {
18 
19 // Lookup table for the maximum number of bits required per character of a
20 // base-N string representation of a number. To increase accuracy, the array
21 // value is the actual value multiplied by 32. To generate this table:
22 // for (var i = 0; i <= 36; i++) { print(Math.ceil(Math.log2(i) * 32) + ","); }
23 constexpr uint8_t kMaxBitsPerChar[] = {
24     0,   0,   32,  51,  64,  75,  83,  90,  96,  // 0..8
25     102, 107, 111, 115, 119, 122, 126, 128,      // 9..16
26     131, 134, 136, 139, 141, 143, 145, 147,      // 17..24
27     149, 151, 153, 154, 156, 158, 159, 160,      // 25..32
28     162, 163, 165, 166,                          // 33..36
29 };
30 
31 static const int kBitsPerCharTableShift = 5;
32 static const size_t kBitsPerCharTableMultiplier = 1u << kBitsPerCharTableShift;
33 
34 static const char kConversionChars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
35 
36 // Raises {base} to the power of {exponent}. Does not check for overflow.
digit_pow(digit_t base,digit_t exponent)37 digit_t digit_pow(digit_t base, digit_t exponent) {
38   digit_t result = 1ull;
39   while (exponent > 0) {
40     if (exponent & 1) {
41       result *= base;
42     }
43     exponent >>= 1;
44     base *= base;
45   }
46   return result;
47 }
48 
49 // Compile-time version of the above.
digit_pow_rec(digit_t base,digit_t exponent)50 constexpr digit_t digit_pow_rec(digit_t base, digit_t exponent) {
51   return exponent == 1 ? base : base * digit_pow_rec(base, exponent - 1);
52 }
53 
54 // A variant of ToStringFormatter::BasecaseLast, specialized for a radix
55 // known at compile-time.
56 template <int radix>
BasecaseFixedLast(digit_t chunk,char * out)57 char* BasecaseFixedLast(digit_t chunk, char* out) {
58   while (chunk != 0) {
59     DCHECK(*(out - 1) == kStringZapValue);
60     if (radix <= 10) {
61       *(--out) = '0' + (chunk % radix);
62     } else {
63       *(--out) = kConversionChars[chunk % radix];
64     }
65     chunk /= radix;
66   }
67   return out;
68 }
69 
70 // By making {radix} a compile-time constant and computing {chunk_divisor}
71 // as another compile-time constant from it, we allow the compiler to emit
72 // an optimized instruction sequence based on multiplications with "magic"
73 // numbers (modular multiplicative inverses) instead of actual divisions.
74 // The price we pay is having to work on half digits; the technique doesn't
75 // work with twodigit_t-by-digit_t divisions.
76 // Includes an equivalent of ToStringFormatter::BasecaseMiddle, accordingly
77 // specialized for a radix known at compile time.
78 template <digit_t radix>
DivideByMagic(RWDigits rest,Digits input,char * output)79 char* DivideByMagic(RWDigits rest, Digits input, char* output) {
80   constexpr uint8_t max_bits_per_char = kMaxBitsPerChar[radix];
81   constexpr int chunk_chars =
82       kHalfDigitBits * kBitsPerCharTableMultiplier / max_bits_per_char;
83   constexpr digit_t chunk_divisor = digit_pow_rec(radix, chunk_chars);
84   digit_t remainder = 0;
85   for (int i = input.len() - 1; i >= 0; i--) {
86     digit_t d = input[i];
87     digit_t upper = (remainder << kHalfDigitBits) | (d >> kHalfDigitBits);
88     digit_t u_result = upper / chunk_divisor;
89     remainder = upper % chunk_divisor;
90     digit_t lower = (remainder << kHalfDigitBits) | (d & kHalfDigitMask);
91     digit_t l_result = lower / chunk_divisor;
92     remainder = lower % chunk_divisor;
93     rest[i] = (u_result << kHalfDigitBits) | l_result;
94   }
95   // {remainder} is now the current chunk to be written out.
96   for (int i = 0; i < chunk_chars; i++) {
97     DCHECK(*(output - 1) == kStringZapValue);
98     if (radix <= 10) {
99       *(--output) = '0' + (remainder % radix);
100     } else {
101       *(--output) = kConversionChars[remainder % radix];
102     }
103     remainder /= radix;
104   }
105   DCHECK(remainder == 0);
106   return output;
107 }
108 
109 class RecursionLevel;
110 
111 // The classic algorithm must check for interrupt requests if no faster
112 // algorithm is available.
113 #if V8_ADVANCED_BIGINT_ALGORITHMS
114 #define MAYBE_INTERRUPT(code) ((void)0)
115 #else
116 #define MAYBE_INTERRUPT(code) code
117 #endif
118 
119 class ToStringFormatter {
120  public:
ToStringFormatter(Digits X,int radix,bool sign,char * out,int chars_available,ProcessorImpl * processor)121   ToStringFormatter(Digits X, int radix, bool sign, char* out,
122                     int chars_available, ProcessorImpl* processor)
123       : digits_(X),
124         radix_(radix),
125         sign_(sign),
126         out_start_(out),
127         out_end_(out + chars_available),
128         out_(out_end_),
129         processor_(processor) {
130     digits_.Normalize();
131     DCHECK(chars_available >= ToStringResultLength(digits_, radix_, sign_));
132   }
133 
134   void Start();
135   int Finish();
136 
Classic()137   void Classic() {
138     if (digits_.len() == 0) {
139       *(--out_) = '0';
140       return;
141     }
142     if (digits_.len() == 1) {
143       out_ = BasecaseLast(digits_[0], out_);
144       return;
145     }
146     // {rest} holds the part of the BigInt that we haven't looked at yet.
147     // Not to be confused with "remainder"!
148     ScratchDigits rest(digits_.len());
149     // In the first round, divide the input, allocating a new BigInt for
150     // the result == rest; from then on divide the rest in-place.
151     Digits dividend = digits_;
152     do {
153       if (radix_ == 10) {
154         // Faster but costs binary size, so we optimize the most common case.
155         out_ = DivideByMagic<10>(rest, dividend, out_);
156         MAYBE_INTERRUPT(processor_->AddWorkEstimate(rest.len() * 2));
157       } else {
158         digit_t chunk;
159         processor_->DivideSingle(rest, &chunk, dividend, chunk_divisor_);
160         out_ = BasecaseMiddle(chunk, out_);
161         // Assume that a division is about ten times as expensive as a
162         // multiplication.
163         MAYBE_INTERRUPT(processor_->AddWorkEstimate(rest.len() * 10));
164       }
165       MAYBE_INTERRUPT(if (processor_->should_terminate()) return );
166       rest.Normalize();
167       dividend = rest;
168     } while (rest.len() > 1);
169     out_ = BasecaseLast(rest[0], out_);
170   }
171 
172   void BasePowerOfTwo();
173 
174   void Fast();
175   char* FillWithZeros(RecursionLevel* level, char* prev_cursor, char* out,
176                       bool is_last_on_level);
177   char* ProcessLevel(RecursionLevel* level, Digits chunk, char* out,
178                      bool is_last_on_level);
179 
180  private:
181   // When processing the last (most significant) digit, don't write leading
182   // zeros.
BasecaseLast(digit_t digit,char * out)183   char* BasecaseLast(digit_t digit, char* out) {
184     if (radix_ == 10) return BasecaseFixedLast<10>(digit, out);
185     do {
186       DCHECK(*(out - 1) == kStringZapValue);
187       *(--out) = kConversionChars[digit % radix_];
188       digit /= radix_;
189     } while (digit > 0);
190     return out;
191   }
192 
193   // When processing a middle (non-most significant) digit, always write the
194   // same number of characters (as many '0' as necessary).
BasecaseMiddle(digit_t digit,char * out)195   char* BasecaseMiddle(digit_t digit, char* out) {
196     for (int i = 0; i < chunk_chars_; i++) {
197       DCHECK(*(out - 1) == kStringZapValue);
198       *(--out) = kConversionChars[digit % radix_];
199       digit /= radix_;
200     }
201     DCHECK(digit == 0);
202     return out;
203   }
204 
205   Digits digits_;
206   int radix_;
207   int max_bits_per_char_ = 0;
208   int chunk_chars_ = 0;
209   bool sign_;
210   char* out_start_;
211   char* out_end_;
212   char* out_;
213   digit_t chunk_divisor_ = 0;
214   ProcessorImpl* processor_;
215 };
216 
217 #undef MAYBE_INTERRUPT
218 
219 // Prepares data for {Classic}. Not needed for {BasePowerOfTwo}.
Start()220 void ToStringFormatter::Start() {
221   max_bits_per_char_ = kMaxBitsPerChar[radix_];
222   chunk_chars_ = kDigitBits * kBitsPerCharTableMultiplier / max_bits_per_char_;
223   chunk_divisor_ = digit_pow(radix_, chunk_chars_);
224   // By construction of chunk_chars_, there can't have been overflow.
225   DCHECK(chunk_divisor_ != 0);
226 }
227 
Finish()228 int ToStringFormatter::Finish() {
229   DCHECK(out_ >= out_start_);
230   DCHECK(out_ < out_end_);  // At least one character was written.
231   while (out_ < out_end_ && *out_ == '0') out_++;
232   if (sign_) *(--out_) = '-';
233   int excess = 0;
234   if (out_ > out_start_) {
235     size_t actual_length = out_end_ - out_;
236     excess = static_cast<int>(out_ - out_start_);
237     std::memmove(out_start_, out_, actual_length);
238   }
239   return excess;
240 }
241 
BasePowerOfTwo()242 void ToStringFormatter::BasePowerOfTwo() {
243   const int bits_per_char = CountTrailingZeros(radix_);
244   const int char_mask = radix_ - 1;
245   digit_t digit = 0;
246   // Keeps track of how many unprocessed bits there are in {digit}.
247   int available_bits = 0;
248   for (int i = 0; i < digits_.len() - 1; i++) {
249     digit_t new_digit = digits_[i];
250     // Take any leftover bits from the last iteration into account.
251     int current = (digit | (new_digit << available_bits)) & char_mask;
252     *(--out_) = kConversionChars[current];
253     int consumed_bits = bits_per_char - available_bits;
254     digit = new_digit >> consumed_bits;
255     available_bits = kDigitBits - consumed_bits;
256     while (available_bits >= bits_per_char) {
257       *(--out_) = kConversionChars[digit & char_mask];
258       digit >>= bits_per_char;
259       available_bits -= bits_per_char;
260     }
261   }
262   // Take any leftover bits from the last iteration into account.
263   digit_t msd = digits_.msd();
264   int current = (digit | (msd << available_bits)) & char_mask;
265   *(--out_) = kConversionChars[current];
266   digit = msd >> (bits_per_char - available_bits);
267   while (digit != 0) {
268     *(--out_) = kConversionChars[digit & char_mask];
269     digit >>= bits_per_char;
270   }
271 }
272 
273 #if V8_ADVANCED_BIGINT_ALGORITHMS
274 
275 // "Fast" divide-and-conquer conversion to string. The basic idea is to
276 // recursively cut the BigInt in half (using a division with remainder,
277 // the divisor being ~half as large (in bits) as the current dividend).
278 //
279 // As preparation, we build up a linked list of metadata for each recursion
280 // level. We do this bottom-up, i.e. start with the level that will produce
281 // two halves that are register-sized and bail out to the base case.
282 // Each higher level (executed earlier, prepared later) uses a divisor that is
283 // the square of the previously-created "next" level's divisor. Preparation
284 // terminates when the current divisor is at least half as large as the bigint.
285 // We also precompute each level's divisor's inverse, so we can use
286 // Barrett division later.
287 //
288 // Example: say we want to format 1234567890123, and we can fit two decimal
289 // digits into a register for the base case.
290 //
291 //              1234567890123
292 //                    ↓
293 //               %100000000 (a)              // RecursionLevel 2,
294 //             /            \                // is_toplevel_ == true.
295 //         12345            67890123
296 //           ↓                  ↓
297 //    (e) %10000             %10000 (b)      // RecursionLevel 1
298 //        /    \            /      \
299 //       1     2345      6789      0123
300 //       ↓   (f) ↓         ↓ (d)     ↓
301 // (g) %100    %100      %100      %100 (c)  // RecursionLevel 0
302 //     / \     /   \     /   \     /   \
303 //    00 01   23   45   67   89   01   23
304 //        ↓    ↓    ↓    ↓    ↓    ↓    ↓    // Base case.
305 //       "1" "23" "45" "67" "89" "01" "23"
306 //
307 // We start building RecursionLevels in order 0 -> 1 -> 2, performing the
308 // squarings 100² = 10000 and 10000² = 100000000 each only once. Execution
309 // then happens in order (a) through (g); lower-level divisors are used
310 // repeatedly. We build the string from right to left.
311 // Note that we can skip the division at (g) and fall through directly.
312 // Also, note that there are two chunks with value 1: one of them must produce
313 // a leading "0" in its string representation, the other must not.
314 //
315 // In this example, {base_divisor} is 100 and {base_char_count} is 2.
316 
317 // TODO(jkummerow): Investigate whether it is beneficial to build one or two
318 // fewer RecursionLevels, and use the topmost level for more than one division.
319 
320 class RecursionLevel {
321  public:
322   static RecursionLevel* CreateLevels(digit_t base_divisor, int base_char_count,
323                                       int target_bit_length,
324                                       ProcessorImpl* processor);
~RecursionLevel()325   ~RecursionLevel() { delete next_; }
326 
327   void ComputeInverse(ProcessorImpl* proc, int dividend_length = 0);
328   Digits GetInverse(int dividend_length);
329 
330  private:
331   friend class ToStringFormatter;
RecursionLevel(digit_t base_divisor,int base_char_count)332   RecursionLevel(digit_t base_divisor, int base_char_count)
333       : char_count_(base_char_count), divisor_(1) {
334     divisor_[0] = base_divisor;
335   }
RecursionLevel(RecursionLevel * next)336   explicit RecursionLevel(RecursionLevel* next)
337       : char_count_(next->char_count_ * 2),
338         next_(next),
339         divisor_(next->divisor_.len() * 2) {
340     next->is_toplevel_ = false;
341   }
342 
LeftShiftDivisor()343   void LeftShiftDivisor() {
344     leading_zero_shift_ = CountLeadingZeros(divisor_.msd());
345     LeftShift(divisor_, divisor_, leading_zero_shift_);
346   }
347 
348   int leading_zero_shift_{0};
349   // The number of characters generated by *each half* of this level.
350   int char_count_;
351   bool is_toplevel_{true};
352   RecursionLevel* next_{nullptr};
353   ScratchDigits divisor_;
354   std::unique_ptr<Storage> inverse_storage_;
355   Digits inverse_{nullptr, 0};
356 };
357 
358 // static
CreateLevels(digit_t base_divisor,int base_char_count,int target_bit_length,ProcessorImpl * processor)359 RecursionLevel* RecursionLevel::CreateLevels(digit_t base_divisor,
360                                              int base_char_count,
361                                              int target_bit_length,
362                                              ProcessorImpl* processor) {
363   RecursionLevel* level = new RecursionLevel(base_divisor, base_char_count);
364   // We can stop creating levels when the next level's divisor, which is the
365   // square of the current level's divisor, would be strictly bigger (in terms
366   // of its numeric value) than the input we're formatting. Since computing that
367   // next divisor is expensive, we want to predict the necessity based on bit
368   // lengths. Bit lengths are an imperfect predictor of numeric value, so we
369   // have to be careful:
370   // - since we can't estimate which one of two numbers of equal bit length
371   //   is bigger, we have to aim for a strictly bigger bit length.
372   // - when squaring, the bit length sometimes doubles (e.g. 0b11² == 0b1001),
373   //   but usually we "lose" a bit (e.g. 0b10² == 0b100).
374   while (BitLength(level->divisor_) * 2 - 1 <= target_bit_length) {
375     RecursionLevel* prev = level;
376     level = new RecursionLevel(prev);
377     processor->Multiply(level->divisor_, prev->divisor_, prev->divisor_);
378     if (processor->should_terminate()) {
379       delete level;
380       return nullptr;
381     }
382     level->divisor_.Normalize();
383     // Left-shifting the divisor must only happen after it's been used to
384     // compute the next divisor.
385     prev->LeftShiftDivisor();
386     prev->ComputeInverse(processor);
387   }
388   level->LeftShiftDivisor();
389   // Not calling info->ComputeInverse here so that it can take the input's
390   // length into account to save some effort on inverse generation.
391   return level;
392 }
393 
394 // The top level might get by with a smaller inverse than we could maximally
395 // compute, so the caller should provide the dividend length.
ComputeInverse(ProcessorImpl * processor,int dividend_length)396 void RecursionLevel::ComputeInverse(ProcessorImpl* processor,
397                                     int dividend_length) {
398   int inverse_len = divisor_.len();
399   if (dividend_length != 0) {
400     inverse_len = dividend_length - divisor_.len();
401     DCHECK(inverse_len <= divisor_.len());
402   }
403   int scratch_len = InvertScratchSpace(inverse_len);
404   ScratchDigits scratch(scratch_len);
405   Storage* inv_storage = new Storage(inverse_len + 1);
406   inverse_storage_.reset(inv_storage);
407   RWDigits inverse_initializer(inv_storage->get(), inverse_len + 1);
408   Digits input(divisor_, divisor_.len() - inverse_len, inverse_len);
409   processor->Invert(inverse_initializer, input, scratch);
410   inverse_initializer.TrimOne();
411   inverse_ = inverse_initializer;
412 }
413 
GetInverse(int dividend_length)414 Digits RecursionLevel::GetInverse(int dividend_length) {
415   DCHECK(inverse_.len() != 0);
416   int inverse_len = dividend_length - divisor_.len();
417   DCHECK(inverse_len <= inverse_.len());
418   return inverse_ + (inverse_.len() - inverse_len);
419 }
420 
Fast()421 void ToStringFormatter::Fast() {
422   std::unique_ptr<RecursionLevel> recursion_levels(RecursionLevel::CreateLevels(
423       chunk_divisor_, chunk_chars_, BitLength(digits_), processor_));
424   if (processor_->should_terminate()) return;
425   out_ = ProcessLevel(recursion_levels.get(), digits_, out_, true);
426 }
427 
428 // Writes '0' characters right-to-left, starting at {out}-1, until the distance
429 // from {right_boundary} to {out} equals the number of characters that {level}
430 // is supposed to produce.
FillWithZeros(RecursionLevel * level,char * right_boundary,char * out,bool is_last_on_level)431 char* ToStringFormatter::FillWithZeros(RecursionLevel* level,
432                                        char* right_boundary, char* out,
433                                        bool is_last_on_level) {
434   // Fill up with zeros up to the character count expected to be generated
435   // on this level; unless this is the left edge of the result.
436   if (is_last_on_level) return out;
437   int chunk_chars = level == nullptr ? chunk_chars_ : level->char_count_ * 2;
438   char* end = right_boundary - chunk_chars;
439   DCHECK(out >= end);
440   while (out > end) {
441     *(--out) = '0';
442   }
443   return out;
444 }
445 
ProcessLevel(RecursionLevel * level,Digits chunk,char * out,bool is_last_on_level)446 char* ToStringFormatter::ProcessLevel(RecursionLevel* level, Digits chunk,
447                                       char* out, bool is_last_on_level) {
448   // Step 0: if only one digit is left, bail out to the base case.
449   Digits normalized = chunk;
450   normalized.Normalize();
451   if (normalized.len() <= 1) {
452     char* right_boundary = out;
453     if (normalized.len() == 1) {
454       out = BasecaseLast(normalized[0], out);
455     }
456     return FillWithZeros(level, right_boundary, out, is_last_on_level);
457   }
458 
459   // Step 1: If the chunk is guaranteed to remain smaller than the divisor
460   // even after left-shifting, fall through to the next level immediately.
461   if (normalized.len() < level->divisor_.len()) {
462     char* right_boundary = out;
463     out = ProcessLevel(level->next_, chunk, out, is_last_on_level);
464     return FillWithZeros(level, right_boundary, out, is_last_on_level);
465   }
466   // Step 2: Prepare the chunk.
467   bool allow_inplace_modification = chunk.digits() != digits_.digits();
468   Digits original_chunk = chunk;
469   ShiftedDigits chunk_shifted(chunk, level->leading_zero_shift_,
470                               allow_inplace_modification);
471   chunk = chunk_shifted;
472   chunk.Normalize();
473   // Check (now precisely) if the chunk is smaller than the divisor.
474   int comparison = Compare(chunk, level->divisor_);
475   if (comparison <= 0) {
476     char* right_boundary = out;
477     if (comparison < 0) {
478       // If the chunk is strictly smaller than the divisor, we can process
479       // it directly on the next level as the right half, and know that the
480       // left half is all '0'.
481       // In case we shifted {chunk} in-place, we must undo that
482       // before the call...
483       chunk_shifted.Reset();
484       // ...and otherwise undo the {chunk = chunk_shifted} assignment above.
485       chunk = original_chunk;
486       out = ProcessLevel(level->next_, chunk, out, is_last_on_level);
487     } else {
488       DCHECK(comparison == 0);
489       // If the chunk is equal to the divisor, we know that the right half
490       // is all '0', and the left half is '...0001'.
491       // Handling this case specially is an optimization; we could also
492       // fall through to the generic "chunk > divisor" path below.
493       out = FillWithZeros(level->next_, right_boundary, out, false);
494       *(--out) = '1';
495     }
496     // In both cases, make sure the left half is fully written.
497     return FillWithZeros(level, right_boundary, out, is_last_on_level);
498   }
499   // Step 3: Allocate space for the results.
500   // Allocate one extra digit so the next level can left-shift in-place.
501   ScratchDigits right(level->divisor_.len() + 1);
502   // Allocate one extra digit because DivideBarrett requires it.
503   ScratchDigits left(chunk.len() - level->divisor_.len() + 1);
504 
505   // Step 4: Divide to split {chunk} into {left} and {right}.
506   int inverse_len = chunk.len() - level->divisor_.len();
507   if (inverse_len == 0) {
508     processor_->DivideSchoolbook(left, right, chunk, level->divisor_);
509   } else if (level->divisor_.len() == 1) {
510     processor_->DivideSingle(left, right.digits(), chunk, level->divisor_[0]);
511     for (int i = 1; i < right.len(); i++) right[i] = 0;
512   } else {
513     ScratchDigits scratch(DivideBarrettScratchSpace(chunk.len()));
514     // The top level only computes its inverse when {chunk.len()} is
515     // available. Other levels have precomputed theirs.
516     if (level->is_toplevel_) {
517       level->ComputeInverse(processor_, chunk.len());
518       if (processor_->should_terminate()) return out;
519     }
520     Digits inverse = level->GetInverse(chunk.len());
521     processor_->DivideBarrett(left, right, chunk, level->divisor_, inverse,
522                               scratch);
523     if (processor_->should_terminate()) return out;
524   }
525   RightShift(right, right, level->leading_zero_shift_);
526 #if DEBUG
527   Digits left_test = left;
528   left_test.Normalize();
529   DCHECK(left_test.len() <= level->divisor_.len());
530 #endif
531 
532   // Step 5: Recurse.
533   char* end_of_right_part = ProcessLevel(level->next_, right, out, false);
534   // The recursive calls are required and hence designed to write exactly as
535   // many characters as their level is responsible for.
536   DCHECK(end_of_right_part == out - level->char_count_);
537   USE(end_of_right_part);
538   if (processor_->should_terminate()) return out;
539   // We intentionally don't use {end_of_right_part} here to be prepared for
540   // potential future multi-threaded execution.
541   return ProcessLevel(level->next_, left, out - level->char_count_,
542                       is_last_on_level);
543 }
544 
545 #endif  // V8_ADVANCED_BIGINT_ALGORITHMS
546 
547 }  // namespace
548 
ToString(char * out,int * out_length,Digits X,int radix,bool sign)549 void ProcessorImpl::ToString(char* out, int* out_length, Digits X, int radix,
550                              bool sign) {
551   const bool use_fast_algorithm = X.len() >= kToStringFastThreshold;
552   ToStringImpl(out, out_length, X, radix, sign, use_fast_algorithm);
553 }
554 
555 // Factored out so that tests can call it.
ToStringImpl(char * out,int * out_length,Digits X,int radix,bool sign,bool fast)556 void ProcessorImpl::ToStringImpl(char* out, int* out_length, Digits X,
557                                  int radix, bool sign, bool fast) {
558 #if DEBUG
559   for (int i = 0; i < *out_length; i++) out[i] = kStringZapValue;
560 #endif
561   ToStringFormatter formatter(X, radix, sign, out, *out_length, this);
562   if (IsPowerOfTwo(radix)) {
563     formatter.BasePowerOfTwo();
564 #if V8_ADVANCED_BIGINT_ALGORITHMS
565   } else if (fast) {
566     formatter.Start();
567     formatter.Fast();
568     if (should_terminate()) return;
569 #else
570     USE(fast);
571 #endif  // V8_ADVANCED_BIGINT_ALGORITHMS
572   } else {
573     formatter.Start();
574     formatter.Classic();
575   }
576   int excess = formatter.Finish();
577   *out_length -= excess;
578 }
579 
ToString(char * out,int * out_length,Digits X,int radix,bool sign)580 Status Processor::ToString(char* out, int* out_length, Digits X, int radix,
581                            bool sign) {
582   ProcessorImpl* impl = static_cast<ProcessorImpl*>(this);
583   impl->ToString(out, out_length, X, radix, sign);
584   return impl->get_and_clear_status();
585 }
586 
ToStringResultLength(Digits X,int radix,bool sign)587 int ToStringResultLength(Digits X, int radix, bool sign) {
588   const int bit_length = BitLength(X);
589   int result;
590   if (IsPowerOfTwo(radix)) {
591     const int bits_per_char = CountTrailingZeros(radix);
592     result = DIV_CEIL(bit_length, bits_per_char) + sign;
593   } else {
594     // Maximum number of bits we can represent with one character.
595     const uint8_t max_bits_per_char = kMaxBitsPerChar[radix];
596     // For estimating the result length, we have to be pessimistic and work with
597     // the minimum number of bits one character can represent.
598     const uint8_t min_bits_per_char = max_bits_per_char - 1;
599     // Perform the following computation with uint64_t to avoid overflows.
600     uint64_t chars_required = bit_length;
601     chars_required *= kBitsPerCharTableMultiplier;
602     chars_required = DIV_CEIL(chars_required, min_bits_per_char);
603     DCHECK(chars_required < std::numeric_limits<int>::max());
604     result = static_cast<int>(chars_required);
605   }
606   result += sign;
607   return result;
608 }
609 
610 }  // namespace bigint
611 }  // namespace v8
612