| Index: runtime/third_party/double-conversion/src/bignum-dtoa.cc
|
| ===================================================================
|
| --- runtime/third_party/double-conversion/src/bignum-dtoa.cc (revision 33139)
|
| +++ runtime/third_party/double-conversion/src/bignum-dtoa.cc (working copy)
|
| @@ -30,7 +30,7 @@
|
| #include "bignum-dtoa.h"
|
|
|
| #include "bignum.h"
|
| -#include "double.h"
|
| +#include "ieee.h"
|
|
|
| namespace double_conversion {
|
|
|
| @@ -49,7 +49,9 @@
|
| static int EstimatePower(int exponent);
|
| // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
|
| // and denominator.
|
| -static void InitialScaledStartValues(double v,
|
| +static void InitialScaledStartValues(uint64_t significand,
|
| + int exponent,
|
| + bool lower_boundary_is_closer,
|
| int estimated_power,
|
| bool need_boundary_deltas,
|
| Bignum* numerator,
|
| @@ -88,9 +90,24 @@
|
| Vector<char> buffer, int* length, int* decimal_point) {
|
| ASSERT(v > 0);
|
| ASSERT(!Double(v).IsSpecial());
|
| - uint64_t significand = Double(v).Significand();
|
| + uint64_t significand;
|
| + int exponent;
|
| + bool lower_boundary_is_closer;
|
| + if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
|
| + float f = static_cast<float>(v);
|
| + ASSERT(f == v);
|
| + significand = Single(f).Significand();
|
| + exponent = Single(f).Exponent();
|
| + lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
|
| + } else {
|
| + significand = Double(v).Significand();
|
| + exponent = Double(v).Exponent();
|
| + lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
|
| + }
|
| + bool need_boundary_deltas =
|
| + (mode == BIGNUM_DTOA_SHORTEST || mode == BIGNUM_DTOA_SHORTEST_SINGLE);
|
| +
|
| bool is_even = (significand & 1) == 0;
|
| - int exponent = Double(v).Exponent();
|
| int normalized_exponent = NormalizedExponent(significand, exponent);
|
| // estimated_power might be too low by 1.
|
| int estimated_power = EstimatePower(normalized_exponent);
|
| @@ -118,8 +135,8 @@
|
| // The maximum double is 1.7976931348623157e308 which needs fewer than
|
| // 308*4 binary digits.
|
| ASSERT(Bignum::kMaxSignificantBits >= 324*4);
|
| - bool need_boundary_deltas = (mode == BIGNUM_DTOA_SHORTEST);
|
| - InitialScaledStartValues(v, estimated_power, need_boundary_deltas,
|
| + InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
|
| + estimated_power, need_boundary_deltas,
|
| &numerator, &denominator,
|
| &delta_minus, &delta_plus);
|
| // We now have v = (numerator / denominator) * 10^estimated_power.
|
| @@ -130,6 +147,7 @@
|
| // 1 <= (numerator + delta_plus) / denominator < 10
|
| switch (mode) {
|
| case BIGNUM_DTOA_SHORTEST:
|
| + case BIGNUM_DTOA_SHORTEST_SINGLE:
|
| GenerateShortestDigits(&numerator, &denominator,
|
| &delta_minus, &delta_plus,
|
| is_even, buffer, length);
|
| @@ -174,13 +192,13 @@
|
| delta_plus = delta_minus;
|
| }
|
| *length = 0;
|
| - while (true) {
|
| + for (;;) {
|
| uint16_t digit;
|
| digit = numerator->DivideModuloIntBignum(*denominator);
|
| ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
|
| // digit = numerator / denominator (integer division).
|
| // numerator = numerator % denominator.
|
| - buffer[(*length)++] = digit + '0';
|
| + buffer[(*length)++] = static_cast<char>(digit + '0');
|
|
|
| // Can we stop already?
|
| // If the remainder of the division is less than the distance to the lower
|
| @@ -264,7 +282,7 @@
|
| // exponent (decimal_point), when rounding upwards.
|
| static void GenerateCountedDigits(int count, int* decimal_point,
|
| Bignum* numerator, Bignum* denominator,
|
| - Vector<char>(buffer), int* length) {
|
| + Vector<char> buffer, int* length) {
|
| ASSERT(count >= 0);
|
| for (int i = 0; i < count - 1; ++i) {
|
| uint16_t digit;
|
| @@ -272,7 +290,7 @@
|
| ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
|
| // digit = numerator / denominator (integer division).
|
| // numerator = numerator % denominator.
|
| - buffer[i] = digit + '0';
|
| + buffer[i] = static_cast<char>(digit + '0');
|
| // Prepare for next iteration.
|
| numerator->Times10();
|
| }
|
| @@ -282,7 +300,8 @@
|
| if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
|
| digit++;
|
| }
|
| - buffer[count - 1] = digit + '0';
|
| + ASSERT(digit <= 10);
|
| + buffer[count - 1] = static_cast<char>(digit + '0');
|
| // Correct bad digits (in case we had a sequence of '9's). Propagate the
|
| // carry until we hat a non-'9' or til we reach the first digit.
|
| for (int i = count - 1; i > 0; --i) {
|
| @@ -388,7 +407,7 @@
|
| const double k1Log10 = 0.30102999566398114; // 1/lg(10)
|
|
|
| // For doubles len(f) == 53 (don't forget the hidden bit).
|
| - const int kSignificandSize = 53;
|
| + const int kSignificandSize = Double::kSignificandSize;
|
| double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
|
| return static_cast<int>(estimate);
|
| }
|
| @@ -396,7 +415,8 @@
|
|
|
| // See comments for InitialScaledStartValues.
|
| static void InitialScaledStartValuesPositiveExponent(
|
| - double v, int estimated_power, bool need_boundary_deltas,
|
| + uint64_t significand, int exponent,
|
| + int estimated_power, bool need_boundary_deltas,
|
| Bignum* numerator, Bignum* denominator,
|
| Bignum* delta_minus, Bignum* delta_plus) {
|
| // A positive exponent implies a positive power.
|
| @@ -405,8 +425,8 @@
|
| // by 10^estimated_power.
|
|
|
| // numerator = v.
|
| - numerator->AssignUInt64(Double(v).Significand());
|
| - numerator->ShiftLeft(Double(v).Exponent());
|
| + numerator->AssignUInt64(significand);
|
| + numerator->ShiftLeft(exponent);
|
| // denominator = 10^estimated_power.
|
| denominator->AssignPowerUInt16(10, estimated_power);
|
|
|
| @@ -418,35 +438,20 @@
|
| // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
|
| // denominator (of 2) delta_plus equals 2^e.
|
| delta_plus->AssignUInt16(1);
|
| - delta_plus->ShiftLeft(Double(v).Exponent());
|
| - // Same for delta_minus (with adjustments below if f == 2^p-1).
|
| + delta_plus->ShiftLeft(exponent);
|
| + // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
|
| delta_minus->AssignUInt16(1);
|
| - delta_minus->ShiftLeft(Double(v).Exponent());
|
| -
|
| - // If the significand (without the hidden bit) is 0, then the lower
|
| - // boundary is closer than just half a ulp (unit in the last place).
|
| - // There is only one exception: if the next lower number is a denormal then
|
| - // the distance is 1 ulp. This cannot be the case for exponent >= 0 (but we
|
| - // have to test it in the other function where exponent < 0).
|
| - uint64_t v_bits = Double(v).AsUint64();
|
| - if ((v_bits & Double::kSignificandMask) == 0) {
|
| - // The lower boundary is closer at half the distance of "normal" numbers.
|
| - // Increase the common denominator and adapt all but the delta_minus.
|
| - denominator->ShiftLeft(1); // *2
|
| - numerator->ShiftLeft(1); // *2
|
| - delta_plus->ShiftLeft(1); // *2
|
| - }
|
| + delta_minus->ShiftLeft(exponent);
|
| }
|
| }
|
|
|
|
|
| // See comments for InitialScaledStartValues
|
| static void InitialScaledStartValuesNegativeExponentPositivePower(
|
| - double v, int estimated_power, bool need_boundary_deltas,
|
| + uint64_t significand, int exponent,
|
| + int estimated_power, bool need_boundary_deltas,
|
| Bignum* numerator, Bignum* denominator,
|
| Bignum* delta_minus, Bignum* delta_plus) {
|
| - uint64_t significand = Double(v).Significand();
|
| - int exponent = Double(v).Exponent();
|
| // v = f * 2^e with e < 0, and with estimated_power >= 0.
|
| // This means that e is close to 0 (have a look at how estimated_power is
|
| // computed).
|
| @@ -469,36 +474,18 @@
|
| // Given that the denominator already includes v's exponent the distance
|
| // to the boundaries is simply 1.
|
| delta_plus->AssignUInt16(1);
|
| - // Same for delta_minus (with adjustments below if f == 2^p-1).
|
| + // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
|
| delta_minus->AssignUInt16(1);
|
| -
|
| - // If the significand (without the hidden bit) is 0, then the lower
|
| - // boundary is closer than just one ulp (unit in the last place).
|
| - // There is only one exception: if the next lower number is a denormal
|
| - // then the distance is 1 ulp. Since the exponent is close to zero
|
| - // (otherwise estimated_power would have been negative) this cannot happen
|
| - // here either.
|
| - uint64_t v_bits = Double(v).AsUint64();
|
| - if ((v_bits & Double::kSignificandMask) == 0) {
|
| - // The lower boundary is closer at half the distance of "normal" numbers.
|
| - // Increase the denominator and adapt all but the delta_minus.
|
| - denominator->ShiftLeft(1); // *2
|
| - numerator->ShiftLeft(1); // *2
|
| - delta_plus->ShiftLeft(1); // *2
|
| - }
|
| }
|
| }
|
|
|
|
|
| // See comments for InitialScaledStartValues
|
| static void InitialScaledStartValuesNegativeExponentNegativePower(
|
| - double v, int estimated_power, bool need_boundary_deltas,
|
| + uint64_t significand, int exponent,
|
| + int estimated_power, bool need_boundary_deltas,
|
| Bignum* numerator, Bignum* denominator,
|
| Bignum* delta_minus, Bignum* delta_plus) {
|
| - const uint64_t kMinimalNormalizedExponent =
|
| - UINT64_2PART_C(0x00100000, 00000000);
|
| - uint64_t significand = Double(v).Significand();
|
| - int exponent = Double(v).Exponent();
|
| // Instead of multiplying the denominator with 10^estimated_power we
|
| // multiply all values (numerator and deltas) by 10^-estimated_power.
|
|
|
| @@ -535,18 +522,7 @@
|
| // delta_plus = 10^-estimated_power, and
|
| // delta_minus = 10^-estimated_power.
|
| // These assignments have been done earlier.
|
| -
|
| - // The special case where the lower boundary is twice as close.
|
| - // This time we have to look out for the exception too.
|
| - uint64_t v_bits = Double(v).AsUint64();
|
| - if ((v_bits & Double::kSignificandMask) == 0 &&
|
| - // The only exception where a significand == 0 has its boundaries at
|
| - // "normal" distances:
|
| - (v_bits & Double::kExponentMask) != kMinimalNormalizedExponent) {
|
| - numerator->ShiftLeft(1); // *2
|
| - denominator->ShiftLeft(1); // *2
|
| - delta_plus->ShiftLeft(1); // *2
|
| - }
|
| + // The adjustments if f == 2^p-1 (lower boundary is closer) are done later.
|
| }
|
| }
|
|
|
| @@ -586,27 +562,39 @@
|
| //
|
| // It is then easy to kickstart the digit-generation routine.
|
| //
|
| -// The boundary-deltas are only filled if need_boundary_deltas is set.
|
| -static void InitialScaledStartValues(double v,
|
| +// The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST
|
| +// or BIGNUM_DTOA_SHORTEST_SINGLE.
|
| +
|
| +static void InitialScaledStartValues(uint64_t significand,
|
| + int exponent,
|
| + bool lower_boundary_is_closer,
|
| int estimated_power,
|
| bool need_boundary_deltas,
|
| Bignum* numerator,
|
| Bignum* denominator,
|
| Bignum* delta_minus,
|
| Bignum* delta_plus) {
|
| - if (Double(v).Exponent() >= 0) {
|
| + if (exponent >= 0) {
|
| InitialScaledStartValuesPositiveExponent(
|
| - v, estimated_power, need_boundary_deltas,
|
| + significand, exponent, estimated_power, need_boundary_deltas,
|
| numerator, denominator, delta_minus, delta_plus);
|
| } else if (estimated_power >= 0) {
|
| InitialScaledStartValuesNegativeExponentPositivePower(
|
| - v, estimated_power, need_boundary_deltas,
|
| + significand, exponent, estimated_power, need_boundary_deltas,
|
| numerator, denominator, delta_minus, delta_plus);
|
| } else {
|
| InitialScaledStartValuesNegativeExponentNegativePower(
|
| - v, estimated_power, need_boundary_deltas,
|
| + significand, exponent, estimated_power, need_boundary_deltas,
|
| numerator, denominator, delta_minus, delta_plus);
|
| }
|
| +
|
| + if (need_boundary_deltas && lower_boundary_is_closer) {
|
| + // The lower boundary is closer at half the distance of "normal" numbers.
|
| + // Increase the common denominator and adapt all but the delta_minus.
|
| + denominator->ShiftLeft(1); // *2
|
| + numerator->ShiftLeft(1); // *2
|
| + delta_plus->ShiftLeft(1); // *2
|
| + }
|
| }
|
|
|
|
|
|
|