parent
f8b3c65d7d
commit
add5a50581
@ -191,8 +191,13 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
|||||||
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
|
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
|
||||||
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
|
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
|
||||||
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
|
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
|
||||||
if (precisionBits >= halfWay + error)
|
if (precisionBits >= halfWay + error) {
|
||||||
rounded.f++;
|
rounded.f++;
|
||||||
|
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
|
||||||
|
rounded.f >>= 1;
|
||||||
|
rounded.e++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*result = rounded.ToDouble();
|
*result = rounded.ToDouble();
|
||||||
|
|
||||||
|
@ -327,15 +327,44 @@ static void TestParseDouble() {
|
|||||||
if (fullPrecision) {
|
if (fullPrecision) {
|
||||||
EXPECT_EQ(d.Uint64Value(), a.Uint64Value());
|
EXPECT_EQ(d.Uint64Value(), a.Uint64Value());
|
||||||
if (d.Uint64Value() != a.Uint64Value())
|
if (d.Uint64Value() != a.Uint64Value())
|
||||||
printf(" String: %sn Actual: %.17gnExpected: %.17gn", buffer, h.actual_, d.Value());
|
printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
EXPECT_EQ(d.Sign(), a.Sign()); /* for 0.0 != -0.0 */
|
EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0
|
||||||
EXPECT_DOUBLE_EQ(d.Value(), h.actual_);
|
EXPECT_DOUBLE_EQ(d.Value(), h.actual_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #340
|
||||||
|
TEST_DOUBLE(fullPrecision, "7.450580596923828e-9", 7.450580596923828e-9);
|
||||||
|
{
|
||||||
|
internal::Double d(1.0);
|
||||||
|
for (int i = 0; i < 324; i++) {
|
||||||
|
char buffer[32];
|
||||||
|
*internal::dtoa(d.Value(), buffer) = '\0';
|
||||||
|
|
||||||
|
StringStream s(buffer);
|
||||||
|
ParseDoubleHandler h;
|
||||||
|
Reader reader;
|
||||||
|
ASSERT_EQ(kParseErrorNone, reader.Parse<fullPrecision ? kParseFullPrecisionFlag : 0>(s, h).Code());
|
||||||
|
EXPECT_EQ(1u, h.step_);
|
||||||
|
internal::Double a(h.actual_);
|
||||||
|
if (fullPrecision) {
|
||||||
|
EXPECT_EQ(d.Uint64Value(), a.Uint64Value());
|
||||||
|
if (d.Uint64Value() != a.Uint64Value())
|
||||||
|
printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0
|
||||||
|
EXPECT_DOUBLE_EQ(d.Value(), h.actual_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
d = d.Value() * 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
#undef TEST_DOUBLE
|
#undef TEST_DOUBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user