Skip to content

Commit daae3e1

Browse files
committed
Fix u2985907
1 parent 96465f9 commit daae3e1

File tree

2 files changed

+162
-134
lines changed

2 files changed

+162
-134
lines changed

src/int-benchmark.cc

Lines changed: 2 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -21,139 +21,7 @@
2121
#include <vector>
2222

2323
#include "itostr.cc"
24-
25-
// The method by StackOverflow user
26-
// https://stackoverflow.com/users/2985907/user2985907 sometimes incorrectly
27-
// attributed to jiaendu: https://stackoverflow.com/a/19944488/471164
28-
inline int u2985907_utoa10(unsigned int value, char* str) {
29-
#define JOIN(N) \
30-
N "0", N "1", N "2", N "3", N "4", N "5", N "6", N "7", N "8", N "9"
31-
32-
#define JOIN2(N) \
33-
JOIN(N "0"), JOIN(N "1"), JOIN(N "2"), JOIN(N "3"), JOIN(N "4"), \
34-
JOIN(N "5"), JOIN(N "6"), JOIN(N "7"), JOIN(N "8"), JOIN(N "9")
35-
36-
#define JOIN3(N) \
37-
JOIN2(N "0"), JOIN2(N "1"), JOIN2(N "2"), JOIN2(N "3"), JOIN2(N "4"), \
38-
JOIN2(N "5"), JOIN2(N "6"), JOIN2(N "7"), JOIN2(N "8"), JOIN2(N "9")
39-
40-
#define JOIN4 \
41-
JOIN3("0"), JOIN3("1"), JOIN3("2"), JOIN3("3"), JOIN3("4"), JOIN3("5"), \
42-
JOIN3("6"), JOIN3("7"), JOIN3("8"), JOIN3("9")
43-
44-
#define JOIN5(N) \
45-
JOIN(N), JOIN(N "1"), JOIN(N "2"), JOIN(N "3"), JOIN(N "4"), JOIN(N "5"), \
46-
JOIN(N "6"), JOIN(N "7"), JOIN(N "8"), JOIN(N "9")
47-
48-
#define JOIN6 \
49-
JOIN5(""), JOIN2("1"), JOIN2("2"), JOIN2("3"), JOIN2("4"), JOIN2("5"), \
50-
JOIN2("6"), JOIN2("7"), JOIN2("8"), JOIN2("9")
51-
52-
#define F(N) ((N) >= 100 ? 3 : (N) >= 10 ? 2 : 1)
53-
54-
#define F10(N) \
55-
F(N), F(N + 1), F(N + 2), F(N + 3), F(N + 4), F(N + 5), F(N + 6), F(N + 7), \
56-
F(N + 8), F(N + 9)
57-
58-
#define F100(N) \
59-
F10(N), F10(N + 10), F10(N + 20), F10(N + 30), F10(N + 40), F10(N + 50), \
60-
F10(N + 60), F10(N + 70), F10(N + 80), F10(N + 90)
61-
62-
static const short offsets[] = {F100(0), F100(100), F100(200), F100(300),
63-
F100(400), F100(500), F100(600), F100(700),
64-
F100(800), F100(900)};
65-
66-
static const char table1[][4] = {JOIN("")};
67-
static const char table2[][4] = {JOIN2("")};
68-
static const char table3[][4] = {JOIN3("")};
69-
static const char table4[][8] = {JOIN4};
70-
static const char table5[][4] = {JOIN6};
71-
72-
#undef JOIN
73-
#undef JOIN2
74-
#undef JOIN3
75-
#undef JOIN4
76-
#undef F
77-
#undef F10
78-
#undef F100
79-
80-
char* wstr;
81-
#if (_WIN64 || __x86_64__ || __ppc64__)
82-
uint64_t remains[2];
83-
#else
84-
uint32_t remains[2];
85-
#endif
86-
unsigned int v2;
87-
88-
if (value >= 100000000) {
89-
#if (_WIN64 || __x86_64__ || __ppc64__)
90-
remains[0] = (((uint64_t)value * (uint64_t)3518437209) >> 45);
91-
remains[1] = (((uint64_t)value * (uint64_t)2882303762) >> 58);
92-
#else
93-
remains[0] = value / 10000;
94-
remains[1] = value / 100000000;
95-
#endif
96-
v2 = remains[1];
97-
remains[1] = remains[0] - remains[1] * 10000;
98-
remains[0] = value - remains[0] * 10000;
99-
if (v2 >= 10) {
100-
memcpy(str, table5[v2], 2);
101-
str += 2;
102-
memcpy(str, table4[remains[1]], 4);
103-
str += 4;
104-
memcpy(str, table4[remains[0]], 4);
105-
return 10;
106-
} else {
107-
*(char*)str = v2 + '0';
108-
str += 1;
109-
memcpy(str, table4[remains[1]], 4);
110-
str += 4;
111-
memcpy(str, table4[remains[0]], 4);
112-
return 9;
113-
}
114-
} else if (value >= 10000) {
115-
#if (_WIN64 || __x86_64__ || __ppc64__)
116-
v2 = (((uint64_t)value * (uint64_t)3518437209) >> 45);
117-
#else
118-
v2 = value / 10000;
119-
#endif
120-
remains[0] = value - v2 * 10000;
121-
if (v2 >= 1000) {
122-
memcpy(str, table4[v2], 4);
123-
str += 4;
124-
memcpy(str, table4[remains[0]], 4);
125-
return 8;
126-
} else {
127-
wstr = str;
128-
memcpy(wstr, table5[v2], 4);
129-
wstr += offsets[v2];
130-
memcpy(wstr, table4[remains[0]], 4);
131-
wstr += 4;
132-
return (wstr - str);
133-
}
134-
} else {
135-
if (value >= 1000) {
136-
memcpy(str, table4[value], 4);
137-
return 4;
138-
} else if (value >= 100) {
139-
memcpy(str, table3[value], 3);
140-
return 3;
141-
} else if (value >= 10) {
142-
memcpy(str, table2[value], 2);
143-
return 2;
144-
} else {
145-
*(char*)str = *(char*)table1[value];
146-
return 1;
147-
}
148-
}
149-
}
150-
151-
int u2985907_itoa10(int value, char* str) {
152-
if (value < 0) { *(str++) = '-';
153-
return u2985907_utoa10(-value, str) + 1;
154-
}
155-
else return u2985907_utoa10(value, str);
156-
}
24+
#include "u2985907.h"
15725

