19#ifndef RAPIDJSON_DIYFP_H_
20#define RAPIDJSON_DIYFP_H_
26#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
28#pragma intrinsic(_umul128)
36RAPIDJSON_DIAG_OFF(effc++)
41RAPIDJSON_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);
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;
161inline 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]);
224inline 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);
238inline 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);
251RAPIDJSON_DIAG_OFF(padded)
#define RAPIDJSON_ASSERT(x)
Assertion.
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
common definitions and configuration
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
DiyFp operator*(const DiyFp &rhs) const