dtoa.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_DTOA_
24 #define RAPIDJSON_DTOA_
25 
26 #include "diyfp.h"
27 #include "ieee754.h"
28 #include "itoa.h" // GetDigitsLut()
29 
31 namespace internal {
32 
33 #ifdef __GNUC__
34 RAPIDJSON_DIAG_PUSH
35 RAPIDJSON_DIAG_OFF(effc++)
36 RAPIDJSON_DIAG_OFF(array - bounds) // some gcc versions generate wrong warnings
37 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
38 #endif
39 
40 inline void GrisuRound(char *buffer, int len, uint64_t delta, uint64_t rest,
41  uint64_t ten_kappa, uint64_t wp_w) {
42  while (rest < wp_w && delta - rest >= ten_kappa &&
43  (rest + ten_kappa < wp_w ||
44  wp_w - rest > rest + ten_kappa - wp_w)) {
45  buffer[len - 1]--;
46  rest += ten_kappa;
47  }
48 }
49 
51  // Simple pure C++ implementation was faster than __builtin_clz version in
52  // this situation.
53  if (n < 10) return 1;
54  if (n < 100) return 2;
55  if (n < 1000) return 3;
56  if (n < 10000) return 4;
57  if (n < 100000) return 5;
58  if (n < 1000000) return 6;
59  if (n < 10000000) return 7;
60  if (n < 100000000) return 8;
61  // Will not reach 10 digits in DigitGen()
62  // if (n < 1000000000) return 9;
63  // return 10;
64  return 9;
65 }
66 
67 inline void DigitGen(const DiyFp &W, const DiyFp &Mp, uint64_t delta,
68  char *buffer, int *len, int *K) {
69  static const uint32_t kPow10[] = {1, 10, 100, 1000,
70  10000, 100000, 1000000, 10000000,
71  100000000, 1000000000};
72  const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
73  const DiyFp wp_w = Mp - W;
74  uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
75  uint64_t p2 = Mp.f & (one.f - 1);
76  int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
77  *len = 0;
78 
79  while (kappa > 0) {
80  uint32_t d = 0;
81  switch (kappa) {
82  case 9:
83  d = p1 / 100000000;
84  p1 %= 100000000;
85  break;
86  case 8:
87  d = p1 / 10000000;
88  p1 %= 10000000;
89  break;
90  case 7:
91  d = p1 / 1000000;
92  p1 %= 1000000;
93  break;
94  case 6:
95  d = p1 / 100000;
96  p1 %= 100000;
97  break;
98  case 5:
99  d = p1 / 10000;
100  p1 %= 10000;
101  break;
102  case 4:
103  d = p1 / 1000;
104  p1 %= 1000;
105  break;
106  case 3:
107  d = p1 / 100;
108  p1 %= 100;
109  break;
110  case 2:
111  d = p1 / 10;
112  p1 %= 10;
113  break;
114  case 1:
115  d = p1;
116  p1 = 0;
117  break;
118  default:;
119  }
120  if (d || *len)
121  buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
122  kappa--;
123  uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
124  if (tmp <= delta) {
125  *K += kappa;
126  GrisuRound(buffer, *len, delta, tmp,
127  static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
128  return;
129  }
130  }
131 
132  // kappa = 0
133  for (;;) {
134  p2 *= 10;
135  delta *= 10;
136  char d = static_cast<char>(p2 >> -one.e);
137  if (d || *len) buffer[(*len)++] = static_cast<char>('0' + d);
138  p2 &= one.f - 1;
139  kappa--;
140  if (p2 < delta) {
141  *K += kappa;
142  int index = -kappa;
143  GrisuRound(buffer, *len, delta, p2, one.f,
144  wp_w.f * (index < 9 ? kPow10[index] : 0));
145  return;
146  }
147  }
148 }
149 
150 inline void Grisu2(double value, char *buffer, int *length, int *K) {
151  const DiyFp v(value);
152  DiyFp w_m, w_p;
153  v.NormalizedBoundaries(&w_m, &w_p);
154 
155  const DiyFp c_mk = GetCachedPower(w_p.e, K);
156  const DiyFp W = v.Normalize() * c_mk;
157  DiyFp Wp = w_p * c_mk;
158  DiyFp Wm = w_m * c_mk;
159  Wm.f++;
160  Wp.f--;
161  DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
162 }
163 
164 inline char *WriteExponent(int K, char *buffer) {
165  if (K < 0) {
166  *buffer++ = '-';
167  K = -K;
168  }
169 
170  if (K >= 100) {
171  *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
172  K %= 100;
173  const char *d = GetDigitsLut() + K * 2;
174  *buffer++ = d[0];
175  *buffer++ = d[1];
176  } else if (K >= 10) {
177  const char *d = GetDigitsLut() + K * 2;
178  *buffer++ = d[0];
179  *buffer++ = d[1];
180  } else
181  *buffer++ = static_cast<char>('0' + static_cast<char>(K));
182 
183  return buffer;
184 }
185 
186 inline char *Prettify(char *buffer, int length, int k, int maxDecimalPlaces) {
187  const int kk = length + k; // 10^(kk-1) <= v < 10^kk
188 
189  if (0 <= k && kk <= 21) {
190  // 1234e7 -> 12340000000
191  for (int i = length; i < kk; i++) buffer[i] = '0';
192  buffer[kk] = '.';
193  buffer[kk + 1] = '0';
194  return &buffer[kk + 2];
195  } else if (0 < kk && kk <= 21) {
196  // 1234e-2 -> 12.34
197  std::memmove(&buffer[kk + 1], &buffer[kk],
198  static_cast<size_t>(length - kk));
199  buffer[kk] = '.';
200  if (0 > k + maxDecimalPlaces) {
201  // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
202  // Remove extra trailing zeros (at least one) after truncation.
203  for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
204  if (buffer[i] != '0') return &buffer[i + 1];
205  return &buffer[kk + 2]; // Reserve one zero
206  } else
207  return &buffer[length + 1];
208  } else if (-6 < kk && kk <= 0) {
209  // 1234e-6 -> 0.001234
210  const int offset = 2 - kk;
211  std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
212  buffer[0] = '0';
213  buffer[1] = '.';
214  for (int i = 2; i < offset; i++) buffer[i] = '0';
215  if (length - kk > maxDecimalPlaces) {
216  // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
217  // Remove extra trailing zeros (at least one) after truncation.
218  for (int i = maxDecimalPlaces + 1; i > 2; i--)
219  if (buffer[i] != '0') return &buffer[i + 1];
220  return &buffer[3]; // Reserve one zero
221  } else
222  return &buffer[length + offset];
223  } else if (kk < -maxDecimalPlaces) {
224  // Truncate to zero
225  buffer[0] = '0';
226  buffer[1] = '.';
227  buffer[2] = '0';
228  return &buffer[3];
229  } else if (length == 1) {
230  // 1e30
231  buffer[1] = 'e';
232  return WriteExponent(kk - 1, &buffer[2]);
233  } else {
234  // 1234e30 -> 1.234e33
235  std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
236  buffer[1] = '.';
237  buffer[length + 1] = 'e';
238  return WriteExponent(kk - 1, &buffer[0 + length + 2]);
239  }
240 }
241 
242 inline char *dtoa(double value, char *buffer, int maxDecimalPlaces = 324) {
243  RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
244  Double d(value);
245  if (d.IsZero()) {
246  if (d.Sign()) *buffer++ = '-'; // -0.0, Issue #289
247  buffer[0] = '0';
248  buffer[1] = '.';
249  buffer[2] = '0';
250  return &buffer[3];
251  } else {
252  if (value < 0) {
253  *buffer++ = '-';
254  value = -value;
255  }
256  int length, K;
257  Grisu2(value, buffer, &length, &K);
258  return Prettify(buffer, length, K, maxDecimalPlaces);
259  }
260 }
261 
262 #ifdef __GNUC__
263 RAPIDJSON_DIAG_POP
264 #endif
265 
266 } // namespace internal
268 
269 #endif // RAPIDJSON_DTOA_
d
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:433
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:131
char * Prettify(char *buffer, int length, int k, int maxDecimalPlaces)
Definition: dtoa.h:186
const char * GetDigitsLut()
Definition: itoa.h:27
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:128
DiyFp Normalize() const
Definition: diyfp.h:105
bool Sign() const
Definition: ieee754.h:41
void Grisu2(double value, char *buffer, int *length, int *K)
Definition: dtoa.h:150
unsigned int uint32_t
Definition: stdint.h:127
bool IsZero() const
Definition: ieee754.h:58
void GrisuRound(char *buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w)
Definition: dtoa.h:40
unsigned __int64 uint64_t
Definition: stdint.h:137
uint64_t f
Definition: diyfp.h:165
void DigitGen(const DiyFp &W, const DiyFp &Mp, uint64_t delta, char *buffer, int *len, int *K)
Definition: dtoa.h:67
char * WriteExponent(int K, char *buffer)
Definition: dtoa.h:164
int CountDecimalDigit32(uint32_t n)
Definition: dtoa.h:50
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1518
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
void NormalizedBoundaries(DiyFp *minus, DiyFp *plus) const
Definition: diyfp.h:121
DiyFp GetCachedPower(int e, int *K)
Definition: diyfp.h:272
char * dtoa(double value, char *buffer, int maxDecimalPlaces=324)
Definition: dtoa.h:242


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