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)
27 #pragma intrinsic(_umul128)
30 RAPIDJSON_NAMESPACE_BEGIN
35 RAPIDJSON_DIAG_OFF(effc++)
41 DiyFp(uint64_t fp,
int exp) : f(fp), e(exp) {}
43 explicit DiyFp(
double d) {
49 int biased_e =
static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
50 uint64_t significand = (u.u64 & kDpSignificandMask);
52 f = significand + kDpHiddenBit;
53 e = biased_e - kDpExponentBias;
57 e = kDpMinExponent + 1;
61 DiyFp operator-(
const DiyFp& rhs)
const {
62 return DiyFp(f - rhs.f, e);
65 DiyFp operator*(
const DiyFp& rhs)
const {
66 #if defined(_MSC_VER) && defined(_M_AMD64)
68 uint64_t l = _umul128(f, rhs.f, &h);
69 if (l & (uint64_t(1) << 63))
71 return DiyFp(h, e + rhs.e + 64);
72 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
73 __extension__
typedef unsigned __int128 uint128;
74 uint128 p =
static_cast<uint128
>(f) * static_cast<uint128>(rhs.f);
75 uint64_t h =
static_cast<uint64_t
>(p >> 64);
76 uint64_t l =
static_cast<uint64_t
>(p);
77 if (l & (uint64_t(1) << 63))
79 return DiyFp(h, e + rhs.e + 64);
81 const uint64_t M32 = 0xFFFFFFFF;
82 const uint64_t a = f >> 32;
83 const uint64_t b = f & M32;
84 const uint64_t c = rhs.f >> 32;
85 const uint64_t d = rhs.f & M32;
86 const uint64_t ac = a * c;
87 const uint64_t bc = b * c;
88 const uint64_t ad = a * d;
89 const uint64_t bd = b * d;
90 uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
92 return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
96 DiyFp Normalize()
const {
97 #if defined(_MSC_VER) && defined(_M_AMD64)
99 _BitScanReverse64(&index, f);
100 return DiyFp(f << (63 - index), e - (63 - index));
101 #elif defined(__GNUC__) && __GNUC__ >= 4
102 int s = __builtin_clzll(f);
103 return DiyFp(f << s, e - s);
106 while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
114 DiyFp NormalizeBoundary()
const {
116 while (!(res.f & (kDpHiddenBit << 1))) {
120 res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
121 res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
125 void NormalizedBoundaries(DiyFp* minus, DiyFp* plus)
const {
126 DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
127 DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
128 mi.f <<= mi.e - pl.e;
134 double ToDouble()
const {
139 const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
140 static_cast<uint64_t
>(e + kDpExponentBias);
141 u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
145 static const int kDiySignificandSize = 64;
146 static const int kDpSignificandSize = 52;
147 static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
148 static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
149 static const int kDpMinExponent = -kDpExponentBias;
150 static const int kDpDenormalExponent = -kDpExponentBias + 1;
159 inline DiyFp GetCachedPowerByIndex(
size_t index) {
161 static const uint64_t kCachedPowers_F[] = {
207 static const int16_t kCachedPowers_E[] = {
208 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
209 -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
210 -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
211 -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
212 -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
213 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
214 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
215 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
216 907, 933, 960, 986, 1013, 1039, 1066
218 return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
221 inline DiyFp GetCachedPower(
int e,
int* K) {
224 double dk = (-61 - e) * 0.30102999566398114 + 347;
225 int k =
static_cast<int>(dk);
229 unsigned index =
static_cast<unsigned>((k >> 3) + 1);
230 *K = -(-348 +
static_cast<int>(index << 3));
232 return GetCachedPowerByIndex(index);
235 inline DiyFp GetCachedPower10(
int exp,
int *outExp) {
236 unsigned index = (
static_cast<unsigned>(exp) + 348u) / 8u;
237 *outExp = -348 +
static_cast<int>(index) * 8;
238 return GetCachedPowerByIndex(index);
246 RAPIDJSON_NAMESPACE_END
248 #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