15826
// Integer to string converter by Alf P. Steinbach modified to return a pointer
15927
// past the end of the output to avoid calling strlen.
@@ -465,7 +333,7 @@ void u2985907(benchmark::State& state) {
465333
for (auto s : state) {
466334
for (auto value : data) {
467335
char buffer[12];
468-
unsigned size = u2985907_itoa10(value, buffer);
336+
unsigned size = so_u2985907::ufast_itoa10(value, buffer);
469337
dc.add({buffer, size});
470338
}
471339
}

src/u2985907.h

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#include <stdint.h>
2+
3+
// The integer to string conversion method by StackOverflow user
4+
// https://stackoverflow.com/users/2985907/user2985907 sometimes incorrectly
5+
// attributed to jiaendu: https://stackoverflow.com/a/19944488/471164
6+
// Includes fixes from
7+
// https://gist.github.com/cpei-avalara/8aedf14f5618852be2cff4de267d497c.
8+
namespace so_u2985907 {
9+
10+
inline int ufast_utoa10(unsigned int value, char* str)
11+
{
12+
#define JOIN(N) \
13+
N "0", N "1", N "2", N "3", N "4", N "5", N "6", N "7", N "8", N "9" \
14+
15+
#define JOIN2(N) \
16+
JOIN(N "0"), JOIN(N "1"), JOIN(N "2"), JOIN(N "3"), JOIN(N "4"), \
17+
JOIN(N "5"), JOIN(N "6"), JOIN(N "7"), JOIN(N "8"), JOIN(N "9") \
18+
19+
#define JOIN3(N) \
20+
JOIN2(N "0"), JOIN2(N "1"), JOIN2(N "2"), JOIN2(N "3"), JOIN2(N "4"), \
21+
JOIN2(N "5"), JOIN2(N "6"), JOIN2(N "7"), JOIN2(N "8"), JOIN2(N "9") \
22+
23+
#define JOIN4 \
24+
JOIN3("0"), JOIN3("1"), JOIN3("2"), JOIN3("3"), JOIN3("4"), \
25+
JOIN3("5"), JOIN3("6"), JOIN3("7"), JOIN3("8"), JOIN3("9") \
26+
27+
#define JOIN5(N) \
28+
JOIN(N), JOIN(N "1"), JOIN(N "2"), JOIN(N "3"), JOIN(N "4"), \
29+
JOIN(N "5"), JOIN(N "6"), JOIN(N "7"), JOIN(N "8"), JOIN(N "9") \
30+
31+
#define JOIN6 \
32+
JOIN5(""), JOIN2("1"), JOIN2("2"), JOIN2("3"), JOIN2("4"), \
33+
JOIN2("5"), JOIN2("6"), JOIN2("7"), JOIN2("8"), JOIN2("9") \
34+
35+
#define F(N) ((N) >= 100 ? 3 : (N) >= 10 ? 2 : 1)
36+
37+
#define F10(N) \
38+
F(N), F(N + 1), F(N + 2), F(N + 3), F(N + 4), \
39+
F(N + 5), F(N + 6), F(N + 7), F(N + 8), F(N + 9) \
40+
41+
#define F100(N) \
42+
F10(N), F10(N + 10), F10(N + 20), F10(N + 30), \
43+
F10(N + 40), F10(N + 50), F10(N + 60), F10(N + 70),\
44+
F10(N + 80), F10(N + 90) \
45+
46+
static const short offsets[] = {
47+
F100( 0), F100(100), F100(200), F100(300), F100(400),
48+
F100(500), F100(600), F100(700), F100(800), F100(900)
49+
};
50+
51+
static const char table1[][4] = { JOIN ("") };
52+
static const char table2[][4] = { JOIN2("") };
53+
static const char table3[][4] = { JOIN3("") };
54+
static const char table4[][8] = { JOIN4 };
55+
static const char table5[][4] = { JOIN6 };
56+
57+
#undef JOIN
58+
#undef JOIN2
59+
#undef JOIN3
60+
#undef JOIN4
61+
#undef F
62+
#undef F10
63+
#undef F100
64+
65+
char *wstr;
66+
#if (_WIN64 || __x86_64__ || __ppc64__)
67+
uint64_t remains[2];
68+
#else
69+
uint32_t remains[2];
70+
#endif
71+
unsigned int v2;
72+
73+
if (value >= 100000000)
74+
{
75+
#if (_WIN64 || __x86_64__ || __ppc64__)
76+
remains[0] = (((uint64_t)value * (uint64_t)3518437209) >> 45);
77+
remains[1] = (((uint64_t)value * (uint64_t)2882303762) >> 58);
78+
#else
79+
remains[0] = value / 10000;
80+
remains[1] = value / 100000000;
81+
#endif
82+
v2 = remains[1];
83+
remains[1] = remains[0] - remains[1] * 10000;
84+
remains[0] = value - remains[0] * 10000;
85+
if (v2 >= 10)
86+
{
87+
memcpy(str,table5[v2],2);
88+
str += 2;
89+
memcpy(str,table4[remains[1]],4);
90+
str += 4;
91+
memcpy(str,table4[remains[0]],4);
92+
return 10;
93+
}
94+
else
95+
{
96+
*(char *) str = v2 + '0';
97+
str += 1;
98+
memcpy(str,table4[remains[1]],4);
99+
str += 4;
100+
memcpy(str,table4[remains[0]],4);
101+
return 9;
102+
}
103+
}
104+
else if (value >= 10000)
105+
{
106+
#if (_WIN64 || __x86_64__ || __ppc64__)
107+
v2 = (((uint64_t)value * (uint64_t)3518437209 ) >> 45);
108+
#else
109+
v2 = value / 10000;
110+
#endif
111+
remains[0] = value - v2 * 10000;
112+
if (v2 >= 1000)
113+
{
114+
memcpy(str,table4[v2],4);
115+
str += 4;
116+
memcpy(str,table4[remains[0]],4);
117+
return 8;
118+
}
119+
else
120+
{
121+
wstr = str;
122+
memcpy(wstr,table5[v2],4);
123+
wstr += offsets[v2];
124+
memcpy(wstr,table4[remains[0]],4);
125+
wstr += 4;
126+
return (wstr - str);
127+
}
128+
}
129+
else
130+
{
131+
if (value >= 1000)
132+
{
133+
memcpy(str,table4[value],4);
134+
return 4;
135+
}
136+
else if (value >= 100)
137+
{
138+
memcpy(str,table3[value],3);
139+
return 3;
140+
}
141+
else if (value >= 10)
142+
{
143+
memcpy(str,table2[value],2);
144+
return 2;
145+
}
146+
else
147+
{
148+
*(char *) str = *(char *) table1[value];
149+
return 1;
150+
}
151+
}
152+
}
153+
154+
int ufast_itoa10(int value, char* str) {
155+
if (value < 0) { *(str++) = '-';
156+
return ufast_utoa10(-value, str) + 1;
157+
}
158+
else return ufast_utoa10(value, str);
159+
}
160+
} // namespace so_u2985907

0 commit comments

Comments
 (0)