20#ifndef RAPIDJSON_DIYFP_H_
21#define RAPIDJSON_DIYFP_H_
27#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
29#if !defined(_ARM64EC_)
30#pragma intrinsic(_umul128)
32#pragma comment(lib,"softintrin")
41RAPIDJSON_DIAG_OFF(effc++)
46RAPIDJSON_DIAG_OFF(padded)
52 DiyFp(uint64_t fp,
int exp) : f(fp), e(exp) {}
54 explicit DiyFp(
double d) {
60 int biased_e =
static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
61 uint64_t significand = (u.u64 & kDpSignificandMask);
63 f = significand + kDpHiddenBit;
64 e = biased_e - kDpExponentBias;
68 e = kDpMinExponent + 1;
72 DiyFp operator-(
const DiyFp& rhs)
const {
73 return DiyFp(f - rhs.f, e);
77#if defined(_MSC_VER) && defined(_M_AMD64)
79 uint64_t l = _umul128(f, rhs.f, &h);
80 if (l & (uint64_t(1) << 63))
82 return DiyFp(h, e + rhs.e + 64);
83#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
84 __extension__
typedef unsigned __int128 uint128;
85 uint128 p =
static_cast<uint128
>(f) *
static_cast<uint128
>(rhs.f);
86 uint64_t h =
static_cast<uint64_t
>(p >> 64);
87 uint64_t l =
static_cast<uint64_t
>(p);
88 if (l & (uint64_t(1) << 63))
90 return DiyFp(h, e + rhs.e + 64);
92 const uint64_t M32 = 0xFFFFFFFF;
93 const uint64_t a = f >> 32;
94 const uint64_t b = f & M32;
95 const uint64_t c = rhs.f >> 32;
96 const uint64_t d = rhs.f & M32;
97 const uint64_t ac = a * c;
98 const uint64_t bc = b * c;
99 const uint64_t ad = a * d;
100 const uint64_t bd = b * d;
101 uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
103 return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
107 DiyFp Normalize()
const {
108 int s =
static_cast<int>(clzll(f));
109 return DiyFp(f << s, e - s);
112 DiyFp NormalizeBoundary()
const {
114 while (!(res.f & (kDpHiddenBit << 1))) {
118 res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
119 res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
123 void NormalizedBoundaries(DiyFp* minus, DiyFp* plus)
const {
124 DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
125 DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
126 mi.f <<= mi.e - pl.e;
132 double ToDouble()
const {
138 if (e < kDpDenormalExponent) {
142 if (e >= kDpMaxExponent) {
144 return std::numeric_limits<double>::infinity();
146 const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
147 static_cast<uint64_t>(e + kDpExponentBias);
148 u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
152 static const int kDiySignificandSize = 64;
153 static const int kDpSignificandSize = 52;
154 static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
155 static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
156 static const int kDpMinExponent = -kDpExponentBias;
157 static const int kDpDenormalExponent = -kDpExponentBias + 1;
166inline DiyFp GetCachedPowerByIndex(
size_t index) {
168 static const uint64_t kCachedPowers_F[] = {
214 static const int16_t kCachedPowers_E[] = {
215 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
216 -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
217 -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
218 -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
219 -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
220 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
221 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
222 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
223 907, 933, 960, 986, 1013, 1039, 1066
226 return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
229inline DiyFp GetCachedPower(
int e,
int* K) {
232 double dk = (-61 - e) * 0.30102999566398114 + 347;
233 int k =
static_cast<int>(dk);
237 unsigned index =
static_cast<unsigned>((k >> 3) + 1);
238 *K = -(-348 +
static_cast<int>(index << 3));
240 return GetCachedPowerByIndex(index);
243inline DiyFp GetCachedPower10(
int exp,
int *outExp) {
245 unsigned index =
static_cast<unsigned>(
exp + 348) / 8u;
246 *outExp = -348 +
static_cast<int>(index) * 8;
247 return GetCachedPowerByIndex(index);
256RAPIDJSON_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)
__host__ __device__ double exp(double v)
Exponentielle de v.
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