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 |
+ } |
} |