File indexing completed on 2025-12-16 10:28:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef RAPIDJSON_DIYFP_H_
0020 #define RAPIDJSON_DIYFP_H_
0021
0022 #include "../rapidjson.h"
0023 #include "clzll.h"
0024 #include <limits>
0025
0026 #if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
0027 #include <intrin.h>
0028 #if !defined(_ARM64EC_)
0029 #pragma intrinsic(_umul128)
0030 #else
0031 #pragma comment(lib,"softintrin")
0032 #endif
0033 #endif
0034
0035 RAPIDJSON_NAMESPACE_BEGIN
0036 namespace internal {
0037
0038 #ifdef __GNUC__
0039 RAPIDJSON_DIAG_PUSH
0040 RAPIDJSON_DIAG_OFF(effc++)
0041 #endif
0042
0043 #ifdef __clang__
0044 RAPIDJSON_DIAG_PUSH
0045 RAPIDJSON_DIAG_OFF(padded)
0046 #endif
0047
0048 struct DiyFp {
0049 DiyFp() : f(), e() {}
0050
0051 DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
0052
0053 explicit DiyFp(double d) {
0054 union {
0055 double d;
0056 uint64_t u64;
0057 } u = { d };
0058
0059 int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
0060 uint64_t significand = (u.u64 & kDpSignificandMask);
0061 if (biased_e != 0) {
0062 f = significand + kDpHiddenBit;
0063 e = biased_e - kDpExponentBias;
0064 }
0065 else {
0066 f = significand;
0067 e = kDpMinExponent + 1;
0068 }
0069 }
0070
0071 DiyFp operator-(const DiyFp& rhs) const {
0072 return DiyFp(f - rhs.f, e);
0073 }
0074
0075 DiyFp operator*(const DiyFp& rhs) const {
0076 #if defined(_MSC_VER) && defined(_M_AMD64)
0077 uint64_t h;
0078 uint64_t l = _umul128(f, rhs.f, &h);
0079 if (l & (uint64_t(1) << 63))
0080 h++;
0081 return DiyFp(h, e + rhs.e + 64);
0082 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
0083 __extension__ typedef unsigned __int128 uint128;
0084 uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
0085 uint64_t h = static_cast<uint64_t>(p >> 64);
0086 uint64_t l = static_cast<uint64_t>(p);
0087 if (l & (uint64_t(1) << 63))
0088 h++;
0089 return DiyFp(h, e + rhs.e + 64);
0090 #else
0091 const uint64_t M32 = 0xFFFFFFFF;
0092 const uint64_t a = f >> 32;
0093 const uint64_t b = f & M32;
0094 const uint64_t c = rhs.f >> 32;
0095 const uint64_t d = rhs.f & M32;
0096 const uint64_t ac = a * c;
0097 const uint64_t bc = b * c;
0098 const uint64_t ad = a * d;
0099 const uint64_t bd = b * d;
0100 uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
0101 tmp += 1U << 31;
0102 return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
0103 #endif
0104 }
0105
0106 DiyFp Normalize() const {
0107 int s = static_cast<int>(clzll(f));
0108 return DiyFp(f << s, e - s);
0109 }
0110
0111 DiyFp NormalizeBoundary() const {
0112 DiyFp res = *this;
0113 while (!(res.f & (kDpHiddenBit << 1))) {
0114 res.f <<= 1;
0115 res.e--;
0116 }
0117 res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
0118 res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
0119 return res;
0120 }
0121
0122 void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
0123 DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
0124 DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
0125 mi.f <<= mi.e - pl.e;
0126 mi.e = pl.e;
0127 *plus = pl;
0128 *minus = mi;
0129 }
0130
0131 double ToDouble() const {
0132 union {
0133 double d;
0134 uint64_t u64;
0135 }u;
0136 RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
0137 if (e < kDpDenormalExponent) {
0138
0139 return 0.0;
0140 }
0141 if (e >= kDpMaxExponent) {
0142
0143 return std::numeric_limits<double>::infinity();
0144 }
0145 const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
0146 static_cast<uint64_t>(e + kDpExponentBias);
0147 u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
0148 return u.d;
0149 }
0150
0151 static const int kDiySignificandSize = 64;
0152 static const int kDpSignificandSize = 52;
0153 static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
0154 static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
0155 static const int kDpMinExponent = -kDpExponentBias;
0156 static const int kDpDenormalExponent = -kDpExponentBias + 1;
0157 static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
0158 static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
0159 static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
0160
0161 uint64_t f;
0162 int e;
0163 };
0164
0165 inline DiyFp GetCachedPowerByIndex(size_t index) {
0166
0167 static const uint64_t kCachedPowers_F[] = {
0168 RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
0169 RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
0170 RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
0171 RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
0172 RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
0173 RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
0174 RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
0175 RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
0176 RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
0177 RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
0178 RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
0179 RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
0180 RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
0181 RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
0182 RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
0183 RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
0184 RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
0185 RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
0186 RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
0187 RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
0188 RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
0189 RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
0190 RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
0191 RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
0192 RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
0193 RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
0194 RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
0195 RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
0196 RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
0197 RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
0198 RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
0199 RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
0200 RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
0201 RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
0202 RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
0203 RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
0204 RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
0205 RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
0206 RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
0207 RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
0208 RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
0209 RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
0210 RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
0211 RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
0212 };
0213 static const int16_t kCachedPowers_E[] = {
0214 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
0215 -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
0216 -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
0217 -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
0218 -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
0219 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
0220 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
0221 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
0222 907, 933, 960, 986, 1013, 1039, 1066
0223 };
0224 RAPIDJSON_ASSERT(index < 87);
0225 return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
0226 }
0227
0228 inline DiyFp GetCachedPower(int e, int* K) {
0229
0230
0231 double dk = (-61 - e) * 0.30102999566398114 + 347;
0232 int k = static_cast<int>(dk);
0233 if (dk - k > 0.0)
0234 k++;
0235
0236 unsigned index = static_cast<unsigned>((k >> 3) + 1);
0237 *K = -(-348 + static_cast<int>(index << 3));
0238
0239 return GetCachedPowerByIndex(index);
0240 }
0241
0242 inline DiyFp GetCachedPower10(int exp, int *outExp) {
0243 RAPIDJSON_ASSERT(exp >= -348);
0244 unsigned index = static_cast<unsigned>(exp + 348) / 8u;
0245 *outExp = -348 + static_cast<int>(index) * 8;
0246 return GetCachedPowerByIndex(index);
0247 }
0248
0249 #ifdef __GNUC__
0250 RAPIDJSON_DIAG_POP
0251 #endif
0252
0253 #ifdef __clang__
0254 RAPIDJSON_DIAG_POP
0255 RAPIDJSON_DIAG_OFF(padded)
0256 #endif
0257
0258 }
0259 RAPIDJSON_NAMESPACE_END
0260
0261 #endif