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.
|
||||
//
|
||||
//
|
||||
// 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
|
||||
@ -7,9 +7,9 @@
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// 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
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// 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
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
||||
@ -56,7 +56,7 @@ struct DiyFp {
|
||||
if (biased_e != 0) {
|
||||
f = significand + kDpHiddenBit;
|
||||
e = biased_e - kDpExponentBias;
|
||||
}
|
||||
}
|
||||
else {
|
||||
f = significand;
|
||||
e = kDpMinExponent + 1;
|
||||
@ -142,9 +142,12 @@ struct DiyFp {
|
||||
uint64_t u64;
|
||||
}u;
|
||||
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
||||
RAPIDJSON_ASSERT(e >= kDpDenormalExponent);
|
||||
if (e < kDpDenormalExponent) {
|
||||
// Underflow.
|
||||
return 0.0;
|
||||
}
|
||||
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);
|
||||
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||
return u.d;
|
||||
@ -226,7 +229,7 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||
RAPIDJSON_ASSERT(index < 87);
|
||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||
}
|
||||
|
||||
|
||||
inline DiyFp GetCachedPower(int e, int* K) {
|
||||
|
||||
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
||||
|
@ -392,6 +392,15 @@ static void TestParseDouble() {
|
||||
"83723677529752585477247372368372368547354737253685475529752",
|
||||
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
|
||||
}
|
||||
|
||||
@ -1346,20 +1355,20 @@ TEST(Reader, IterativePullParsing_General) {
|
||||
handler.LOG_DOUBLE,
|
||||
handler.LOG_ENDARRAY | 7
|
||||
};
|
||||
|
||||
|
||||
StringStream is("[1, {\"k\": [1, 2]}, null, false, true, \"string\", 1.2]");
|
||||
Reader reader;
|
||||
|
||||
|
||||
reader.IterativeParseInit();
|
||||
while (!reader.IterativeParseComplete()) {
|
||||
size_t oldLogCount = handler.LogCount;
|
||||
EXPECT_TRUE(oldLogCount < sizeof(e) / sizeof(int)) << "overrun";
|
||||
|
||||
|
||||
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(e[oldLogCount], handler.Logs[oldLogCount]) << "wrong event returned";
|
||||
}
|
||||
|
||||
|
||||
EXPECT_FALSE(reader.HasParseError());
|
||||
EXPECT_EQ(sizeof(e) / sizeof(int), handler.LogCount) << "handler invoked wrong number of times";
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user