result_builder->AddCharacter('+');
}
}
- if (exponent == 0) {
- result_builder->AddCharacter('0');
- return;
- }
DOUBLE_CONVERSION_ASSERT(exponent < 1e4);
// Changing this constant requires updating the comment of DoubleToStringConverter constructor
const int kMaxExponentLength = 5;
char buffer[kMaxExponentLength + 1];
buffer[kMaxExponentLength] = '\0';
int first_char_pos = kMaxExponentLength;
- while (exponent > 0) {
- buffer[--first_char_pos] = '0' + (exponent % 10);
- exponent /= 10;
+ if (exponent == 0) {
+ buffer[--first_char_pos] = '0';
+ } else {
+ while (exponent > 0) {
+ buffer[--first_char_pos] = '0' + (exponent % 10);
+ exponent /= 10;
+ }
}
// Add prefix '0' to make exponent width >= min(min_exponent_with_, kMaxExponentLength)
// For example: convert 1e+9 -> 1e+09, if min_exponent_with_ is set to 2
int exponent = decimal_point - 1;
int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
- if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
+ bool as_exponential =
+ (-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
(decimal_point - precision + extra_zero >
- max_trailing_padding_zeroes_in_precision_mode_)) {
+ max_trailing_padding_zeroes_in_precision_mode_);
+ if ((flags_ & NO_TRAILING_ZERO) != 0) {
+ // Truncate trailing zeros that occur after the decimal point (if exponential,
+ // that is everything after the first digit).
+ int stop = as_exponential ? 1 : std::max(1, decimal_point);
+ while (decimal_rep_length > stop && decimal_rep[decimal_rep_length - 1] == '0') {
+ --decimal_rep_length;
+ }
+ // Clamp precision to avoid the code below re-adding the zeros.
+ precision = std::min(precision, decimal_rep_length);
+ }
+ if (as_exponential) {
// Fill buffer to contain 'precision' digits.
// Usually the buffer is already at the correct length, but 'DoubleToAscii'
// is allowed to return less characters.
class DoubleToStringConverter {
public:
-#if 0 // not needed for ICU
// When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint
// or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
// function returns false.
static const int kMaxFixedDigitsBeforePoint = 60;
- static const int kMaxFixedDigitsAfterPoint = 60;
+ static const int kMaxFixedDigitsAfterPoint = 100;
// When calling ToExponential with a requested_digits
// parameter > kMaxExponentialDigits then the function returns false.
static const int kMinPrecisionDigits = 1;
static const int kMaxPrecisionDigits = 120;
+ // The maximal number of digits that are needed to emit a double in base 10.
+ // A higher precision can be achieved by using more digits, but the shortest
+ // accurate representation of any double will never use more digits than
+ // kBase10MaximalLength.
+ // Note that DoubleToAscii null-terminates its input. So the given buffer
+ // should be at least kBase10MaximalLength + 1 characters long.
+ static const int kBase10MaximalLength = 17;
+
+ // The maximal number of digits that are needed to emit a single in base 10.
+ // A higher precision can be achieved by using more digits, but the shortest
+ // accurate representation of any single will never use more digits than
+ // kBase10MaximalLengthSingle.
+ static const int kBase10MaximalLengthSingle = 9;
+
+ // The length of the longest string that 'ToShortest' can produce when the
+ // converter is instantiated with EcmaScript defaults (see
+ // 'EcmaScriptConverter')
+ // This value does not include the trailing '\0' character.
+ // This amount of characters is needed for negative values that hit the
+ // 'decimal_in_shortest_low' limit. For example: "-0.0000033333333333333333"
+ static const int kMaxCharsEcmaScriptShortest = 25;
+
+#if 0 // not needed for ICU
enum Flags {
NO_FLAGS = 0,
EMIT_POSITIVE_EXPONENT_SIGN = 1,
EMIT_TRAILING_DECIMAL_POINT = 2,
EMIT_TRAILING_ZERO_AFTER_POINT = 4,
- UNIQUE_ZERO = 8
+ UNIQUE_ZERO = 8,
+ NO_TRAILING_ZERO = 16
};
// Flags should be a bit-or combination of the possible Flags-enum.
// Example: 2345.0 is converted to "2345.".
// - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
// emits a trailing '0'-character. This flag requires the
- // EXMIT_TRAILING_DECIMAL_POINT flag.
+ // EMIT_TRAILING_DECIMAL_POINT flag.
// Example: 2345.0 is converted to "2345.0".
// - UNIQUE_ZERO: "-0.0" is converted to "0.0".
+ // - NO_TRAILING_ZERO: Trailing zeros are removed from the fractional portion
+ // of the result in precision mode. Matches printf's %g.
+ // When EMIT_TRAILING_ZERO_AFTER_POINT is also given, one trailing zero is
+ // preserved.
//
// Infinity symbol and nan_symbol provide the string representation for these
// special values. If the string is NULL and the special value is encountered
}
// Returns a converter following the EcmaScript specification.
+ //
+ // Flags: UNIQUE_ZERO and EMIT_POSITIVE_EXPONENT_SIGN.
+ // Special values: "Infinity" and "NaN".
+ // Lower case 'e' for exponential values.
+ // decimal_in_shortest_low: -6
+ // decimal_in_shortest_high: 21
+ // max_leading_padding_zeroes_in_precision_mode: 6
+ // max_trailing_padding_zeroes_in_precision_mode: 0
static const DoubleToStringConverter& EcmaScriptConverter();
// Computes the shortest string of digits that correctly represent the input
// Returns true if the conversion succeeds. The conversion always succeeds
// except when the input value is special and no infinity_symbol or
// nan_symbol has been given to the constructor.
+ //
+ // The length of the longest result is the maximum of the length of the
+ // following string representations (each with possible examples):
+ // - NaN and negative infinity: "NaN", "-Infinity", "-inf".
+ // - -10^(decimal_in_shortest_high - 1):
+ // "-100000000000000000000", "-1000000000000000.0"
+ // - the longest string in range [0; -10^decimal_in_shortest_low]. Generally,
+ // this string is 3 + kBase10MaximalLength - decimal_in_shortest_low.
+ // (Sign, '0', decimal point, padding zeroes for decimal_in_shortest_low,
+ // and the significant digits).
+ // "-0.0000033333333333333333", "-0.0012345678901234567"
+ // - the longest exponential representation. (A negative number with
+ // kBase10MaximalLength significant digits).
+ // "-1.7976931348623157e+308", "-1.7976931348623157E308"
+ // In addition, the buffer must be able to hold the trailing '\0' character.
bool ToShortest(double value, StringBuilder* result_builder) const {
return ToShortestIeeeNumber(value, result_builder, SHORTEST);
}
// been provided to the constructor,
// - 'value' > 10^kMaxFixedDigitsBeforePoint, or
// - 'requested_digits' > kMaxFixedDigitsAfterPoint.
- // The last two conditions imply that the result will never contain more than
- // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
+ // The last two conditions imply that the result for non-special values never
+ // contains more than
+ // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
// (one additional character for the sign, and one for the decimal point).
+ // In addition, the buffer must be able to hold the trailing '\0' character.
bool ToFixed(double value,
int requested_digits,
StringBuilder* result_builder) const;
// - the input value is special and no infinity_symbol or nan_symbol has
// been provided to the constructor,
// - 'requested_digits' > kMaxExponentialDigits.
- // The last condition implies that the result will never contain more than
+ //
+ // The last condition implies that the result never contains more than
// kMaxExponentialDigits + 8 characters (the sign, the digit before the
// decimal point, the decimal point, the exponent character, the
// exponent's sign, and at most 3 exponent digits).
+ // In addition, the buffer must be able to hold the trailing '\0' character.
bool ToExponential(double value,
int requested_digits,
StringBuilder* result_builder) const;
+
// Computes 'precision' leading digits of the given 'value' and returns them
// either in exponential or decimal format, depending on
// max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
// been provided to the constructor,
// - precision < kMinPericisionDigits
// - precision > kMaxPrecisionDigits
- // The last condition implies that the result will never contain more than
+ //
+ // The last condition implies that the result never contains more than
// kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
// exponent character, the exponent's sign, and at most 3 exponent digits).
+ // In addition, the buffer must be able to hold the trailing '\0' character.
bool ToPrecision(double value,
int precision,
StringBuilder* result_builder) const;
PRECISION
};
- // The maximal number of digits that are needed to emit a double in base 10.
- // A higher precision can be achieved by using more digits, but the shortest
- // accurate representation of any double will never use more digits than
- // kBase10MaximalLength.
- // Note that DoubleToAscii null-terminates its input. So the given buffer
- // should be at least kBase10MaximalLength + 1 characters long.
- static const int kBase10MaximalLength = 17;
-
// Converts the given double 'v' to digit characters. 'v' must not be NaN,
// +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
// applies to 'v' after it has been casted to a single-precision float. That
// ICU PATCH: Wrap in ICU namespace
U_NAMESPACE_BEGIN
+#ifdef _MSC_VER
+# if _MSC_VER >= 1900
+// Fix MSVC >= 2015 (_MSC_VER == 1900) warning
+// C4244: 'argument': conversion from 'const uc16' to 'char', possible loss of data
+// against Advance and friends, when instantiated with **it as char, not uc16.
+ __pragma(warning(disable: 4244))
+# endif
+# if _MSC_VER <= 1700 // VS2012, see IsDecimalDigitForRadix warning fix, below
+# define VS2012_RADIXWARN
+# endif
+#endif
+
namespace double_conversion {
namespace {
//
// 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.
-#ifdef _MSC_VER
+// condition was always true. Moving it into a separate function and
+// suppressing optimisation keeps the compiler from warning.
+#ifdef VS2012_RADIXWARN
#pragma optimize("",off)
static bool IsDecimalDigitForRadix(int c, int radix) {
return '0' <= c && c <= '9' && (c - '0') < radix;
DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos] = '\0';
+ // Code above ensures there are no leading zeros and the buffer has fewer than
+ // kMaxSignificantDecimalDigits characters. Trim trailing zeros.
+ Vector<const char> chars(buffer, buffer_pos);
+ chars = TrimTrailingZeros(chars);
+ exponent += buffer_pos - chars.length();
+
double converted;
if (read_as_double) {
- converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
+ converted = StrtodTrimmed(chars, exponent);
} else {
- converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
+ converted = StrtofTrimmed(chars, exponent);
}
*processed_characters_count = static_cast<int>(current - input);
return sign? -converted: converted;
return Vector<const char>(buffer.start(), 0);
}
-
-static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
- for (int i = buffer.length() - 1; i >= 0; --i) {
- if (buffer[i] != '0') {
- return buffer.SubVector(0, i + 1);
- }
- }
- return Vector<const char>(buffer.start(), 0);
-}
-
-
static void CutToMaxSignificantDigits(Vector<const char> buffer,
int exponent,
char* significant_buffer,
int exponent,
double* result) {
#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
+ // Avoid "unused parameter" warnings
+ (void) trimmed;
+ (void) exponent;
+ (void) result;
// On x86 the floating-point stack can be 64 or 80 bits wide. If it is
// 80 bits wide (as is the case on Linux) then double-rounding occurs and the
// result is not accurate.
// We know that Windows32 uses 64 bits and is therefore accurate.
- // Note that the ARM simulator is compiled for 32bits. It therefore exhibits
- // the same problem.
return false;
#else
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
return ('1' <= d) && (d <= '9');
}
+#ifdef __has_cpp_attribute
+#if __has_cpp_attribute(maybe_unused)
+[[maybe_unused]]
+#endif
+#endif
static bool AssertTrimmedDigits(const Vector<const char>& buffer) {
for(int i = 0; i < buffer.length(); ++i) {
if(!IsDigit(buffer[i])) {
TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
&trimmed, &updated_exponent);
exponent = updated_exponent;
+ return StrtofTrimmed(trimmed, exponent);
+}
+
+float StrtofTrimmed(Vector<const char> trimmed, int exponent) {
+ DOUBLE_CONVERSION_ASSERT(trimmed.length() <= kMaxSignificantDecimalDigits);
+ DOUBLE_CONVERSION_ASSERT(AssertTrimmedDigits(trimmed));
double double_guess;
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
// contain a dot or a sign. It must not start with '0', and must not be empty.
float Strtof(Vector<const char> buffer, int exponent);
-// For special use cases, the heart of the Strtod() function is also available
-// separately, it assumes that 'trimmed' is as produced by TrimAndCut(), i.e.
-// no leading or trailing zeros, also no lone zero, and not 'too many' digits.
+// Same as Strtod, but assumes that 'trimmed' is already trimmed, as if run
+// through TrimAndCut. That is, 'trimmed' must have no leading or trailing
+// zeros, must not be a lone zero, and must not have 'too many' digits.
double StrtodTrimmed(Vector<const char> trimmed, int exponent);
+// Same as Strtof, but assumes that 'trimmed' is already trimmed, as if run
+// through TrimAndCut. That is, 'trimmed' must have no leading or trailing
+// zeros, must not be a lone zero, and must not have 'too many' digits.
+float StrtofTrimmed(Vector<const char> trimmed, int exponent);
+
+inline Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
+ for (int i = buffer.length() - 1; i >= 0; --i) {
+ if (buffer[i] != '0') {
+ return buffer.SubVector(0, i + 1);
+ }
+ }
+ return Vector<const char>(buffer.start(), 0);
+}
+
} // namespace double_conversion
// ICU PATCH: Close ICU namespace
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(__hppa__) || defined(__ia64__) || \
defined(__mips__) || \
- defined(__nios2__) || \
+ defined(__nios2__) || defined(__ghs) || \
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
*.kdev4
DartConfiguration.tcl
bazel-*
-
+.cache
result_builder->AddCharacter('+');
}
}
- if (exponent == 0) {
- result_builder->AddCharacter('0');
- return;
- }
DOUBLE_CONVERSION_ASSERT(exponent < 1e4);
// Changing this constant requires updating the comment of DoubleToStringConverter constructor
const int kMaxExponentLength = 5;
char buffer[kMaxExponentLength + 1];
buffer[kMaxExponentLength] = '\0';
int first_char_pos = kMaxExponentLength;
- while (exponent > 0) {
- buffer[--first_char_pos] = '0' + (exponent % 10);
- exponent /= 10;
+ if (exponent == 0) {
+ buffer[--first_char_pos] = '0';
+ } else {
+ while (exponent > 0) {
+ buffer[--first_char_pos] = '0' + (exponent % 10);
+ exponent /= 10;
+ }
}
// Add prefix '0' to make exponent width >= min(min_exponent_with_, kMaxExponentLength)
// For example: convert 1e+9 -> 1e+09, if min_exponent_with_ is set to 2
int exponent = decimal_point - 1;
int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
- if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
+ bool as_exponential =
+ (-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
(decimal_point - precision + extra_zero >
- max_trailing_padding_zeroes_in_precision_mode_)) {
+ max_trailing_padding_zeroes_in_precision_mode_);
+ if ((flags_ & NO_TRAILING_ZERO) != 0) {
+ // Truncate trailing zeros that occur after the decimal point (if exponential,
+ // that is everything after the first digit).
+ int stop = as_exponential ? 1 : std::max(1, decimal_point);
+ while (decimal_rep_length > stop && decimal_rep[decimal_rep_length - 1] == '0') {
+ --decimal_rep_length;
+ }
+ // Clamp precision to avoid the code below re-adding the zeros.
+ precision = std::min(precision, decimal_rep_length);
+ }
+ if (as_exponential) {
// Fill buffer to contain 'precision' digits.
// Usually the buffer is already at the correct length, but 'DoubleToAscii'
// is allowed to return less characters.
// or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
// function returns false.
static const int kMaxFixedDigitsBeforePoint = 60;
- static const int kMaxFixedDigitsAfterPoint = 60;
+ static const int kMaxFixedDigitsAfterPoint = 100;
// When calling ToExponential with a requested_digits
// parameter > kMaxExponentialDigits then the function returns false.
static const int kMinPrecisionDigits = 1;
static const int kMaxPrecisionDigits = 120;
+ // The maximal number of digits that are needed to emit a double in base 10.
+ // A higher precision can be achieved by using more digits, but the shortest
+ // accurate representation of any double will never use more digits than
+ // kBase10MaximalLength.
+ // Note that DoubleToAscii null-terminates its input. So the given buffer
+ // should be at least kBase10MaximalLength + 1 characters long.
+ static const int kBase10MaximalLength = 17;
+
+ // The maximal number of digits that are needed to emit a single in base 10.
+ // A higher precision can be achieved by using more digits, but the shortest
+ // accurate representation of any single will never use more digits than
+ // kBase10MaximalLengthSingle.
+ static const int kBase10MaximalLengthSingle = 9;
+
+ // The length of the longest string that 'ToShortest' can produce when the
+ // converter is instantiated with EcmaScript defaults (see
+ // 'EcmaScriptConverter')
+ // This value does not include the trailing '\0' character.
+ // This amount of characters is needed for negative values that hit the
+ // 'decimal_in_shortest_low' limit. For example: "-0.0000033333333333333333"
+ static const int kMaxCharsEcmaScriptShortest = 25;
+
enum Flags {
NO_FLAGS = 0,
EMIT_POSITIVE_EXPONENT_SIGN = 1,
EMIT_TRAILING_DECIMAL_POINT = 2,
EMIT_TRAILING_ZERO_AFTER_POINT = 4,
- UNIQUE_ZERO = 8
+ UNIQUE_ZERO = 8,
+ NO_TRAILING_ZERO = 16
};
// Flags should be a bit-or combination of the possible Flags-enum.
// Example: 2345.0 is converted to "2345.".
// - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
// emits a trailing '0'-character. This flag requires the
- // EXMIT_TRAILING_DECIMAL_POINT flag.
+ // EMIT_TRAILING_DECIMAL_POINT flag.
// Example: 2345.0 is converted to "2345.0".
// - UNIQUE_ZERO: "-0.0" is converted to "0.0".
+ // - NO_TRAILING_ZERO: Trailing zeros are removed from the fractional portion
+ // of the result in precision mode. Matches printf's %g.
+ // When EMIT_TRAILING_ZERO_AFTER_POINT is also given, one trailing zero is
+ // preserved.
//
// Infinity symbol and nan_symbol provide the string representation for these
// special values. If the string is NULL and the special value is encountered
}
// Returns a converter following the EcmaScript specification.
+ //
+ // Flags: UNIQUE_ZERO and EMIT_POSITIVE_EXPONENT_SIGN.
+ // Special values: "Infinity" and "NaN".
+ // Lower case 'e' for exponential values.
+ // decimal_in_shortest_low: -6
+ // decimal_in_shortest_high: 21
+ // max_leading_padding_zeroes_in_precision_mode: 6
+ // max_trailing_padding_zeroes_in_precision_mode: 0
static const DoubleToStringConverter& EcmaScriptConverter();
// Computes the shortest string of digits that correctly represent the input
// Returns true if the conversion succeeds. The conversion always succeeds
// except when the input value is special and no infinity_symbol or
// nan_symbol has been given to the constructor.
+ //
+ // The length of the longest result is the maximum of the length of the
+ // following string representations (each with possible examples):
+ // - NaN and negative infinity: "NaN", "-Infinity", "-inf".
+ // - -10^(decimal_in_shortest_high - 1):
+ // "-100000000000000000000", "-1000000000000000.0"
+ // - the longest string in range [0; -10^decimal_in_shortest_low]. Generally,
+ // this string is 3 + kBase10MaximalLength - decimal_in_shortest_low.
+ // (Sign, '0', decimal point, padding zeroes for decimal_in_shortest_low,
+ // and the significant digits).
+ // "-0.0000033333333333333333", "-0.0012345678901234567"
+ // - the longest exponential representation. (A negative number with
+ // kBase10MaximalLength significant digits).
+ // "-1.7976931348623157e+308", "-1.7976931348623157E308"
+ // In addition, the buffer must be able to hold the trailing '\0' character.
bool ToShortest(double value, StringBuilder* result_builder) const {
return ToShortestIeeeNumber(value, result_builder, SHORTEST);
}
// been provided to the constructor,
// - 'value' > 10^kMaxFixedDigitsBeforePoint, or
// - 'requested_digits' > kMaxFixedDigitsAfterPoint.
- // The last two conditions imply that the result will never contain more than
- // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
+ // The last two conditions imply that the result for non-special values never
+ // contains more than
+ // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
// (one additional character for the sign, and one for the decimal point).
+ // In addition, the buffer must be able to hold the trailing '\0' character.
bool ToFixed(double value,
int requested_digits,
StringBuilder* result_builder) const;
// - the input value is special and no infinity_symbol or nan_symbol has
// been provided to the constructor,
// - 'requested_digits' > kMaxExponentialDigits.
- // The last condition implies that the result will never contain more than
+ //
+ // The last condition implies that the result never contains more than
// kMaxExponentialDigits + 8 characters (the sign, the digit before the
// decimal point, the decimal point, the exponent character, the
// exponent's sign, and at most 3 exponent digits).
+ // In addition, the buffer must be able to hold the trailing '\0' character.
bool ToExponential(double value,
int requested_digits,
StringBuilder* result_builder) const;
+
// Computes 'precision' leading digits of the given 'value' and returns them
// either in exponential or decimal format, depending on
// max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
// been provided to the constructor,
// - precision < kMinPericisionDigits
// - precision > kMaxPrecisionDigits
- // The last condition implies that the result will never contain more than
+ //
+ // The last condition implies that the result never contains more than
// kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
// exponent character, the exponent's sign, and at most 3 exponent digits).
+ // In addition, the buffer must be able to hold the trailing '\0' character.
bool ToPrecision(double value,
int precision,
StringBuilder* result_builder) const;
PRECISION
};
- // The maximal number of digits that are needed to emit a double in base 10.
- // A higher precision can be achieved by using more digits, but the shortest
- // accurate representation of any double will never use more digits than
- // kBase10MaximalLength.
- // Note that DoubleToAscii null-terminates its input. So the given buffer
- // should be at least kBase10MaximalLength + 1 characters long.
- static const int kBase10MaximalLength = 17;
-
// Converts the given double 'v' to digit characters. 'v' must not be NaN,
// +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
// applies to 'v' after it has been casted to a single-precision float. That
#include "strtod.h"
#include "utils.h"
+#ifdef _MSC_VER
+# if _MSC_VER >= 1900
+// Fix MSVC >= 2015 (_MSC_VER == 1900) warning
+// C4244: 'argument': conversion from 'const uc16' to 'char', possible loss of data
+// against Advance and friends, when instantiated with **it as char, not uc16.
+ __pragma(warning(disable: 4244))
+# endif
+# if _MSC_VER <= 1700 // VS2012, see IsDecimalDigitForRadix warning fix, below
+# define VS2012_RADIXWARN
+# endif
+#endif
+
namespace double_conversion {
namespace {
//
// 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.
-#ifdef _MSC_VER
+// condition was always true. Moving it into a separate function and
+// suppressing optimisation keeps the compiler from warning.
+#ifdef VS2012_RADIXWARN
#pragma optimize("",off)
static bool IsDecimalDigitForRadix(int c, int radix) {
return '0' <= c && c <= '9' && (c - '0') < radix;
DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos] = '\0';
+ // Code above ensures there are no leading zeros and the buffer has fewer than
+ // kMaxSignificantDecimalDigits characters. Trim trailing zeros.
+ Vector<const char> chars(buffer, buffer_pos);
+ chars = TrimTrailingZeros(chars);
+ exponent += buffer_pos - chars.length();
+
double converted;
if (read_as_double) {
- converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
+ converted = StrtodTrimmed(chars, exponent);
} else {
- converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
+ converted = StrtofTrimmed(chars, exponent);
}
*processed_characters_count = static_cast<int>(current - input);
return sign? -converted: converted;
return Vector<const char>(buffer.start(), 0);
}
-
-static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
- for (int i = buffer.length() - 1; i >= 0; --i) {
- if (buffer[i] != '0') {
- return buffer.SubVector(0, i + 1);
- }
- }
- return Vector<const char>(buffer.start(), 0);
-}
-
-
static void CutToMaxSignificantDigits(Vector<const char> buffer,
int exponent,
char* significant_buffer,
int exponent,
double* result) {
#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
+ // Avoid "unused parameter" warnings
+ (void) trimmed;
+ (void) exponent;
+ (void) result;
// On x86 the floating-point stack can be 64 or 80 bits wide. If it is
// 80 bits wide (as is the case on Linux) then double-rounding occurs and the
// result is not accurate.
// We know that Windows32 uses 64 bits and is therefore accurate.
- // Note that the ARM simulator is compiled for 32bits. It therefore exhibits
- // the same problem.
return false;
#else
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
return ('1' <= d) && (d <= '9');
}
+#ifdef __has_cpp_attribute
+#if __has_cpp_attribute(maybe_unused)
+[[maybe_unused]]
+#endif
+#endif
static bool AssertTrimmedDigits(const Vector<const char>& buffer) {
for(int i = 0; i < buffer.length(); ++i) {
if(!IsDigit(buffer[i])) {
TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
&trimmed, &updated_exponent);
exponent = updated_exponent;
+ return StrtofTrimmed(trimmed, exponent);
+}
+
+float StrtofTrimmed(Vector<const char> trimmed, int exponent) {
+ DOUBLE_CONVERSION_ASSERT(trimmed.length() <= kMaxSignificantDecimalDigits);
+ DOUBLE_CONVERSION_ASSERT(AssertTrimmedDigits(trimmed));
double double_guess;
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
// contain a dot or a sign. It must not start with '0', and must not be empty.
float Strtof(Vector<const char> buffer, int exponent);
-// For special use cases, the heart of the Strtod() function is also available
-// separately, it assumes that 'trimmed' is as produced by TrimAndCut(), i.e.
-// no leading or trailing zeros, also no lone zero, and not 'too many' digits.
+// Same as Strtod, but assumes that 'trimmed' is already trimmed, as if run
+// through TrimAndCut. That is, 'trimmed' must have no leading or trailing
+// zeros, must not be a lone zero, and must not have 'too many' digits.
double StrtodTrimmed(Vector<const char> trimmed, int exponent);
+// Same as Strtof, but assumes that 'trimmed' is already trimmed, as if run
+// through TrimAndCut. That is, 'trimmed' must have no leading or trailing
+// zeros, must not be a lone zero, and must not have 'too many' digits.
+float StrtofTrimmed(Vector<const char> trimmed, int exponent);
+
+inline Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
+ for (int i = buffer.length() - 1; i >= 0; --i) {
+ if (buffer[i] != '0') {
+ return buffer.SubVector(0, i + 1);
+ }
+ }
+ return Vector<const char>(buffer.start(), 0);
+}
+
} // namespace double_conversion
#endif // DOUBLE_CONVERSION_STRTOD_H_
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(__hppa__) || defined(__ia64__) || \
defined(__mips__) || \
- defined(__nios2__) || \
+ defined(__nios2__) || defined(__ghs) || \
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
TEST(DoubleToFixed) {
- const int kBufferSize = 128;
+ const int kBufferSize = 168;
char buffer[kBufferSize];
StringBuilder builder(buffer, kBufferSize);
int flags = DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
CHECK_EQ("0.0", builder.Finalize());
DOUBLE_CONVERSION_ASSERT(DoubleToStringConverter::kMaxFixedDigitsBeforePoint == 60);
- DOUBLE_CONVERSION_ASSERT(DoubleToStringConverter::kMaxFixedDigitsAfterPoint == 60);
+ DOUBLE_CONVERSION_ASSERT(DoubleToStringConverter::kMaxFixedDigitsAfterPoint == 100);
+
+ // Most of the 100 digit tests were copied from
+ // https://searchfox.org/mozilla-central/source/js/src/tests/non262/Number/toFixed-values.js.
+
builder.Reset();
CHECK(dc.ToFixed(
0.0, DoubleToStringConverter::kMaxFixedDigitsAfterPoint, &builder));
- CHECK_EQ("0.000000000000000000000000000000000000000000000000000000000000",
+ CHECK_EQ("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
builder.Finalize());
builder.Reset();
CHECK(dc.ToFixed(
9e59, DoubleToStringConverter::kMaxFixedDigitsAfterPoint, &builder));
CHECK_EQ("899999999999999918767229449717619953810131273674690656206848."
- "000000000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
builder.Finalize());
builder.Reset();
CHECK(dc.ToFixed(
-9e59, DoubleToStringConverter::kMaxFixedDigitsAfterPoint, &builder));
CHECK_EQ("-899999999999999918767229449717619953810131273674690656206848."
- "000000000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(
+ 1e-100, DoubleToStringConverter::kMaxFixedDigitsAfterPoint, &builder));
+ CHECK_EQ("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(0.3000000000000000444089209850062616169452667236328125,
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("0.3000000000000000444089209850062616169452667236328125000000000000000000000000000000000000000000000000",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(1.5e-100,
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(1.15e-99, // In reality: 1.14999999999999992147301128036734...
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(3.141592653589793,
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(1.0,
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(-123456.78,
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("-123456.7799999999988358467817306518554687500000000000000000000000000000000000000000000000000000000000000000",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(123456.78,
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("123456.7799999999988358467817306518554687500000000000000000000000000000000000000000000000000000000000000000",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(100000000000000000000.0,
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("100000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc.ToFixed(-100000000000000000000.0,
+ DoubleToStringConverter::kMaxFixedDigitsAfterPoint,
+ &builder));
+ CHECK_EQ("-100000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
builder.Finalize());
builder.Reset();
CHECK(dc5.ToFixed(0.1, 30, &builder));
CHECK_EQ("0.100000000000000005551115123126", builder.Finalize());
+ builder.Reset();
+ CHECK(dc5.ToFixed(0.1, 100, &builder));
+ CHECK_EQ("0.1000000000000000055511151231257827021181583404541015625000000000000000000000000000000000000000000000", builder.Finalize());
+
builder.Reset();
CHECK(dc5.ToFixed(0.1, 17, &builder));
CHECK_EQ("0.10000000000000001", builder.Finalize());
builder.Reset();
CHECK(dc4.ToExponential(-Double::NaN(), 1, &builder));
CHECK_EQ("NaN", builder.Finalize());
+
+ // Test min_exponent_width
+ DoubleToStringConverter dc5(flags, NULL, NULL, 'e', 0, 0, 0, 0, 2);
+
+ builder.Reset();
+ CHECK(dc5.ToExponential(11111111111.0, 6, &builder));
+ CHECK_EQ("1.111111e10", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToExponential(1111111111.0, 6, &builder));
+ CHECK_EQ("1.111111e09", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToExponential(1111111.0, 6, &builder));
+ CHECK_EQ("1.111111e06", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToExponential(10000000000.0, 6, &builder));
+ CHECK_EQ("1.000000e10", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToExponential(1000000000.0, 6, &builder));
+ CHECK_EQ("1.000000e09", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToExponential(1.0, 6, &builder));
+ CHECK_EQ("1.000000e00", builder.Finalize());
}
builder.Reset();
CHECK(dc7.ToPrecision(-Double::NaN(), 1, &builder));
CHECK_EQ("NaN", builder.Finalize());
+
+ // Test NO_TRAILING_ZERO and its interaction with other flags.
+ flags = DoubleToStringConverter::NO_TRAILING_ZERO;
+ DoubleToStringConverter dc9(flags, "Infinity", "NaN", 'e', 0, 0, 6, 1);
+ flags = DoubleToStringConverter::NO_TRAILING_ZERO |
+ DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT;
+ DoubleToStringConverter dc10(flags, "Infinity", "NaN", 'e', 0, 0, 6, 1);
+ flags = DoubleToStringConverter::NO_TRAILING_ZERO |
+ DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |
+ DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT;
+ DoubleToStringConverter dc11(flags, "Infinity", "NaN", 'e', 0, 0, 6, 1);
+
+ builder.Reset();
+ CHECK(dc9.ToPrecision(230.001, 5, &builder));
+ CHECK_EQ("230", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc10.ToPrecision(230.001, 5, &builder));
+ CHECK_EQ("230.", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc11.ToPrecision(230.001, 5, &builder));
+ CHECK_EQ("230.0", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToPrecision(230.001, 5, &builder));
+ CHECK_EQ("230.00", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc9.ToPrecision(2300010, 5, &builder));
+ CHECK_EQ("2.3e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc10.ToPrecision(2300010, 5, &builder));
+ CHECK_EQ("2.3e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc11.ToPrecision(2300010, 5, &builder));
+ CHECK_EQ("2.3e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToPrecision(2300010, 5, &builder));
+ CHECK_EQ("2.3000e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc9.ToPrecision(0.02300010, 5, &builder));
+ CHECK_EQ("0.023", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc10.ToPrecision(0.02300010, 5, &builder));
+ CHECK_EQ("0.023", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc11.ToPrecision(0.02300010, 5, &builder));
+ CHECK_EQ("0.023", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToPrecision(0.02300010, 5, &builder));
+ CHECK_EQ("0.023000", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc9.ToPrecision(2000010, 5, &builder));
+ CHECK_EQ("2e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc10.ToPrecision(2000010, 5, &builder));
+ CHECK_EQ("2e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc11.ToPrecision(2000010, 5, &builder));
+ CHECK_EQ("2e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToPrecision(2000010, 5, &builder));
+ CHECK_EQ("2.0000e6", builder.Finalize());
+
+ // Test that rounding up still works with NO_TRAILING_ZERO
+ builder.Reset();
+ CHECK(dc9.ToPrecision(2000080, 5, &builder));
+ CHECK_EQ("2.0001e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc10.ToPrecision(2000080, 5, &builder));
+ CHECK_EQ("2.0001e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc11.ToPrecision(2000080, 5, &builder));
+ CHECK_EQ("2.0001e6", builder.Finalize());
+
+ builder.Reset();
+ CHECK(dc5.ToPrecision(2000080, 5, &builder));
+ CHECK_EQ("2.0001e6", builder.Finalize());
}
return Strtof(StringToVector(str), exponent);
}
+static float StrtofTrimmedChar(const char* str, int exponent) {
+ return StrtofTrimmed(StringToVector(str), exponent);
+}
+
TEST(Strtod) {
Vector<const char> vector;
}
+TEST(StrtofTrimmed) {
+ Vector<const char> vector;
+
+ vector = StringToVector("1");
+ CHECK_EQ(1.0f, StrtofTrimmed(vector, 0));
+ CHECK_EQ(10.0f, StrtofTrimmed(vector, 1));
+ CHECK_EQ(100.0f, StrtofTrimmed(vector, 2));
+ CHECK_EQ(1e20f, StrtofTrimmed(vector, 20));
+ CHECK_EQ(1e22f, StrtofTrimmed(vector, 22));
+ CHECK_EQ(1e23f, StrtofTrimmed(vector, 23));
+ CHECK_EQ(1e35f, StrtofTrimmed(vector, 35));
+ CHECK_EQ(1e36f, StrtofTrimmed(vector, 36));
+ CHECK_EQ(1e37f, StrtofTrimmed(vector, 37));
+ CHECK_EQ(1e-1f, StrtofTrimmed(vector, -1));
+ CHECK_EQ(1e-2f, StrtofTrimmed(vector, -2));
+ CHECK_EQ(1e-5f, StrtofTrimmed(vector, -5));
+ CHECK_EQ(1e-20f, StrtofTrimmed(vector, -20));
+ CHECK_EQ(1e-22f, StrtofTrimmed(vector, -22));
+ CHECK_EQ(1e-23f, StrtofTrimmed(vector, -23));
+ CHECK_EQ(1e-25f, StrtofTrimmed(vector, -25));
+ CHECK_EQ(1e-39f, StrtofTrimmed(vector, -39));
+
+ vector = StringToVector("2");
+ CHECK_EQ(2.0f, StrtofTrimmed(vector, 0));
+ CHECK_EQ(20.0f, StrtofTrimmed(vector, 1));
+ CHECK_EQ(200.0f, StrtofTrimmed(vector, 2));
+ CHECK_EQ(2e20f, StrtofTrimmed(vector, 20));
+ CHECK_EQ(2e22f, StrtofTrimmed(vector, 22));
+ CHECK_EQ(2e23f, StrtofTrimmed(vector, 23));
+ CHECK_EQ(2e35f, StrtofTrimmed(vector, 35));
+ CHECK_EQ(2e36f, StrtofTrimmed(vector, 36));
+ CHECK_EQ(2e37f, StrtofTrimmed(vector, 37));
+ CHECK_EQ(2e-1f, StrtofTrimmed(vector, -1));
+ CHECK_EQ(2e-2f, StrtofTrimmed(vector, -2));
+ CHECK_EQ(2e-5f, StrtofTrimmed(vector, -5));
+ CHECK_EQ(2e-20f, StrtofTrimmed(vector, -20));
+ CHECK_EQ(2e-22f, StrtofTrimmed(vector, -22));
+ CHECK_EQ(2e-23f, StrtofTrimmed(vector, -23));
+ CHECK_EQ(2e-25f, StrtofTrimmed(vector, -25));
+ CHECK_EQ(2e-39f, StrtofTrimmed(vector, -39));
+
+ vector = StringToVector("9");
+ CHECK_EQ(9.0f, StrtofTrimmed(vector, 0));
+ CHECK_EQ(90.0f, StrtofTrimmed(vector, 1));
+ CHECK_EQ(900.0f, StrtofTrimmed(vector, 2));
+ CHECK_EQ(9e20f, StrtofTrimmed(vector, 20));
+ CHECK_EQ(9e22f, StrtofTrimmed(vector, 22));
+ CHECK_EQ(9e23f, StrtofTrimmed(vector, 23));
+ CHECK_EQ(9e35f, StrtofTrimmed(vector, 35));
+ CHECK_EQ(9e36f, StrtofTrimmed(vector, 36));
+ CHECK_EQ(9e37f, StrtofTrimmed(vector, 37));
+ CHECK_EQ(9e-1f, StrtofTrimmed(vector, -1));
+ CHECK_EQ(9e-2f, StrtofTrimmed(vector, -2));
+ CHECK_EQ(9e-5f, StrtofTrimmed(vector, -5));
+ CHECK_EQ(9e-20f, StrtofTrimmed(vector, -20));
+ CHECK_EQ(9e-22f, StrtofTrimmed(vector, -22));
+ CHECK_EQ(9e-23f, StrtofTrimmed(vector, -23));
+ CHECK_EQ(9e-25f, StrtofTrimmed(vector, -25));
+ CHECK_EQ(9e-39f, StrtofTrimmed(vector, -39));
+
+ vector = StringToVector("12345");
+ CHECK_EQ(12345.0f, StrtofTrimmed(vector, 0));
+ CHECK_EQ(123450.0f, StrtofTrimmed(vector, 1));
+ CHECK_EQ(1234500.0f, StrtofTrimmed(vector, 2));
+ CHECK_EQ(12345e20f, StrtofTrimmed(vector, 20));
+ CHECK_EQ(12345e22f, StrtofTrimmed(vector, 22));
+ CHECK_EQ(12345e23f, StrtofTrimmed(vector, 23));
+ CHECK_EQ(12345e30f, StrtofTrimmed(vector, 30));
+ CHECK_EQ(12345e31f, StrtofTrimmed(vector, 31));
+ CHECK_EQ(12345e32f, StrtofTrimmed(vector, 32));
+ CHECK_EQ(12345e-1f, StrtofTrimmed(vector, -1));
+ CHECK_EQ(12345e-2f, StrtofTrimmed(vector, -2));
+ CHECK_EQ(12345e-5f, StrtofTrimmed(vector, -5));
+ CHECK_EQ(12345e-20f, StrtofTrimmed(vector, -20));
+ CHECK_EQ(12345e-22f, StrtofTrimmed(vector, -22));
+ CHECK_EQ(12345e-23f, StrtofTrimmed(vector, -23));
+ CHECK_EQ(12345e-25f, StrtofTrimmed(vector, -25));
+ CHECK_EQ(12345e-39f, StrtofTrimmed(vector, -39));
+
+ vector = StringToVector("12345678901234");
+ CHECK_EQ(12345678901234.0f, StrtofTrimmed(vector, 0));
+ CHECK_EQ(123456789012340.0f, StrtofTrimmed(vector, 1));
+ CHECK_EQ(1234567890123400.0f, StrtofTrimmed(vector, 2));
+ CHECK_EQ(12345678901234e20f, StrtofTrimmed(vector, 20));
+ CHECK_EQ(12345678901234e22f, StrtofTrimmed(vector, 22));
+ CHECK_EQ(12345678901234e23f, StrtofTrimmed(vector, 23));
+ CHECK_EQ(12345678901234e-1f, StrtofTrimmed(vector, -1));
+ CHECK_EQ(12345678901234e-2f, StrtofTrimmed(vector, -2));
+ CHECK_EQ(12345678901234e-5f, StrtofTrimmed(vector, -5));
+ CHECK_EQ(12345678901234e-20f, StrtofTrimmed(vector, -20));
+ CHECK_EQ(12345678901234e-22f, StrtofTrimmed(vector, -22));
+ CHECK_EQ(12345678901234e-23f, StrtofTrimmed(vector, -23));
+ CHECK_EQ(12345678901234e-25f, StrtofTrimmed(vector, -25));
+ CHECK_EQ(12345678901234e-39f, StrtofTrimmed(vector, -39));
+
+ vector = StringToVector("123456789012345");
+ CHECK_EQ(123456789012345.0f, StrtofTrimmed(vector, 0));
+ CHECK_EQ(1234567890123450.0f, StrtofTrimmed(vector, 1));
+ CHECK_EQ(12345678901234500.0f, StrtofTrimmed(vector, 2));
+ CHECK_EQ(123456789012345e20f, StrtofTrimmed(vector, 20));
+ CHECK_EQ(123456789012345e22f, StrtofTrimmed(vector, 22));
+ CHECK_EQ(123456789012345e23f, StrtofTrimmed(vector, 23));
+ CHECK_EQ(123456789012345e-1f, StrtofTrimmed(vector, -1));
+ CHECK_EQ(123456789012345e-2f, StrtofTrimmed(vector, -2));
+ CHECK_EQ(123456789012345e-5f, StrtofTrimmed(vector, -5));
+ CHECK_EQ(123456789012345e-20f, StrtofTrimmed(vector, -20));
+ CHECK_EQ(123456789012345e-22f, StrtofTrimmed(vector, -22));
+ CHECK_EQ(123456789012345e-23f, StrtofTrimmed(vector, -23));
+ CHECK_EQ(123456789012345e-25f, StrtofTrimmed(vector, -25));
+ CHECK_EQ(123456789012345e-39f, StrtofTrimmed(vector, -39));
+
+ CHECK_EQ(0.0f, StrtofTrimmedChar("", 1324));
+ CHECK_EQ(0.0f, StrtofTrimmedChar("2", -324));
+ CHECK_EQ(1e-45f, StrtofTrimmedChar("1", -45));
+ // It would be more readable to put non-zero literals on the left side (i.e.
+ // CHECK_EQ(1e-46, StrtofChar("1", -45))), but then Gcc complains that
+ // they are truncated to zero.
+ CHECK_EQ(0.0f, StrtofTrimmedChar("1", -46));
+ CHECK_EQ(0.0f, StrtofTrimmedChar("1", -47));
+ CHECK_EQ(1e-45f, StrtofTrimmedChar("1", -45));
+ CHECK_EQ(1e-45f, StrtofTrimmedChar("8", -46));
+
+ // It would be more readable to put the literals (and not Double::Infinity())
+ // on the left side (i.e. CHECK_EQ(3e38, StrtofChar("3", 38))), but then Gcc
+ // complains that the floating constant exceeds range of 'double'.
+ CHECK_EQ(Single::Infinity(), StrtofTrimmedChar("3", 39));
+ CHECK_EQ(3e38f, StrtofTrimmedChar("3", 38));
+ CHECK_EQ(3401e35f, StrtofTrimmedChar("3401", 35));
+ CHECK_EQ(3401e34f, StrtofTrimmedChar("3401", 34));
+ CHECK_EQ(34e37f, StrtofTrimmedChar("34", 37));
+ CHECK_EQ(3.4028234e+38f, StrtofTrimmedChar("34028235676", 28));
+ CHECK_EQ(3.4028234e+38f, StrtofTrimmedChar("34028235677", 28));
+ CHECK_EQ(Single::Infinity(), StrtofTrimmedChar("34028235678", 28));
+
+ // The following number is the result of 89255.0/1e-22. Both floating-point
+ // numbers can be accurately represented with doubles. However on Linux,x86
+ // the floating-point stack is set to 80bits and the double-rounding
+ // introduces an error.
+ CHECK_EQ(89255e-22f, StrtofTrimmedChar("89255", -22));
+
+ // Boundary cases. Boundaries themselves should round to even.
+ //
+ // 0x4f012334 = 2166567936
+ // next: 2166568192
+ // boundary: 2166568064 should round down.
+ CHECK_EQ(2166567936.0f, StrtofTrimmedChar("2166567936", 0));
+ CHECK_EQ(2166568192.0f, StrtofTrimmedChar("2166568192", 0));
+ CHECK_EQ(2166567936.0f, StrtofTrimmedChar("2166568064", 0));
+ CHECK_EQ(2166567936.0f, StrtofTrimmedChar("216656806399999", -5));
+ CHECK_EQ(2166568192.0f, StrtofTrimmedChar("216656806400001", -5));
+ // Verify that we don't double round.
+ // Get the boundary of the boundary.
+ CHECK_EQ(2.1665680640000002384185791015625e9, 2166568064.0);
+ // Visual Studio gets this wrong and believes that these two numbers are the
+ // same doubles. We want to test our conversion and not the compiler. We
+ // therefore disable the check.
+#ifndef _MSC_VER
+ CHECK(2.16656806400000023841857910156251e9 != 2166568064.0);
+#endif
+ CHECK_EQ(2166568192.0f, StrtofTrimmedChar("21665680640000002384185791015625", -22));
+
+ // 0x4fffffff = 8589934080
+ // next: 8589934592
+ // boundary: 8589934336 should round up.
+ CHECK_EQ(8589934592.0f, StrtofTrimmedChar("8589934592", 0));
+ CHECK_EQ(8589934592.0f, StrtofTrimmedChar("8589934336", 0));
+ CHECK_EQ(8589934080.0f, StrtofTrimmedChar("858993433599999", -5));
+ CHECK_EQ(8589934592.0f, StrtofTrimmedChar("858993433600001", -5));
+ // Verify that we don't double round.
+ // Get the boundary of the boundary.
+ // Visual Studio gets this wrong. To avoid failing tests because of a broken
+ // compiler we disable the following two tests. They were only testing the
+ // compiler. The real test is still active.
+#ifndef _MSC_VER
+ CHECK_EQ(8.589934335999999523162841796875e+09, 8589934336.0);
+ CHECK(8.5899343359999995231628417968749e+09 != 8589934336.0);
+#endif
+ CHECK_EQ(8589934080.0f, StrtofTrimmedChar("8589934335999999523162841796875", -21));
+
+ // 0x4f000000 = 2147483648
+ // next: 2147483904
+ // boundary: 2147483776 should round down.
+ CHECK_EQ(2147483648.0f, StrtofTrimmedChar("2147483648", 0));
+ CHECK_EQ(2147483904.0f, StrtofTrimmedChar("2147483904", 0));
+ CHECK_EQ(2147483648.0f, StrtofTrimmedChar("2147483776", 0));
+ CHECK_EQ(2147483648.0f, StrtofTrimmedChar("214748377599999", -5));
+ CHECK_EQ(2147483904.0f, StrtofTrimmedChar("214748377600001", -5));
+}
static int CompareBignumToDiyFp(const Bignum& bignum_digits,
int bignum_exponent,