diyfp.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON
2 // available.
3 //
4 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All
5 // rights reserved.
6 //
7 // Licensed under the MIT License (the "License"); you may not use this file
8 // except in compliance with the License. You may obtain a copy of the License
9 // at
10 //
11 // http://opensource.org/licenses/MIT
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 // License for the specific language governing permissions and limitations under
17 // the License.
18 
19 // This is a C++ header-only implementation of Grisu2 algorithm from the
20 // publication: Loitsch, Florian. "Printing floating-point numbers quickly and
21 // accurately with integers." ACM Sigplan Notices 45.6 (2010): 233-243.
22 
23 #ifndef RAPIDJSON_DIYFP_H_
24 #define RAPIDJSON_DIYFP_H_
25 
26 #include <limits>
27 #include "../rapidjson.h"
28 #include "clzll.h"
29 
30 #if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
31 #include <intrin.h>
32 #pragma intrinsic(_umul128)
33 #endif
34 
36 namespace internal {
37 
38 #ifdef __GNUC__
39 RAPIDJSON_DIAG_PUSH
40 RAPIDJSON_DIAG_OFF(effc++)
41 #endif
42 
43 #ifdef __clang__
44 RAPIDJSON_DIAG_PUSH
45 RAPIDJSON_DIAG_OFF(padded)
46 #endif
47 
48 struct DiyFp {
49  DiyFp() : f(), e() {}
50 
51  DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
52 
53  explicit DiyFp(double d) {
54  union {
55  double d;
56  uint64_t u64;
57  } u = {d};
58 
59  int biased_e =
60  static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
61  uint64_t significand = (u.u64 & kDpSignificandMask);
62  if (biased_e != 0) {
63  f = significand + kDpHiddenBit;
64  e = biased_e - kDpExponentBias;
65  } else {
66  f = significand;
67  e = kDpMinExponent + 1;
68  }
69  }
70 
71  DiyFp operator-(const DiyFp &rhs) const { return DiyFp(f - rhs.f, e); }
72 
73  DiyFp operator*(const DiyFp &rhs) const {
74 #if defined(_MSC_VER) && defined(_M_AMD64)
75  uint64_t h;
76  uint64_t l = _umul128(f, rhs.f, &h);
77  if (l & (uint64_t(1) << 63)) // rounding
78  h++;
79  return DiyFp(h, e + rhs.e + 64);
80 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && \
81  defined(__x86_64__)
82  __extension__ typedef unsigned __int128 uint128;
83  uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
84  uint64_t h = static_cast<uint64_t>(p >> 64);
85  uint64_t l = static_cast<uint64_t>(p);
86  if (l & (uint64_t(1) << 63)) // rounding
87  h++;
88  return DiyFp(h, e + rhs.e + 64);
89 #else
90  const uint64_t M32 = 0xFFFFFFFF;
91  const uint64_t a = f >> 32;
92  const uint64_t b = f & M32;
93  const uint64_t c = rhs.f >> 32;
94  const uint64_t d = rhs.f & M32;
95  const uint64_t ac = a * c;
96  const uint64_t bc = b * c;
97  const uint64_t ad = a * d;
98  const uint64_t bd = b * d;
99  uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
100  tmp += 1U << 31;
101  return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
102 #endif
103  }
104 
105  DiyFp Normalize() const {
106  int s = static_cast<int>(RAPIDJSON_CLZLL(f));
107  return DiyFp(f << s, e - s);
108  }
109 
111  DiyFp res = *this;
112  while (!(res.f & (kDpHiddenBit << 1))) {
113  res.f <<= 1;
114  res.e--;
115  }
116  res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
117  res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
118  return res;
119  }
120 
121  void NormalizedBoundaries(DiyFp *minus, DiyFp *plus) const {
122  DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
123  DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2)
124  : DiyFp((f << 1) - 1, e - 1);
125  mi.f <<= mi.e - pl.e;
126  mi.e = pl.e;
127  *plus = pl;
128  *minus = mi;
129  }
130 
131  double ToDouble() const {
132  union {
133  double d;
134  uint64_t u64;
135  } u;
137  if (e < kDpDenormalExponent) {
138  // Underflow.
139  return 0.0;
140  }
141  if (e >= kDpMaxExponent) {
142  // Overflow.
143  return std::numeric_limits<double>::infinity();
144  }
145  const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0)
146  ? 0
147  : static_cast<uint64_t>(e + kDpExponentBias);
148  u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
149  return u.d;
150  }
151 
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;
158  static const uint64_t kDpExponentMask =
159  RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
161  RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
162  static const uint64_t kDpHiddenBit =
163  RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
164 
166  int e;
167 };
168 
169 inline DiyFp GetCachedPowerByIndex(size_t index) {
170  // 10^-348, 10^-340, ..., 10^340
171  static const uint64_t kCachedPowers_F[] = {
172  RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288),
173  RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
174  RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76),
175  RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
176  RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d),
177  RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
178  RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca),
179  RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
180  RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c),
181  RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
182  RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83),
183  RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
184  RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb),
185  RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
186  RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57),
187  RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
188  RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f),
189  RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
190  RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4),
191  RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
192  RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e),
193  RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
194  RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba),
195  RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
196  RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584),
197  RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
198  RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126),
199  RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
200  RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b),
201  RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
202  RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655),
203  RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
204  RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f),
205  RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
206  RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf),
207  RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
208  RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6),
209  RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
210  RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06),
211  RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
212  RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e),
213  RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
214  RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc),
215  RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
216  RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000),
217  RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
218  RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000),
219  RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
220  RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3),
221  RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
222  RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068),
223  RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
224  RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27),
225  RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
226  RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db),
227  RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
228  RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758),
229  RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
230  RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a),
231  RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
232  RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877),
233  RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
234  RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d),
235  RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
236  RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3),
237  RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
238  RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c),
239  RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
240  RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2),
241  RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
242  RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df),
243  RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
244  RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396),
245  RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
246  RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410),
247  RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
248  RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c),
249  RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
250  RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d),
251  RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
252  RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85),
253  RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
254  RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f),
255  RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
256  RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9),
257  RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
258  RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)};
259  static const int16_t kCachedPowers_E[] = {
260  -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
261  -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
262  -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
263  -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
264  -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
265  242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
266  534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
267  827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
268  RAPIDJSON_ASSERT(index < 87);
269  return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
270 }
271 
272 inline DiyFp GetCachedPower(int e, int *K) {
273  // int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
274  double dk = (-61 - e) * 0.30102999566398114 +
275  347; // dk must be positive, so can do ceiling in positive
276  int k = static_cast<int>(dk);
277  if (dk - k > 0.0) k++;
278 
279  unsigned index = static_cast<unsigned>((k >> 3) + 1);
280  *K = -(-348 + static_cast<int>(
281  index << 3)); // decimal exponent no need lookup table
282 
283  return GetCachedPowerByIndex(index);
284 }
285 
286 inline DiyFp GetCachedPower10(int exp, int *outExp) {
287  RAPIDJSON_ASSERT(exp >= -348);
288  unsigned index = static_cast<unsigned>(exp + 348) / 8u;
289  *outExp = -348 + static_cast<int>(index) * 8;
290  return GetCachedPowerByIndex(index);
291 }
292 
293 #ifdef __GNUC__
294 RAPIDJSON_DIAG_POP
295 #endif
296 
297 #ifdef __clang__
298 RAPIDJSON_DIAG_POP
299 RAPIDJSON_DIAG_OFF(padded)
300 #endif
301 
302 } // namespace internal
304 
305 #endif // RAPIDJSON_DIYFP_H_
d
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:433
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:306
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:131
static const int kDpExponentBias
Definition: diyfp.h:154
XmlRpcServer s
DiyFp GetCachedPower10(int exp, int *outExp)
Definition: diyfp.h:286
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:128
static const int kDiySignificandSize
Definition: diyfp.h:152
DiyFp Normalize() const
Definition: diyfp.h:105
DiyFp(uint64_t fp, int exp)
Definition: diyfp.h:51
static const int kDpMaxExponent
Definition: diyfp.h:155
double ToDouble() const
Definition: diyfp.h:131
signed short int16_t
Definition: stdint.h:123
static const uint64_t kDpSignificandMask
Definition: diyfp.h:160
unsigned __int64 uint64_t
Definition: stdint.h:137
static const int kDpDenormalExponent
Definition: diyfp.h:157
DiyFp operator*(const DiyFp &rhs) const
Definition: diyfp.h:73
uint64_t f
Definition: diyfp.h:165
static const uint64_t kDpExponentMask
Definition: diyfp.h:158
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1365
DiyFp NormalizeBoundary() const
Definition: diyfp.h:110
#define RAPIDJSON_CLZLL
Definition: clzll.h:70
static const int kDpMinExponent
Definition: diyfp.h:156
DiyFp operator-(const DiyFp &rhs) const
Definition: diyfp.h:71
void NormalizedBoundaries(DiyFp *minus, DiyFp *plus) const
Definition: diyfp.h:121
DiyFp GetCachedPower(int e, int *K)
Definition: diyfp.h:272
DiyFp GetCachedPowerByIndex(size_t index)
Definition: diyfp.h:169
DiyFp(double d)
Definition: diyfp.h:53
static const uint64_t kDpHiddenBit
Definition: diyfp.h:162
static const int kDpSignificandSize
Definition: diyfp.h:153


livox_ros_driver
Author(s): Livox Dev Team
autogenerated on Mon Mar 15 2021 02:40:45