19 #ifndef RAPIDJSON_DIYFP_H_ 20 #define RAPIDJSON_DIYFP_H_ 22 #include "../rapidjson.h" 24 #if defined(_MSC_VER) && defined(_M_AMD64) 26 #pragma intrinsic(_BitScanReverse64) 29 RAPIDJSON_NAMESPACE_BEGIN
34 RAPIDJSON_DIAG_OFF(effc++)
40 DiyFp(uint64_t fp,
int exp) : f(fp), e(exp) {}
42 explicit DiyFp(
double d) {
48 int biased_e =
static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
49 uint64_t significand = (u.u64 & kDpSignificandMask);
51 f = significand + kDpHiddenBit;
52 e = biased_e - kDpExponentBias;
56 e = kDpMinExponent + 1;
60 DiyFp operator-(
const DiyFp& rhs)
const {
61 return DiyFp(f - rhs.f, e);
64 DiyFp operator*(
const DiyFp& rhs)
const {
65 #if defined(_MSC_VER) && defined(_M_AMD64) 67 uint64_t l = _umul128(f, rhs.f, &h);
68 if (l & (uint64_t(1) << 63))
70 return DiyFp(h, e + rhs.e + 64);
71 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) 72 __extension__
typedef unsigned __int128 uint128;
73 uint128 p =
static_cast<uint128
>(f) * static_cast<uint128>(rhs.f);
74 uint64_t h =
static_cast<uint64_t
>(p >> 64);
75 uint64_t l =
static_cast<uint64_t
>(p);
76 if (l & (uint64_t(1) << 63))
78 return DiyFp(h, e + rhs.e + 64);
80 const uint64_t M32 = 0xFFFFFFFF;
81 const uint64_t a = f >> 32;
82 const uint64_t b = f & M32;
83 const uint64_t c = rhs.f >> 32;
84 const uint64_t d = rhs.f & M32;
85 const uint64_t ac = a * c;
86 const uint64_t bc = b * c;
87 const uint64_t ad = a * d;
88 const uint64_t bd = b * d;
89 uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
91 return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
95 DiyFp Normalize()
const {
96 #if defined(_MSC_VER) && defined(_M_AMD64) 98 _BitScanReverse64(&index, f);
99 return DiyFp(f << (63 - index), e - (63 - index));
100 #elif defined(__GNUC__) && __GNUC__ >= 4 101 int s = __builtin_clzll(f);
102 return DiyFp(f << s, e - s);
105 while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
113 DiyFp NormalizeBoundary()
const {
115 while (!(res.f & (kDpHiddenBit << 1))) {
119 res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
120 res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
124 void NormalizedBoundaries(DiyFp* minus, DiyFp* plus)
const {
125 DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
126 DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
127 mi.f <<= mi.e - pl.e;
133 double ToDouble()
const {
138 const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
139 static_cast<uint64_t
>(e + kDpExponentBias);
140 u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
144 static const int kDiySignificandSize = 64;
145 static const int kDpSignificandSize = 52;
146 static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
147 static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
148 static const int kDpMinExponent = -kDpExponentBias;
149 static const int kDpDenormalExponent = -kDpExponentBias + 1;
158 inline DiyFp GetCachedPowerByIndex(
size_t index) {
160 static const uint64_t kCachedPowers_F[] = {
206 static const int16_t kCachedPowers_E[] = {
207 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
208 -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
209 -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
210 -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
211 -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
212 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
213 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
214 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
215 907, 933, 960, 986, 1013, 1039, 1066
217 return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
220 inline DiyFp GetCachedPower(
int e,
int* K) {
223 double dk = (-61 - e) * 0.30102999566398114 + 347;
224 int k =
static_cast<int>(dk);
228 unsigned index =
static_cast<unsigned>((k >> 3) + 1);
229 *K = -(-348 +
static_cast<int>(index << 3));
231 return GetCachedPowerByIndex(index);
234 inline DiyFp GetCachedPower10(
int exp,
int *outExp) {
235 unsigned index = (exp + 348) / 8;
236 *outExp = -348 + index * 8;
237 return GetCachedPowerByIndex(index);
245 RAPIDJSON_NAMESPACE_END
247 #endif // RAPIDJSON_DIYFP_H_ #define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:261