Return 0 if binary exponent is too small
This commit is contained in:
parent
f5e5d47fac
commit
4e9b4f6d6a
@ -1,5 +1,5 @@
|
|||||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// http://opensource.org/licenses/MIT
|
// http://opensource.org/licenses/MIT
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software distributed
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// specific language governing permissions and limitations under the License.
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
||||||
@ -56,7 +56,7 @@ struct DiyFp {
|
|||||||
if (biased_e != 0) {
|
if (biased_e != 0) {
|
||||||
f = significand + kDpHiddenBit;
|
f = significand + kDpHiddenBit;
|
||||||
e = biased_e - kDpExponentBias;
|
e = biased_e - kDpExponentBias;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
f = significand;
|
f = significand;
|
||||||
e = kDpMinExponent + 1;
|
e = kDpMinExponent + 1;
|
||||||
@ -142,9 +142,12 @@ struct DiyFp {
|
|||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
}u;
|
}u;
|
||||||
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
||||||
RAPIDJSON_ASSERT(e >= kDpDenormalExponent);
|
if (e < kDpDenormalExponent) {
|
||||||
|
// Underflow.
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
RAPIDJSON_ASSERT(e < kDpMaxExponent);
|
RAPIDJSON_ASSERT(e < kDpMaxExponent);
|
||||||
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||||
static_cast<uint64_t>(e + kDpExponentBias);
|
static_cast<uint64_t>(e + kDpExponentBias);
|
||||||
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||||
return u.d;
|
return u.d;
|
||||||
@ -226,7 +229,7 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
|
|||||||
RAPIDJSON_ASSERT(index < 87);
|
RAPIDJSON_ASSERT(index < 87);
|
||||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DiyFp GetCachedPower(int e, int* K) {
|
inline DiyFp GetCachedPower(int e, int* K) {
|
||||||
|
|
||||||
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
||||||
|
@ -392,6 +392,15 @@ static void TestParseDouble() {
|
|||||||
"83723677529752585477247372368372368547354737253685475529752",
|
"83723677529752585477247372368372368547354737253685475529752",
|
||||||
6223372036854775808.0);
|
6223372036854775808.0);
|
||||||
|
|
||||||
|
|
||||||
|
TEST_DOUBLE(fullPrecision, "1e-325", 0.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "1e-324", 0.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "2e-324", 0.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "2.4703282292062327e-324", 0.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "2.4703282292062328e-324", 2.4703282292062328e-324);
|
||||||
|
TEST_DOUBLE(fullPrecision, "2.48e-324", 2.48e-324);
|
||||||
|
TEST_DOUBLE(fullPrecision, "2.5e-324", 2.5e-324);
|
||||||
|
|
||||||
#undef TEST_DOUBLE
|
#undef TEST_DOUBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,20 +1355,20 @@ TEST(Reader, IterativePullParsing_General) {
|
|||||||
handler.LOG_DOUBLE,
|
handler.LOG_DOUBLE,
|
||||||
handler.LOG_ENDARRAY | 7
|
handler.LOG_ENDARRAY | 7
|
||||||
};
|
};
|
||||||
|
|
||||||
StringStream is("[1, {\"k\": [1, 2]}, null, false, true, \"string\", 1.2]");
|
StringStream is("[1, {\"k\": [1, 2]}, null, false, true, \"string\", 1.2]");
|
||||||
Reader reader;
|
Reader reader;
|
||||||
|
|
||||||
reader.IterativeParseInit();
|
reader.IterativeParseInit();
|
||||||
while (!reader.IterativeParseComplete()) {
|
while (!reader.IterativeParseComplete()) {
|
||||||
size_t oldLogCount = handler.LogCount;
|
size_t oldLogCount = handler.LogCount;
|
||||||
EXPECT_TRUE(oldLogCount < sizeof(e) / sizeof(int)) << "overrun";
|
EXPECT_TRUE(oldLogCount < sizeof(e) / sizeof(int)) << "overrun";
|
||||||
|
|
||||||
EXPECT_TRUE(reader.IterativeParseNext<kParseDefaultFlags>(is, handler)) << "parse fail";
|
EXPECT_TRUE(reader.IterativeParseNext<kParseDefaultFlags>(is, handler)) << "parse fail";
|
||||||
EXPECT_EQ(handler.LogCount, oldLogCount + 1) << "handler should be invoked exactly once each time";
|
EXPECT_EQ(handler.LogCount, oldLogCount + 1) << "handler should be invoked exactly once each time";
|
||||||
EXPECT_EQ(e[oldLogCount], handler.Logs[oldLogCount]) << "wrong event returned";
|
EXPECT_EQ(e[oldLogCount], handler.Logs[oldLogCount]) << "wrong event returned";
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_FALSE(reader.HasParseError());
|
EXPECT_FALSE(reader.HasParseError());
|
||||||
EXPECT_EQ(sizeof(e) / sizeof(int), handler.LogCount) << "handler invoked wrong number of times";
|
EXPECT_EQ(sizeof(e) / sizeof(int), handler.LogCount) << "handler invoked wrong number of times";
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user