19 #ifndef RAPIDJSON_DIYFP_H_
20 #define RAPIDJSON_DIYFP_H_
22 #include "../rapidjson.h"
26 #if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
28 #pragma intrinsic(_umul128)
31 RAPIDJSON_NAMESPACE_BEGIN
36 RAPIDJSON_DIAG_OFF(effc++)
41 RAPIDJSON_DIAG_OFF(padded)
47 DiyFp(uint64_t fp,
int exp) : f(fp), e(exp) {}
49 explicit DiyFp(
double d) {
55 int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
56 uint64_t significand = (u.u64 & kDpSignificandMask);
58 f = significand + kDpHiddenBit;
59 e = biased_e - kDpExponentBias;
63 e = kDpMinExponent + 1;
67 DiyFp operator-(
const DiyFp& rhs)
const {
68 return DiyFp(f - rhs.f, e);
71 DiyFp operator*(
const DiyFp& rhs)
const {
72 #if defined(_MSC_VER) && defined(_M_AMD64)
74 uint64_t l = _umul128(f, rhs.f, &h);
75 if (l & (uint64_t(1) << 63))
77 return DiyFp(h, e + rhs.e + 64);
78 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
79 __extension__
typedef unsigned __int128 uint128;
80 uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
81 uint64_t h = static_cast<uint64_t>(p >> 64);
82 uint64_t l = static_cast<uint64_t>(p);
83 if (l & (uint64_t(1) << 63))
85 return DiyFp(h, e + rhs.e + 64);
87 const uint64_t M32 = 0xFFFFFFFF;
88 const uint64_t a = f >> 32;
89 const uint64_t b = f & M32;
90 const uint64_t c = rhs.f >> 32;
91 const uint64_t d = rhs.f & M32;
92 const uint64_t ac = a * c;
93 const uint64_t bc = b * c;
94 const uint64_t ad = a * d;
95 const uint64_t bd = b * d;
96 uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
98 return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
102 DiyFp Normalize()
const {
103 int s = static_cast<int>(clzll(f));
104 return DiyFp(f << s, e - s);
107 DiyFp NormalizeBoundary()
const {
109 while (!(res.f & (kDpHiddenBit << 1))) {
113 res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
114 res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
118 void NormalizedBoundaries(DiyFp* minus, DiyFp* plus)
const {
119 DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
120 DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
121 mi.f <<= mi.e - pl.e;
127 double ToDouble()
const {
133 if (e < kDpDenormalExponent) {
137 if (e >= kDpMaxExponent) {
139 return std::numeric_limits<double>::infinity();
141 const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
142 static_cast<uint64_t>(e + kDpExponentBias);
143 u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
147 static const int kDiySignificandSize = 64;
148 static const int kDpSignificandSize = 52;
149 static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
150 static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
151 static const int kDpMinExponent = -kDpExponentBias;
152 static const int kDpDenormalExponent = -kDpExponentBias + 1;
161 inline DiyFp GetCachedPowerByIndex(
size_t index) {
163 static const uint64_t kCachedPowers_F[] = {
209 static const int16_t kCachedPowers_E[] = {
210 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
211 -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
212 -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
213 -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
214 -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
215 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
216 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
217 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
218 907, 933, 960, 986, 1013, 1039, 1066
221 return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
224 inline DiyFp GetCachedPower(
int e,
int* K) {
227 double dk = (-61 - e) * 0.30102999566398114 + 347;
228 int k = static_cast<int>(dk);
232 unsigned index = static_cast<unsigned>((k >> 3) + 1);
233 *K = -(-348 + static_cast<int>(index << 3));
235 return GetCachedPowerByIndex(index);
238 inline DiyFp GetCachedPower10(
int exp,
int *outExp) {
240 unsigned index = static_cast<unsigned>(exp + 348) / 8u;
241 *outExp = -348 + static_cast<int>(index) * 8;
242 return GetCachedPowerByIndex(index);
251 RAPIDJSON_DIAG_OFF(padded)
255 RAPIDJSON_NAMESPACE_END
257 #endif // RAPIDJSON_DIYFP_H_