QUDA  v1.1.0
A library for QCD on GPUs
uint_to_char.h
Go to the documentation of this file.
1 #pragma once
2 
3 namespace quda {
4 
5  /*
6  Fast 32-bit and 64-bit conversion to strings. Slightly modified
7  from the original taken from https://github.com/miloyip/itoa-benchmark.
8 
9  Copyright (C) 2014 Milo Yip
10 
11  Permission is hereby granted, free of charge, to any person
12  obtaining a copy of this software and associated documentation
13  files (the "Software"), to deal in the Software without
14  restriction, including without limitation the rights to use, copy,
15  modify, merge, publish, distribute, sublicense, and/or sell copies
16  of the Software, and to permit persons to whom the Software is
17  furnished to do so, subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be
20  included in all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29  DEALINGS IN THE SOFTWARE.
30  */
31 
32  static const char gDigitsLut[200] = {
33  '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
34  '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
35  '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
36  '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
37  '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
38  '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
39  '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
40  '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
41  '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
42  '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
43  };
44 
45  inline void u32toa(char* buffer, uint32_t value) {
46  if (value < 10000) {
47  const uint32_t d1 = (value / 100) << 1;
48  const uint32_t d2 = (value % 100) << 1;
49 
50  if (value >= 1000)
51  *buffer++ = gDigitsLut[d1];
52  if (value >= 100)
53  *buffer++ = gDigitsLut[d1 + 1];
54  if (value >= 10)
55  *buffer++ = gDigitsLut[d2];
56  *buffer++ = gDigitsLut[d2 + 1];
57  }
58  else if (value < 100000000) {
59  // value = bbbbcccc
60  const uint32_t b = value / 10000;
61  const uint32_t c = value % 10000;
62 
63  const uint32_t d1 = (b / 100) << 1;
64  const uint32_t d2 = (b % 100) << 1;
65 
66  const uint32_t d3 = (c / 100) << 1;
67  const uint32_t d4 = (c % 100) << 1;
68 
69  if (value >= 10000000)
70  *buffer++ = gDigitsLut[d1];
71  if (value >= 1000000)
72  *buffer++ = gDigitsLut[d1 + 1];
73  if (value >= 100000)
74  *buffer++ = gDigitsLut[d2];
75  *buffer++ = gDigitsLut[d2 + 1];
76 
77  *buffer++ = gDigitsLut[d3];
78  *buffer++ = gDigitsLut[d3 + 1];
79  *buffer++ = gDigitsLut[d4];
80  *buffer++ = gDigitsLut[d4 + 1];
81  }
82  else {
83  // value = aabbbbcccc in decimal
84 
85  const uint32_t a = value / 100000000; // 1 to 42
86  value %= 100000000;
87 
88  if (a >= 10) {
89  const unsigned i = a << 1;
90  *buffer++ = gDigitsLut[i];
91  *buffer++ = gDigitsLut[i + 1];
92  }
93  else
94  *buffer++ = '0' + static_cast<char>(a);
95 
96  const uint32_t b = value / 10000; // 0 to 9999
97  const uint32_t c = value % 10000; // 0 to 9999
98 
99  const uint32_t d1 = (b / 100) << 1;
100  const uint32_t d2 = (b % 100) << 1;
101 
102  const uint32_t d3 = (c / 100) << 1;
103  const uint32_t d4 = (c % 100) << 1;
104 
105  *buffer++ = gDigitsLut[d1];
106  *buffer++ = gDigitsLut[d1 + 1];
107  *buffer++ = gDigitsLut[d2];
108  *buffer++ = gDigitsLut[d2 + 1];
109  *buffer++ = gDigitsLut[d3];
110  *buffer++ = gDigitsLut[d3 + 1];
111  *buffer++ = gDigitsLut[d4];
112  *buffer++ = gDigitsLut[d4 + 1];
113  }
114  *buffer++ = '\0';
115  }
116 
117  inline void i32toa(char* buffer, int32_t value) {
118  uint32_t u = static_cast<uint32_t>(value);
119  if (value < 0) {
120  *buffer++ = '-';
121  u = ~u + 1;
122  }
123 
124  u32toa(buffer, u);
125  }
126 
127  inline void u64toa(char* buffer, uint64_t value) {
128  if (value < 100000000) {
129  uint32_t v = static_cast<uint32_t>(value);
130  if (v < 10000) {
131  const uint32_t d1 = (v / 100) << 1;
132  const uint32_t d2 = (v % 100) << 1;
133 
134  if (v >= 1000)
135  *buffer++ = gDigitsLut[d1];
136  if (v >= 100)
137  *buffer++ = gDigitsLut[d1 + 1];
138  if (v >= 10)
139  *buffer++ = gDigitsLut[d2];
140  *buffer++ = gDigitsLut[d2 + 1];
141  }
142  else {
143  // value = bbbbcccc
144  const uint32_t b = v / 10000;
145  const uint32_t c = v % 10000;
146 
147  const uint32_t d1 = (b / 100) << 1;
148  const uint32_t d2 = (b % 100) << 1;
149 
150  const uint32_t d3 = (c / 100) << 1;
151  const uint32_t d4 = (c % 100) << 1;
152 
153  if (value >= 10000000)
154  *buffer++ = gDigitsLut[d1];
155  if (value >= 1000000)
156  *buffer++ = gDigitsLut[d1 + 1];
157  if (value >= 100000)
158  *buffer++ = gDigitsLut[d2];
159  *buffer++ = gDigitsLut[d2 + 1];
160 
161  *buffer++ = gDigitsLut[d3];
162  *buffer++ = gDigitsLut[d3 + 1];
163  *buffer++ = gDigitsLut[d4];
164  *buffer++ = gDigitsLut[d4 + 1];
165  }
166  }
167  else if (value < 10000000000000000) {
168  const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
169  const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
170 
171  const uint32_t b0 = v0 / 10000;
172  const uint32_t c0 = v0 % 10000;
173 
174  const uint32_t d1 = (b0 / 100) << 1;
175  const uint32_t d2 = (b0 % 100) << 1;
176 
177  const uint32_t d3 = (c0 / 100) << 1;
178  const uint32_t d4 = (c0 % 100) << 1;
179 
180  const uint32_t b1 = v1 / 10000;
181  const uint32_t c1 = v1 % 10000;
182 
183  const uint32_t d5 = (b1 / 100) << 1;
184  const uint32_t d6 = (b1 % 100) << 1;
185 
186  const uint32_t d7 = (c1 / 100) << 1;
187  const uint32_t d8 = (c1 % 100) << 1;
188 
189  if (value >= 1000000000000000)
190  *buffer++ = gDigitsLut[d1];
191  if (value >= 100000000000000)
192  *buffer++ = gDigitsLut[d1 + 1];
193  if (value >= 10000000000000)
194  *buffer++ = gDigitsLut[d2];
195  if (value >= 1000000000000)
196  *buffer++ = gDigitsLut[d2 + 1];
197  if (value >= 100000000000)
198  *buffer++ = gDigitsLut[d3];
199  if (value >= 10000000000)
200  *buffer++ = gDigitsLut[d3 + 1];
201  if (value >= 1000000000)
202  *buffer++ = gDigitsLut[d4];
203  if (value >= 100000000)
204  *buffer++ = gDigitsLut[d4 + 1];
205 
206  *buffer++ = gDigitsLut[d5];
207  *buffer++ = gDigitsLut[d5 + 1];
208  *buffer++ = gDigitsLut[d6];
209  *buffer++ = gDigitsLut[d6 + 1];
210  *buffer++ = gDigitsLut[d7];
211  *buffer++ = gDigitsLut[d7 + 1];
212  *buffer++ = gDigitsLut[d8];
213  *buffer++ = gDigitsLut[d8 + 1];
214  }
215  else {
216  const uint32_t a = static_cast<uint32_t>(value / 10000000000000000); // 1 to 1844
217  value %= 10000000000000000;
218 
219  if (a < 10)
220  *buffer++ = '0' + static_cast<char>(a);
221  else if (a < 100) {
222  const uint32_t i = a << 1;
223  *buffer++ = gDigitsLut[i];
224  *buffer++ = gDigitsLut[i + 1];
225  }
226  else if (a < 1000) {
227  *buffer++ = '0' + static_cast<char>(a / 100);
228 
229  const uint32_t i = (a % 100) << 1;
230  *buffer++ = gDigitsLut[i];
231  *buffer++ = gDigitsLut[i + 1];
232  }
233  else {
234  const uint32_t i = (a / 100) << 1;
235  const uint32_t j = (a % 100) << 1;
236  *buffer++ = gDigitsLut[i];
237  *buffer++ = gDigitsLut[i + 1];
238  *buffer++ = gDigitsLut[j];
239  *buffer++ = gDigitsLut[j + 1];
240  }
241 
242  const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
243  const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
244 
245  const uint32_t b0 = v0 / 10000;
246  const uint32_t c0 = v0 % 10000;
247 
248  const uint32_t d1 = (b0 / 100) << 1;
249  const uint32_t d2 = (b0 % 100) << 1;
250 
251  const uint32_t d3 = (c0 / 100) << 1;
252  const uint32_t d4 = (c0 % 100) << 1;
253 
254  const uint32_t b1 = v1 / 10000;
255  const uint32_t c1 = v1 % 10000;
256 
257  const uint32_t d5 = (b1 / 100) << 1;
258  const uint32_t d6 = (b1 % 100) << 1;
259 
260  const uint32_t d7 = (c1 / 100) << 1;
261  const uint32_t d8 = (c1 % 100) << 1;
262 
263  *buffer++ = gDigitsLut[d1];
264  *buffer++ = gDigitsLut[d1 + 1];
265  *buffer++ = gDigitsLut[d2];
266  *buffer++ = gDigitsLut[d2 + 1];
267  *buffer++ = gDigitsLut[d3];
268  *buffer++ = gDigitsLut[d3 + 1];
269  *buffer++ = gDigitsLut[d4];
270  *buffer++ = gDigitsLut[d4 + 1];
271  *buffer++ = gDigitsLut[d5];
272  *buffer++ = gDigitsLut[d5 + 1];
273  *buffer++ = gDigitsLut[d6];
274  *buffer++ = gDigitsLut[d6 + 1];
275  *buffer++ = gDigitsLut[d7];
276  *buffer++ = gDigitsLut[d7 + 1];
277  *buffer++ = gDigitsLut[d8];
278  *buffer++ = gDigitsLut[d8 + 1];
279  }
280 
281  *buffer = '\0';
282  }
283 
284  inline void i64toa(char* buffer, int64_t value) {
285  uint64_t u = static_cast<uint64_t>(value);
286  if (value < 0) {
287  *buffer++ = '-';
288  u = ~u + 1;
289  }
290 
291  u64toa(buffer, u);
292  }
293 
294 }
void i64toa(char *buffer, int64_t value)
Definition: uint_to_char.h:284
void u32toa(char *buffer, uint32_t value)
Definition: uint_to_char.h:45
void i32toa(char *buffer, int32_t value)
Definition: uint_to_char.h:117
void u64toa(char *buffer, uint64_t value)
Definition: uint_to_char.h:127