Index: runtime/third_party/double-conversion/src/double-conversion.cc |
=================================================================== |
--- runtime/third_party/double-conversion/src/double-conversion.cc (revision 33139) |
+++ runtime/third_party/double-conversion/src/double-conversion.cc (working copy) |
@@ -31,9 +31,9 @@ |
#include "double-conversion.h" |
#include "bignum-dtoa.h" |
-#include "double.h" |
#include "fast-dtoa.h" |
#include "fixed-dtoa.h" |
+#include "ieee.h" |
#include "strtod.h" |
#include "utils.h" |
@@ -98,7 +98,8 @@ |
} |
ASSERT(exponent < 1e4); |
const int kMaxExponentLength = 5; |
- char buffer[kMaxExponentLength]; |
+ char buffer[kMaxExponentLength + 1]; |
+ buffer[kMaxExponentLength] = '\0'; |
int first_char_pos = kMaxExponentLength; |
while (exponent > 0) { |
buffer[--first_char_pos] = '0' + (exponent % 10); |
@@ -157,8 +158,11 @@ |
} |
-bool DoubleToStringConverter::ToShortest(double value, |
- StringBuilder* result_builder) const { |
+bool DoubleToStringConverter::ToShortestIeeeNumber( |
+ double value, |
+ StringBuilder* result_builder, |
+ DoubleToStringConverter::DtoaMode mode) const { |
+ ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE); |
if (Double(value).IsSpecial()) { |
return HandleSpecialValues(value, result_builder); |
} |
@@ -169,7 +173,7 @@ |
char decimal_rep[kDecimalRepCapacity]; |
int decimal_rep_length; |
- DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity, |
+ DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity, |
&sign, &decimal_rep_length, &decimal_point); |
bool unique_zero = (flags_ & UNIQUE_ZERO) != 0; |
@@ -338,11 +342,12 @@ |
DoubleToStringConverter::DtoaMode dtoa_mode) { |
switch (dtoa_mode) { |
case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST; |
+ case DoubleToStringConverter::SHORTEST_SINGLE: |
+ return BIGNUM_DTOA_SHORTEST_SINGLE; |
case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED; |
case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; |
default: |
UNREACHABLE(); |
- return BIGNUM_DTOA_SHORTEST; // To silence compiler. |
} |
} |
@@ -357,7 +362,7 @@ |
int* point) { |
Vector<char> vector(buffer, buffer_length); |
ASSERT(!Double(v).IsSpecial()); |
- ASSERT(mode == SHORTEST || requested_digits >= 0); |
+ ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0); |
if (Double(v).Sign() < 0) { |
*sign = true; |
@@ -385,6 +390,10 @@ |
case SHORTEST: |
fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point); |
break; |
+ case SHORTEST_SINGLE: |
+ fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, |
+ vector, length, point); |
+ break; |
case FIXED: |
fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point); |
break; |
@@ -393,8 +402,8 @@ |
vector, length, point); |
break; |
default: |
+ fast_worked = false; |
UNREACHABLE(); |
- fast_worked = false; |
} |
if (fast_worked) return; |
@@ -452,16 +461,43 @@ |
} |
+// Returns true if 'c' is a decimal digit that is valid for the given radix. |
+// |
+// The function is small and could be inlined, but VS2012 emitted a warning |
+// because it constant-propagated the radix and concluded that the last |
+// condition was always true. By moving it into a separate function the |
+// compiler wouldn't warn anymore. |
+static bool IsDecimalDigitForRadix(int c, int radix) { |
+ return '0' <= c && c <= '9' && (c - '0') < radix; |
+} |
+ |
+// Returns true if 'c' is a character digit that is valid for the given radix. |
+// The 'a_character' should be 'a' or 'A'. |
+// |
+// The function is small and could be inlined, but VS2012 emitted a warning |
+// because it constant-propagated the radix and concluded that the first |
+// condition was always false. By moving it into a separate function the |
+// compiler wouldn't warn anymore. |
+static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { |
+ return radix > 10 && c >= a_character && c < a_character + radix - 10; |
+} |
+ |
+ |
// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. |
template <int radix_log_2> |
-static double RadixStringToDouble(const char* current, |
- const char* end, |
- bool sign, |
- bool allow_trailing_junk, |
- double junk_string_value, |
- const char** trailing_pointer) { |
+static double RadixStringToIeee(const char* current, |
+ const char* end, |
+ bool sign, |
+ bool allow_trailing_junk, |
+ double junk_string_value, |
+ bool read_as_double, |
+ const char** trailing_pointer) { |
ASSERT(current != end); |
+ const int kDoubleSize = Double::kSignificandSize; |
+ const int kSingleSize = Single::kSignificandSize; |
+ const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; |
+ |
// Skip leading 0s. |
while (*current == '0') { |
++current; |
@@ -477,11 +513,11 @@ |
do { |
int digit; |
- if (*current >= '0' && *current <= '9' && *current < '0' + radix) { |
+ if (IsDecimalDigitForRadix(*current, radix)) { |
digit = static_cast<char>(*current) - '0'; |
- } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { |
+ } else if (IsCharacterDigitForRadix(*current, radix, 'a')) { |
digit = static_cast<char>(*current) - 'a' + 10; |
- } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { |
+ } else if (IsCharacterDigitForRadix(*current, radix, 'A')) { |
digit = static_cast<char>(*current) - 'A' + 10; |
} else { |
if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) { |
@@ -492,7 +528,7 @@ |
} |
number = number * radix + digit; |
- int overflow = static_cast<int>(number >> 53); |
+ int overflow = static_cast<int>(number >> kSignificandSize); |
if (overflow != 0) { |
// Overflow occurred. Need to determine which direction to round the |
// result. |
@@ -508,7 +544,7 @@ |
exponent = overflow_bits_count; |
bool zero_tail = true; |
- while (true) { |
+ for (;;) { |
++current; |
if (current == end || !isDigit(*current, radix)) break; |
zero_tail = zero_tail && *current == '0'; |
@@ -531,7 +567,7 @@ |
} |
// Rounding up may cause overflow. |
- if ((number & ((int64_t)1 << 53)) != 0) { |
+ if ((number & ((int64_t)1 << kSignificandSize)) != 0) { |
exponent++; |
number >>= 1; |
} |
@@ -540,7 +576,7 @@ |
++current; |
} while (current != end); |
- ASSERT(number < ((int64_t)1 << 53)); |
+ ASSERT(number < ((int64_t)1 << kSignificandSize)); |
ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); |
*trailing_pointer = current; |
@@ -558,10 +594,11 @@ |
} |
-double StringToDoubleConverter::StringToDouble( |
+double StringToDoubleConverter::StringToIeee( |
const char* input, |
int length, |
- int* processed_characters_count) { |
+ int* processed_characters_count, |
+ bool read_as_double) const { |
const char* current = input; |
const char* end = input + length; |
@@ -584,7 +621,7 @@ |
if (allow_leading_spaces || allow_trailing_spaces) { |
if (!AdvanceToNonspace(¤t, end)) { |
- *processed_characters_count = current - input; |
+ *processed_characters_count = static_cast<int>(current - input); |
return empty_string_value_; |
} |
if (!allow_leading_spaces && (input != current)) { |
@@ -633,7 +670,7 @@ |
} |
ASSERT(buffer_pos == 0); |
- *processed_characters_count = current - input; |
+ *processed_characters_count = static_cast<int>(current - input); |
return sign ? -Double::Infinity() : Double::Infinity(); |
} |
} |
@@ -652,7 +689,7 @@ |
} |
ASSERT(buffer_pos == 0); |
- *processed_characters_count = current - input; |
+ *processed_characters_count = static_cast<int>(current - input); |
return sign ? -Double::NaN() : Double::NaN(); |
} |
} |
@@ -661,7 +698,7 @@ |
if (*current == '0') { |
++current; |
if (current == end) { |
- *processed_characters_count = current - input; |
+ *processed_characters_count = static_cast<int>(current - input); |
return SignedZero(sign); |
} |
@@ -675,15 +712,16 @@ |
} |
const char* tail_pointer = NULL; |
- double result = RadixStringToDouble<4>(current, |
- end, |
- sign, |
- allow_trailing_junk, |
- junk_string_value_, |
- &tail_pointer); |
+ double result = RadixStringToIeee<4>(current, |
+ end, |
+ sign, |
+ allow_trailing_junk, |
+ junk_string_value_, |
+ read_as_double, |
+ &tail_pointer); |
if (tail_pointer != NULL) { |
if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end); |
- *processed_characters_count = tail_pointer - input; |
+ *processed_characters_count = static_cast<int>(tail_pointer - input); |
} |
return result; |
} |
@@ -692,7 +730,7 @@ |
while (*current == '0') { |
++current; |
if (current == end) { |
- *processed_characters_count = current - input; |
+ *processed_characters_count = static_cast<int>(current - input); |
return SignedZero(sign); |
} |
} |
@@ -740,7 +778,7 @@ |
while (*current == '0') { |
++current; |
if (current == end) { |
- *processed_characters_count = current - input; |
+ *processed_characters_count = static_cast<int>(current - input); |
return SignedZero(sign); |
} |
exponent--; // Move this 0 into the exponent. |
@@ -839,14 +877,15 @@ |
if (octal) { |
double result; |
const char* tail_pointer = NULL; |
- result = RadixStringToDouble<3>(buffer, |
- buffer + buffer_pos, |
- sign, |
- allow_trailing_junk, |
- junk_string_value_, |
- &tail_pointer); |
+ result = RadixStringToIeee<3>(buffer, |
+ buffer + buffer_pos, |
+ sign, |
+ allow_trailing_junk, |
+ junk_string_value_, |
+ read_as_double, |
+ &tail_pointer); |
ASSERT(tail_pointer != NULL); |
- *processed_characters_count = current - input; |
+ *processed_characters_count = static_cast<int>(current - input); |
return result; |
} |
@@ -858,8 +897,13 @@ |
ASSERT(buffer_pos < kBufferSize); |
buffer[buffer_pos] = '\0'; |
- double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); |
- *processed_characters_count = current - input; |
+ double converted; |
+ if (read_as_double) { |
+ converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); |
+ } else { |
+ converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent); |
+ } |
+ *processed_characters_count = static_cast<int>(current - input); |
return sign? -converted: converted; |
} |