strtodtest.cpp
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #include "unittest.h"
16 
18 
19 #ifdef __clang__
20 RAPIDJSON_DIAG_PUSH
21 RAPIDJSON_DIAG_OFF(unreachable-code)
22 #endif
23 
24 #define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1)
25 
26 using namespace rapidjson::internal;
27 
28 TEST(Strtod, CheckApproximationCase) {
29  static const int kSignificandSize = 52;
30  static const int kExponentBias = 0x3FF;
31  static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
32  static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
33  static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
34 
35  // http://www.exploringbinary.com/using-integers-to-check-a-floating-point-approximation/
36  // Let b = 0x1.465a72e467d88p-149
37  // = 5741268244528520 x 2^-201
38  union {
39  double d;
40  uint64_t u;
41  }u;
42  u.u = 0x465a72e467d88 | ((static_cast<uint64_t>(-149 + kExponentBias)) << kSignificandSize);
43  const double b = u.d;
44  const uint64_t bInt = (u.u & kSignificandMask) | kHiddenBit;
45  const int bExp = static_cast<int>(((u.u & kExponentMask) >> kSignificandSize) - kExponentBias - kSignificandSize);
46  EXPECT_DOUBLE_EQ(1.7864e-45, b);
47  EXPECT_EQ(RAPIDJSON_UINT64_C2(0x001465a7, 0x2e467d88), bInt);
48  EXPECT_EQ(-201, bExp);
49 
50  // Let d = 17864 x 10-49
51  const char dInt[] = "17864";
52  const int dExp = -49;
53 
54  // Let h = 2^(bExp-1)
55  const int hExp = bExp - 1;
56  EXPECT_EQ(-202, hExp);
57 
58  int dS_Exp2 = 0;
59  int dS_Exp5 = 0;
60  int bS_Exp2 = 0;
61  int bS_Exp5 = 0;
62  int hS_Exp2 = 0;
63  int hS_Exp5 = 0;
64 
65  // Adjust for decimal exponent
66  if (dExp >= 0) {
67  dS_Exp2 += dExp;
68  dS_Exp5 += dExp;
69  }
70  else {
71  bS_Exp2 -= dExp;
72  bS_Exp5 -= dExp;
73  hS_Exp2 -= dExp;
74  hS_Exp5 -= dExp;
75  }
76 
77  // Adjust for binary exponent
78  if (bExp >= 0)
79  bS_Exp2 += bExp;
80  else {
81  dS_Exp2 -= bExp;
82  hS_Exp2 -= bExp;
83  }
84 
85  // Adjust for half ulp exponent
86  if (hExp >= 0)
87  hS_Exp2 += hExp;
88  else {
89  dS_Exp2 -= hExp;
90  bS_Exp2 -= hExp;
91  }
92 
93  // Remove common power of two factor from all three scaled values
94  int common_Exp2 = std::min(dS_Exp2, std::min(bS_Exp2, hS_Exp2));
95  dS_Exp2 -= common_Exp2;
96  bS_Exp2 -= common_Exp2;
97  hS_Exp2 -= common_Exp2;
98 
99  EXPECT_EQ(153, dS_Exp2);
100  EXPECT_EQ(0, dS_Exp5);
101  EXPECT_EQ(1, bS_Exp2);
102  EXPECT_EQ(49, bS_Exp5);
103  EXPECT_EQ(0, hS_Exp2);
104  EXPECT_EQ(49, hS_Exp5);
105 
106  BigInteger dS = BIGINTEGER_LITERAL(dInt);
107  dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<size_t>(dS_Exp2);
108 
109  BigInteger bS(bInt);
110  bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<size_t>(bS_Exp2);
111 
112  BigInteger hS(1);
113  hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<size_t>(hS_Exp2);
114 
115  EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994138521801764465966248930731085529088") == dS);
116  EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994122305215569213032722473144531250000") == bS);
117  EXPECT_TRUE(BIGINTEGER_LITERAL("17763568394002504646778106689453125") == hS);
118 
119  EXPECT_EQ(1, dS.Compare(bS));
120 
121  BigInteger delta(0);
122  EXPECT_FALSE(dS.Difference(bS, &delta));
123  EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta);
124  EXPECT_TRUE(bS.Difference(dS, &delta));
125  EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta);
126 
127  EXPECT_EQ(-1, delta.Compare(hS));
128 }
129 
130 #ifdef __clang__
131 RAPIDJSON_DIAG_POP
132 #endif
d
#define BIGINTEGER_LITERAL(s)
Definition: strtodtest.cpp:24
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:294
unsigned __int64 uint64_t
Definition: stdint.h:136
TEST(Strtod, CheckApproximationCase)
Definition: strtodtest.cpp:28


choreo_rapidjson
Author(s):
autogenerated on Thu Jul 18 2019 03:59:09