5 #include "src/bignum-dtoa.h" 9 #include "src/base/logging.h" 10 #include "src/bignum.h" 11 #include "src/double.h" 12 #include "src/utils.h" 17 static int NormalizedExponent(uint64_t significand,
int exponent) {
18 DCHECK_NE(significand, 0);
19 while ((significand & Double::kHiddenBit) == 0) {
20 significand = significand << 1;
21 exponent = exponent - 1;
29 static int EstimatePower(
int exponent);
32 static void InitialScaledStartValues(
double v,
34 bool need_boundary_deltas,
44 static void FixupMultiply10(
int estimated_power,
bool is_even,
46 Bignum* numerator, Bignum* denominator,
47 Bignum* delta_minus, Bignum* delta_plus);
50 static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
51 Bignum* delta_minus, Bignum* delta_plus,
53 Vector<char> buffer,
int* length);
55 static void BignumToFixed(
int requested_digits,
int* decimal_point,
56 Bignum* numerator, Bignum* denominator,
57 Vector<char>(buffer),
int* length);
62 static void GenerateCountedDigits(
int count,
int* decimal_point,
63 Bignum* numerator, Bignum* denominator,
64 Vector<char>(buffer),
int* length);
67 void BignumDtoa(
double v, BignumDtoaMode mode,
int requested_digits,
68 Vector<char> buffer,
int* length,
int* decimal_point) {
70 DCHECK(!Double(v).IsSpecial());
71 uint64_t significand = Double(v).Significand();
72 bool is_even = (significand & 1) == 0;
73 int exponent = Double(v).Exponent();
74 int normalized_exponent = NormalizedExponent(significand, exponent);
76 int estimated_power = EstimatePower(normalized_exponent);
82 if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
88 *decimal_point = -requested_digits;
100 DCHECK_GE(Bignum::kMaxSignificantBits, 324 * 4);
101 bool need_boundary_deltas = (mode == BIGNUM_DTOA_SHORTEST);
102 InitialScaledStartValues(v, estimated_power, need_boundary_deltas,
103 &numerator, &denominator,
104 &delta_minus, &delta_plus);
106 FixupMultiply10(estimated_power, is_even, decimal_point,
107 &numerator, &denominator,
108 &delta_minus, &delta_plus);
112 case BIGNUM_DTOA_SHORTEST:
113 GenerateShortestDigits(&numerator, &denominator,
114 &delta_minus, &delta_plus,
115 is_even, buffer, length);
117 case BIGNUM_DTOA_FIXED:
118 BignumToFixed(requested_digits, decimal_point,
119 &numerator, &denominator,
122 case BIGNUM_DTOA_PRECISION:
123 GenerateCountedDigits(requested_digits, decimal_point,
124 &numerator, &denominator,
130 buffer[*length] =
'\0';
147 static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
148 Bignum* delta_minus, Bignum* delta_plus,
150 Vector<char> buffer,
int* length) {
153 if (Bignum::Equal(*delta_minus, *delta_plus)) {
154 delta_plus = delta_minus;
159 digit = numerator->DivideModuloIntBignum(*denominator);
163 buffer[(*length)++] = digit +
'0';
170 bool in_delta_room_minus;
171 bool in_delta_room_plus;
173 in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
175 in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
179 Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
182 Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
184 if (!in_delta_room_minus && !in_delta_room_plus) {
186 numerator->Times10();
187 delta_minus->Times10();
191 if (delta_minus != delta_plus) {
192 delta_plus->Times10();
194 }
else if (in_delta_room_minus && in_delta_room_plus) {
197 int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
200 }
else if (compare > 0) {
206 DCHECK_NE(buffer[(*length) - 1],
'9');
207 buffer[(*length) - 1]++;
214 if ((buffer[(*length) - 1] -
'0') % 2 == 0) {
217 DCHECK_NE(buffer[(*length) - 1],
'9');
218 buffer[(*length) - 1]++;
222 }
else if (in_delta_room_minus) {
231 DCHECK_NE(buffer[(*length) - 1],
'9');
232 buffer[(*length) - 1]++;
245 static void GenerateCountedDigits(
int count,
int* decimal_point,
246 Bignum* numerator, Bignum* denominator,
247 Vector<char>(buffer),
int* length) {
249 for (
int i = 0;
i < count - 1; ++
i) {
251 digit = numerator->DivideModuloIntBignum(*denominator);
255 buffer[
i] = digit +
'0';
257 numerator->Times10();
261 digit = numerator->DivideModuloIntBignum(*denominator);
262 if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
265 buffer[count - 1] = digit +
'0';
268 for (
int i = count - 1;
i > 0; --
i) {
269 if (buffer[
i] !=
'0' + 10)
break;
273 if (buffer[0] ==
'0' + 10) {
287 static void BignumToFixed(
int requested_digits,
int* decimal_point,
288 Bignum* numerator, Bignum* denominator,
289 Vector<char>(buffer),
int* length) {
293 if (-(*decimal_point) > requested_digits) {
299 *decimal_point = -requested_digits;
302 }
else if (-(*decimal_point) == requested_digits) {
305 DCHECK(*decimal_point == -requested_digits);
308 denominator->Times10();
309 if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
323 int needed_digits = (*decimal_point) + requested_digits;
324 GenerateCountedDigits(needed_digits, decimal_point,
325 numerator, denominator,
346 static int EstimatePower(
int exponent) {
368 const double k1Log10 = 0.30102999566398114;
371 const int kSignificandSize = 53;
373 std::ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
374 return static_cast<int>(estimate);
379 static void InitialScaledStartValuesPositiveExponent(
380 double v,
int estimated_power,
bool need_boundary_deltas,
381 Bignum* numerator, Bignum* denominator,
382 Bignum* delta_minus, Bignum* delta_plus) {
384 DCHECK_GE(estimated_power, 0);
389 numerator->AssignUInt64(Double(v).Significand());
390 numerator->ShiftLeft(Double(v).Exponent());
392 denominator->AssignPowerUInt16(10, estimated_power);
394 if (need_boundary_deltas) {
397 denominator->ShiftLeft(1);
398 numerator->ShiftLeft(1);
401 delta_plus->AssignUInt16(1);
402 delta_plus->ShiftLeft(Double(v).Exponent());
404 delta_minus->AssignUInt16(1);
405 delta_minus->ShiftLeft(Double(v).Exponent());
412 uint64_t v_bits = Double(v).AsUint64();
413 if ((v_bits & Double::kSignificandMask) == 0) {
416 denominator->ShiftLeft(1);
417 numerator->ShiftLeft(1);
418 delta_plus->ShiftLeft(1);
425 static void InitialScaledStartValuesNegativeExponentPositivePower(
426 double v,
int estimated_power,
bool need_boundary_deltas,
427 Bignum* numerator, Bignum* denominator,
428 Bignum* delta_minus, Bignum* delta_plus) {
429 uint64_t significand = Double(v).Significand();
430 int exponent = Double(v).Exponent();
438 numerator->AssignUInt64(significand);
440 denominator->AssignPowerUInt16(10, estimated_power);
441 denominator->ShiftLeft(-exponent);
443 if (need_boundary_deltas) {
446 denominator->ShiftLeft(1);
447 numerator->ShiftLeft(1);
452 delta_plus->AssignUInt16(1);
454 delta_minus->AssignUInt16(1);
462 uint64_t v_bits = Double(v).AsUint64();
463 if ((v_bits & Double::kSignificandMask) == 0) {
466 denominator->ShiftLeft(1);
467 numerator->ShiftLeft(1);
468 delta_plus->ShiftLeft(1);
475 static void InitialScaledStartValuesNegativeExponentNegativePower(
476 double v,
int estimated_power,
bool need_boundary_deltas,
477 Bignum* numerator, Bignum* denominator,
478 Bignum* delta_minus, Bignum* delta_plus) {
479 const uint64_t kMinimalNormalizedExponent =
480 V8_2PART_UINT64_C(0x00100000, 00000000);
481 uint64_t significand = Double(v).Significand();
482 int exponent = Double(v).Exponent();
487 Bignum* power_ten = numerator;
488 power_ten->AssignPowerUInt16(10, -estimated_power);
490 if (need_boundary_deltas) {
494 delta_plus->AssignBignum(*power_ten);
495 delta_minus->AssignBignum(*power_ten);
503 DCHECK(numerator == power_ten);
504 numerator->MultiplyByUInt64(significand);
507 denominator->AssignUInt16(1);
508 denominator->ShiftLeft(-exponent);
510 if (need_boundary_deltas) {
513 numerator->ShiftLeft(1);
514 denominator->ShiftLeft(1);
522 uint64_t v_bits = Double(v).AsUint64();
523 if ((v_bits & Double::kSignificandMask) == 0 &&
526 (v_bits & Double::kExponentMask) != kMinimalNormalizedExponent) {
527 numerator->ShiftLeft(1);
528 denominator->ShiftLeft(1);
529 delta_plus->ShiftLeft(1);
571 static void InitialScaledStartValues(
double v,
573 bool need_boundary_deltas,
577 Bignum* delta_plus) {
578 if (Double(v).Exponent() >= 0) {
579 InitialScaledStartValuesPositiveExponent(
580 v, estimated_power, need_boundary_deltas,
581 numerator, denominator, delta_minus, delta_plus);
582 }
else if (estimated_power >= 0) {
583 InitialScaledStartValuesNegativeExponentPositivePower(
584 v, estimated_power, need_boundary_deltas,
585 numerator, denominator, delta_minus, delta_plus);
587 InitialScaledStartValuesNegativeExponentNegativePower(
588 v, estimated_power, need_boundary_deltas,
589 numerator, denominator, delta_minus, delta_plus);
605 static void FixupMultiply10(
int estimated_power,
bool is_even,
607 Bignum* numerator, Bignum* denominator,
608 Bignum* delta_minus, Bignum* delta_plus) {
613 in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
615 in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
620 *decimal_point = estimated_power + 1;
622 *decimal_point = estimated_power;
623 numerator->Times10();
624 if (Bignum::Equal(*delta_minus, *delta_plus)) {
625 delta_minus->Times10();
626 delta_plus->AssignBignum(*delta_minus);
628 delta_minus->Times10();
629 delta_plus->Times10();