mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 15:42:14 +00:00
ICU-21581 Update double-conversion
This commit is contained in:
parent
4a8b16056f
commit
6115e58966
15 changed files with 203 additions and 15 deletions
|
@ -579,7 +579,7 @@ static bool Grisu3(double v,
|
|||
// the difference between w and boundary_minus/plus (a power of 2) and to
|
||||
// compute scaled_boundary_minus/plus by subtracting/adding from
|
||||
// scaled_w. However the code becomes much less readable and the speed
|
||||
// enhancements are not terriffic.
|
||||
// enhancements are not terrific.
|
||||
DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);
|
||||
DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk);
|
||||
|
||||
|
@ -587,7 +587,7 @@ static bool Grisu3(double v,
|
|||
// v == (double) (scaled_w * 10^-mk).
|
||||
// Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
|
||||
// integer than it will be updated. For instance if scaled_w == 1.23 then
|
||||
// the buffer will be filled with "123" und the decimal_exponent will be
|
||||
// the buffer will be filled with "123" and the decimal_exponent will be
|
||||
// decreased by 2.
|
||||
int kappa;
|
||||
bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,
|
||||
|
|
|
@ -800,6 +800,42 @@ float StringToDoubleConverter::StringToFloat(
|
|||
processed_characters_count));
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
double StringToDoubleConverter::StringTo<double>(
|
||||
const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToDouble(buffer, length, processed_characters_count);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
float StringToDoubleConverter::StringTo<float>(
|
||||
const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToFloat(buffer, length, processed_characters_count);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
double StringToDoubleConverter::StringTo<double>(
|
||||
const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToDouble(buffer, length, processed_characters_count);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
float StringToDoubleConverter::StringTo<float>(
|
||||
const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToFloat(buffer, length, processed_characters_count);
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
// ICU PATCH: Close ICU namespace
|
||||
|
|
|
@ -100,7 +100,7 @@ class StringToDoubleConverter {
|
|||
// This *must* start with "0x" and separate the exponent with "p".
|
||||
// Examples: 0x1.2p3 == 9.0
|
||||
// 0x10.1p0 == 16.0625
|
||||
// ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
|
||||
// ALLOW_HEX and ALLOW_HEX_FLOATS are indented.
|
||||
//
|
||||
// empty_string_value is returned when an empty string is given as input.
|
||||
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
|
||||
|
@ -218,6 +218,18 @@ class StringToDoubleConverter {
|
|||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
// Same as StringToDouble for T = double, and StringToFloat for T = float.
|
||||
template <typename T>
|
||||
T StringTo(const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
// Same as StringTo above but for 16 bit characters.
|
||||
template <typename T>
|
||||
T StringTo(const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
const double empty_string_value_;
|
||||
|
|
|
@ -118,6 +118,7 @@ int main(int argc, char** argv) {
|
|||
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
|
||||
defined(__hppa__) || defined(__ia64__) || \
|
||||
defined(__mips__) || \
|
||||
defined(__loongarch__) || \
|
||||
defined(__nios2__) || defined(__ghs) || \
|
||||
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
|
||||
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
if [[ -z $1 ]]; then
|
||||
echo "Pass the current version tag of double-conversion as the first argument to this script";
|
||||
echo "To pull the latest changes, use 'main'"
|
||||
echo "To pull the latest changes, use 'master'"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
|
|
6
vendor/double-conversion/upstream/Changelog
vendored
6
vendor/double-conversion/upstream/Changelog
vendored
|
@ -1,3 +1,7 @@
|
|||
2021-05-19:
|
||||
Loongarch is a RISC-style command system architecture.
|
||||
Add support for loongarch architecture.
|
||||
|
||||
2020-02-16:
|
||||
Add support for quiet and signaling NaNs to ieee header.
|
||||
|
||||
|
@ -10,7 +14,7 @@
|
|||
the necessary line.
|
||||
|
||||
2019-09-02:
|
||||
Add support for e2k architectur. Thanks to Michael Shigorin.
|
||||
Add support for e2k architecture. Thanks to Michael Shigorin.
|
||||
|
||||
2019-08-01:
|
||||
Add min exponent width option in double-to-string conversion.
|
||||
|
|
|
@ -276,7 +276,7 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
|||
|
||||
// Let v = numerator / denominator < 10.
|
||||
// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
|
||||
// from left to right. Once 'count' digits have been produced we decide wether
|
||||
// from left to right. Once 'count' digits have been produced we decide whether
|
||||
// to round up or down. Remainders of exactly .5 round upwards. Numbers such
|
||||
// as 9.999999 propagate a carry all the way, and change the
|
||||
// exponent (decimal_point), when rounding upwards.
|
||||
|
|
|
@ -123,7 +123,7 @@ class DoubleToStringConverter {
|
|||
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
|
||||
// ToPrecision(0.0000012345, 2) -> "0.0000012"
|
||||
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
|
||||
// Similarily the converter may add up to
|
||||
// Similarly the converter may add up to
|
||||
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
|
||||
// returning an exponential representation. A zero added by the
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
|
||||
|
@ -181,7 +181,7 @@ class DoubleToStringConverter {
|
|||
// Example with decimal_in_shortest_low = -6,
|
||||
// decimal_in_shortest_high = 21,
|
||||
// EMIT_POSITIVE_EXPONENT_SIGN activated, and
|
||||
// EMIT_TRAILING_DECIMAL_POINT deactived:
|
||||
// EMIT_TRAILING_DECIMAL_POINT deactivated:
|
||||
// ToShortest(0.000001) -> "0.000001"
|
||||
// ToShortest(0.0000001) -> "1e-7"
|
||||
// ToShortest(111111111111111111111.0) -> "111111111111111110000"
|
||||
|
@ -305,7 +305,7 @@ class DoubleToStringConverter {
|
|||
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
|
||||
// ToPrecision(0.0000012345, 2) -> "0.0000012"
|
||||
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
|
||||
// Similarily the converter may add up to
|
||||
// Similarly the converter may add up to
|
||||
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
|
||||
// returning an exponential representation. A zero added by the
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
|
||||
|
|
|
@ -565,7 +565,7 @@ static bool Grisu3(double v,
|
|||
// the difference between w and boundary_minus/plus (a power of 2) and to
|
||||
// compute scaled_boundary_minus/plus by subtracting/adding from
|
||||
// scaled_w. However the code becomes much less readable and the speed
|
||||
// enhancements are not terriffic.
|
||||
// enhancements are not terrific.
|
||||
DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);
|
||||
DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk);
|
||||
|
||||
|
@ -573,7 +573,7 @@ static bool Grisu3(double v,
|
|||
// v == (double) (scaled_w * 10^-mk).
|
||||
// Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
|
||||
// integer than it will be updated. For instance if scaled_w == 1.23 then
|
||||
// the buffer will be filled with "123" und the decimal_exponent will be
|
||||
// the buffer will be filled with "123" and the decimal_exponent will be
|
||||
// decreased by 2.
|
||||
int kappa;
|
||||
bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,
|
||||
|
|
|
@ -395,8 +395,8 @@ bool FastFixedDtoa(double v,
|
|||
TrimZeros(buffer, length, decimal_point);
|
||||
buffer[*length] = '\0';
|
||||
if ((*length) == 0) {
|
||||
// The string is empty and the decimal_point thus has no importance. Mimick
|
||||
// Gay's dtoa and and set it to -fractional_count.
|
||||
// The string is empty and the decimal_point thus has no importance. Mimic
|
||||
// Gay's dtoa and set it to -fractional_count.
|
||||
*decimal_point = -fractional_count;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -779,4 +779,40 @@ float StringToDoubleConverter::StringToFloat(
|
|||
processed_characters_count));
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
double StringToDoubleConverter::StringTo<double>(
|
||||
const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToDouble(buffer, length, processed_characters_count);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
float StringToDoubleConverter::StringTo<float>(
|
||||
const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToFloat(buffer, length, processed_characters_count);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
double StringToDoubleConverter::StringTo<double>(
|
||||
const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToDouble(buffer, length, processed_characters_count);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
float StringToDoubleConverter::StringTo<float>(
|
||||
const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToFloat(buffer, length, processed_characters_count);
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
|
|
|
@ -86,7 +86,7 @@ class StringToDoubleConverter {
|
|||
// This *must* start with "0x" and separate the exponent with "p".
|
||||
// Examples: 0x1.2p3 == 9.0
|
||||
// 0x10.1p0 == 16.0625
|
||||
// ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
|
||||
// ALLOW_HEX and ALLOW_HEX_FLOATS are indented.
|
||||
//
|
||||
// empty_string_value is returned when an empty string is given as input.
|
||||
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
|
||||
|
@ -204,6 +204,18 @@ class StringToDoubleConverter {
|
|||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
// Same as StringToDouble for T = double, and StringToFloat for T = float.
|
||||
template <typename T>
|
||||
T StringTo(const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
// Same as StringTo above but for 16 bit characters.
|
||||
template <typename T>
|
||||
T StringTo(const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
const double empty_string_value_;
|
||||
|
|
|
@ -550,7 +550,7 @@ float StrtofTrimmed(Vector<const char> trimmed, int exponent) {
|
|||
// low-precision (3 digits):
|
||||
// when read from input: 123
|
||||
// when rounded from high precision: 124.
|
||||
// To do this we simply look at the neigbors of the correct result and see
|
||||
// To do this we simply look at the neighbors of the correct result and see
|
||||
// if they would round to the same float. If the guess is not correct we have
|
||||
// to look at four values (since two different doubles could be the correct
|
||||
// double).
|
||||
|
|
|
@ -108,6 +108,7 @@ int main(int argc, char** argv) {
|
|||
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
|
||||
defined(__hppa__) || defined(__ia64__) || \
|
||||
defined(__mips__) || \
|
||||
defined(__loongarch__) || \
|
||||
defined(__nios2__) || defined(__ghs) || \
|
||||
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
|
||||
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
|
||||
|
|
|
@ -5889,3 +5889,89 @@ TEST(StringToDoubleCaseInsensitiveSpecialValues) {
|
|||
CHECK_EQ(1.0, converter.StringToDouble("+inf", 4, &processed));
|
||||
CHECK_EQ(0, processed);
|
||||
}
|
||||
|
||||
|
||||
TEST(StringToTemplate) {
|
||||
// Test StringToDoubleConverter::StringTo<T>.
|
||||
|
||||
const StringToDoubleConverter converter(StringToDoubleConverter::ALLOW_HEX, 0.0, Double::NaN(), "inf", "nan");
|
||||
|
||||
// First simply check conversion from "0" and "1":
|
||||
for (int i = 0; i <= 1; ++i)
|
||||
{
|
||||
const char c = '0' + i;
|
||||
|
||||
int processed = 0;
|
||||
CHECK_EQ(static_cast<double>(i), converter.StringTo<double>(&c, 1, &processed));
|
||||
CHECK_EQ(1, processed);
|
||||
|
||||
processed = 0;
|
||||
CHECK_EQ(static_cast<float>(i), converter.StringTo<float>(&c, 1, &processed));
|
||||
CHECK_EQ(1, processed);
|
||||
|
||||
const uc16 buffer16[1] = { static_cast<uc16>(c) };
|
||||
|
||||
processed = 0;
|
||||
CHECK_EQ(static_cast<double>(i), converter.StringTo<double>(buffer16, 1, &processed));
|
||||
CHECK_EQ(1, processed);
|
||||
|
||||
processed = 0;
|
||||
CHECK_EQ(static_cast<float>(i), converter.StringTo<float>(buffer16, 1, &processed));
|
||||
CHECK_EQ(1, processed);
|
||||
}
|
||||
{
|
||||
// A number that can be represented by a double, but not by a float.
|
||||
// Allows testing that StringTo<double> behaves like StringToDouble
|
||||
// (and not like StringToFloat).
|
||||
const char buffer[] = "1e+100";
|
||||
const int length = DOUBLE_CONVERSION_ARRAY_SIZE(buffer) - 1;
|
||||
|
||||
int processed1 = 1;
|
||||
int processed2 = 2;
|
||||
|
||||
CHECK_EQ(converter.StringToDouble(buffer, length, &processed1),
|
||||
converter.StringTo<double>(buffer, length, &processed2));
|
||||
CHECK_EQ(processed1, processed2);
|
||||
|
||||
uc16 buffer16[DOUBLE_CONVERSION_ARRAY_SIZE(buffer)];
|
||||
|
||||
for (int i = 0; i <= length; ++i) {
|
||||
buffer16[i] = buffer[i];
|
||||
}
|
||||
|
||||
processed1 = 1;
|
||||
processed2 = 2;
|
||||
|
||||
CHECK_EQ(converter.StringToDouble(buffer16, length, &processed1),
|
||||
converter.StringTo<double>(buffer16, length, &processed2));
|
||||
CHECK_EQ(processed1, processed2);
|
||||
}
|
||||
{
|
||||
// The double rounding example from TEST(StringToFloatHexString), which
|
||||
// yields a slightly different result from StringToFloat than from
|
||||
// StringToDouble. Allows testing that StringTo<float> behaves like
|
||||
// StringToFloat (rather than like StringToDouble).
|
||||
const char buffer[] = "0x100000100000008";
|
||||
const int length = DOUBLE_CONVERSION_ARRAY_SIZE(buffer) - 1;
|
||||
|
||||
int processed1 = 1;
|
||||
int processed2 = 2;
|
||||
|
||||
CHECK_EQ(converter.StringToFloat(buffer, length, &processed1),
|
||||
converter.StringTo<float>(buffer, length, &processed2));
|
||||
CHECK_EQ(processed1, processed2);
|
||||
|
||||
uc16 buffer16[DOUBLE_CONVERSION_ARRAY_SIZE(buffer)];
|
||||
|
||||
for (int i = 0; i <= length; ++i) {
|
||||
buffer16[i] = buffer[i];
|
||||
}
|
||||
|
||||
processed1 = 1;
|
||||
processed2 = 2;
|
||||
|
||||
CHECK_EQ(converter.StringToFloat(buffer16, length, &processed1),
|
||||
converter.StringTo<float>(buffer16, length, &processed2));
|
||||
CHECK_EQ(processed1, processed2);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue