#include <string>
#include <cstdlib>
#include <chrono>
#include <algorithm>
#include <cassert>
#include <climits>
#include <iostream>
void append_Ethon(std::string& s, int value, int radix=10)
{
if(value < 0)
{
s.push_back('-');
value = -value;
}
assert(radix > 1 && radix < 17);
char const* chars = "0123456789abcdef";
char buffer[sizeof(int) * CHAR_BIT];
char* iter = buffer;
while(value >= radix)
{
*iter = chars[value % radix];
value /= radix;
++iter;
}
*iter = chars[value];
s.append(std::reverse_iterator<char*>(iter + 1), std::reverse_iterator<char*>(buffer));
}
void append_Ethon2(std::string& s, int value, int radix=10)
{
if(value < 0)
{
s.push_back('-');
value = -value;
}
assert(radix > 1 && radix < 11);
char buffer[sizeof(int) * CHAR_BIT];
char* iter = buffer;
while(value >= radix)
{
*iter = '0' + value % radix;
value /= radix;
++iter;
}
*iter = '0' + value % radix;
s.append(std::reverse_iterator<char*>(iter + 1), std::reverse_iterator<char*>(buffer));
}
void append_Ethon3(std::string& s, int value)
{
if(value < 0)
{
s.push_back('-');
value = -value;
}
char const* chars =
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
;
char buffer[64];
char* iter = buffer;
while(value >= 100)
{
*iter = chars[value % 100 * 2 + 1];
++iter;
*iter = chars[value % 100 * 2];
value /= 100;
++iter;
}
if(value >= 10)
{
*iter = chars[value * 2];
++iter;
*iter = chars[value * 2 + 1];
++iter;
}
else
{
*iter = '0' + value;
}
s.append(std::reverse_iterator<char*>(iter + 1), std::reverse_iterator<char*>(buffer));
}
void append_Ethon4(std::string& s, int value)
{
if(value < 0)
{
s.push_back('-');
value = -value;
}
char const* chars =
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
;
unsigned size;
if(value >=10000)
{
if(value >=10000000)
{
if(value >=1000000000)
size=10;
else if(value >=100000000)
size=9;
else
size=8;
}
else
{
if(value >=1000000)
size=7;
else if(value >=100000)
size=6;
else
size=5;
}
}
else
{
if(value >=100)
{
if(value >=1000)
size=4;
else
size=3;
}
else
{
if(value >=10)
size=2;
else
size=1;
}
}
s.resize(s.size() + size);
std::reverse_iterator<std::string::iterator> iter( (s.end()) );
while(value >= 100)
{
*iter = chars[value % 100 * 2 + 1];
++iter;
*iter = chars[value % 100 * 2];
value /= 100;
++iter;
}
if(value >= 10)
{
*iter = chars[value * 2];
++iter;
*iter = chars[value * 2 + 1];
++iter;
}
else
{
*iter = '0' + value;
}
}
void append_snprintf(std::string& s, int value)
{
char buffer[64];
snprintf(buffer, 64, "%d", value);
s.append(buffer);
}
void append_tostring(std::string& s, int value)
{
s.append(std::to_string(value));
}
void append_stackoverflow1(std::string& s, int n)
{
const char digit_pairs[201] = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
if(n==0)
{
s += "0";
return;
}
int sign = -(n<0);
unsigned int val = (n^sign)-sign;
int size;
if(val>=10000)
{
if(val>=10000000)
{
if(val>=1000000000)
size=10;
else if(val>=100000000)
size=9;
else
size=8;
}
else
{
if(val>=1000000)
size=7;
else if(val>=100000)
size=6;
else
size=5;
}
}
else
{
if(val>=100)
{
if(val>=1000)
size=4;
else
size=3;
}
else
{
if(val>=10)
size=2;
else
size=1;
}
}
size -= sign;
auto oldSize = s.size();
s.resize(oldSize + size);
char* c = &s[oldSize];
if(sign)
*c='-';
c += size-1;
while(val>=100)
{
int pos = val % 100;
val /= 100;
*(short*)(c-1)=*(short*)(digit_pairs+2*pos);
c-=2;
}
while(val>0)
{
*c--='0' + (val % 10);
val /= 10;
}
}
unsigned const N = 10000000;
int main()
{
using namespace std;
srand(time(0));
vector<int> values( (N) );
generate(values.begin(), values.end(), rand);
// Warmup.
{
string s;
for(unsigned i = 0; i < N; ++i)
append_Ethon(s, values[i]);
cout << "Anti Optimize: " << s.back() << endl;
}
{
string s;
auto start = chrono::high_resolution_clock::now();
for(unsigned i = 0; i < N; ++i)
append_Ethon(s, values[i]);
auto end = chrono::high_resolution_clock::now();
cout << "Ethon (Lookuptable): " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms\n";
cout << "Anti Optimize: " << s.back() << endl;
}
{
string s;
auto start = chrono::high_resolution_clock::now();
for(unsigned i = 0; i < N; ++i)
append_Ethon2(s, values[i]);
auto end = chrono::high_resolution_clock::now();
cout << "Ethon (No Lookuptable): " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms\n";
cout << "Anti Optimize: " << s.back() << endl;
}
{
string s;
auto start = chrono::high_resolution_clock::now();
for(unsigned i = 0; i < N; ++i)
append_Ethon3(s, values[i]);
auto end = chrono::high_resolution_clock::now();
cout << "Ethon (Larger Lookuptable): " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms\n";
cout << "Anti Optimize: " << s.back() << endl;
}
{
string s;
auto start = chrono::high_resolution_clock::now();
for(unsigned i = 0; i < N; ++i)
append_Ethon4(s, values[i]);
auto end = chrono::high_resolution_clock::now();
cout << "Ethon (Larger Lookuptable, no Buffer): " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms\n";
cout << "Anti Optimize: " << s.back() << endl;
}
{
string s;
auto start = chrono::high_resolution_clock::now();
for(unsigned i = 0; i < N; ++i)
append_tostring(s, values[i]);
auto end = chrono::high_resolution_clock::now();
cout << "std::to_string: " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms\n";
cout << "Anti Optimize: " << s.back() << endl;
}
{
string s;
auto start = chrono::high_resolution_clock::now();
for(unsigned i = 0; i < N; ++i)
append_snprintf(s, values[i]);
auto end = chrono::high_resolution_clock::now();
cout << "snprintf: " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms\n";
cout << "Anti Optimize: " << s.back() << endl;
}
{
string s;
auto start = chrono::high_resolution_clock::now();
for(unsigned i = 0; i < N; ++i)
append_stackoverflow1(s, values[i]);
auto end = chrono::high_resolution_clock::now();
cout << "stackoverflow1: " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms\n";
cout << "Anti Optimize: " << s.back() << endl;
}
}