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++)
40 RAPIDJSON_DIAG_OFF(padded)
46 DiyFp(uint64_t fp,
int exp) : f(fp), e(exp) {}
48 explicit DiyFp(
double d) {
54 int biased_e =
static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
55 uint64_t significand = (u.u64 & kDpSignificandMask);
57 f = significand + kDpHiddenBit;
58 e = biased_e - kDpExponentBias;
62 e = kDpMinExponent + 1;
66 DiyFp operator-(
const DiyFp& rhs)
const {
67 return DiyFp(f - rhs.f, e);
70 DiyFp operator*(
const DiyFp& rhs)
const {
71 #if defined(_MSC_VER) && defined(_M_AMD64)
73 uint64_t l = _umul128(f, rhs.f, &h);
74 if (l & (uint64_t(1) << 63))
76 return DiyFp(h, e + rhs.e + 64);
77 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
78 __extension__
typedef unsigned __int128 uint128;
79 uint128 p =
static_cast<uint128
>(f) *
static_cast<uint128
>(rhs.f);
80 uint64_t h =
static_cast<uint64_t
>(p >> 64);
81 uint64_t l =
static_cast<uint64_t
>(p);
82 if (l & (uint64_t(1) << 63))
84 return DiyFp(h, e + rhs.e + 64);
86 const uint64_t M32 = 0xFFFFFFFF;
87 const uint64_t a = f >> 32;
88 const uint64_t b = f & M32;
89 const uint64_t c = rhs.f >> 32;
90 const uint64_t d = rhs.f & M32;
91 const uint64_t ac = a * c;
92 const uint64_t bc = b * c;
93 const uint64_t ad = a * d;
94 const uint64_t bd = b * d;
95 uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
97 return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
101 DiyFp Normalize()
const {
102 #if defined(_MSC_VER) && defined(_M_AMD64)
104 _BitScanReverse64(&index, f);
105 return DiyFp(f << (63 - index), e - (63 - index));
106 #elif defined(__GNUC__) && __GNUC__ >= 4
107 int s = __builtin_clzll(f);
108 return DiyFp(f << s, e - s);
111 while (!(res.f & (
static_cast<uint64_t
>(1) << 63))) {
119 DiyFp NormalizeBoundary()
const {
121 while (!(res.f & (kDpHiddenBit << 1))) {
125 res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
126 res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
130 void NormalizedBoundaries(DiyFp* minus, DiyFp* plus)
const {
131 DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
132 DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
133 mi.f <<= mi.e - pl.e;
139 double ToDouble()
const {
144 const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
145 static_cast<uint64_t
>(e + kDpExponentBias);
146 u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
150 static const int kDiySignificandSize = 64;
151 static const int kDpSignificandSize = 52;
152 static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
153 static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
154 static const int kDpMinExponent = -kDpExponentBias;
155 static const int kDpDenormalExponent = -kDpExponentBias + 1;
164 inline DiyFp GetCachedPowerByIndex(
size_t index) {
166 static const uint64_t kCachedPowers_F[] = {
212 static const int16_t kCachedPowers_E[] = {
213 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
214 -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
215 -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
216 -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
217 -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
218 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
219 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
220 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
221 907, 933, 960, 986, 1013, 1039, 1066
223 return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
226 inline DiyFp GetCachedPower(
int e,
int* K) {
229 double dk = (-61 - e) * 0.30102999566398114 + 347;
230 int k =
static_cast<int>(dk);
234 unsigned index =
static_cast<unsigned>((k >> 3) + 1);
235 *K = -(-348 +
static_cast<int>(index << 3));
237 return GetCachedPowerByIndex(index);
240 inline DiyFp GetCachedPower10(
int exp,
int *outExp) {
241 unsigned index = (
static_cast<unsigned>(exp) + 348u) / 8u;
242 *outExp = -348 +
static_cast<int>(index) * 8;
243 return GetCachedPowerByIndex(index);
252 RAPIDJSON_DIAG_OFF(padded)
256 RAPIDJSON_NAMESPACE_END
258 #endif // RAPIDJSON_DIYFP_H_