Skip to content

Instantly share code, notes, and snippets.

Created October 27, 2013 08:17
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/7179097 to your computer and use it in GitHub Desktop.
Save anonymous/7179097 to your computer and use it in GitHub Desktop.
C++ Fast Integer To String Conversion
/*
*****************************************************************************
* The C++ Integer To String Conversion Benchmark *
* *
* This benchmark is based on the solutions provided in the following *
* stackoverflow question: *
* *
* http://stackoverflow.com/q/4351371 (Date: 20101204) *
* *
* Title: C++ Performance Challenge - Integer To std::string Conversion *
* *
* 0. sprintf (libc) *
* 1. hopman_fast (Chris Hopman) *
* 2. karma (Boost.Spirit) *
* 3. timo (Timo ???) *
* 4. so (user434507) *
* 5. strtk (Arash Partow) *
* 6. voigt (Richard Benjamin Voigt) *
* *
* *
* RESULTS: *
* Integer To String Test *
* [sprintf] Numbers: 240000000 Time: 58.4877sec Rate: 4103425.8081nums/sec *
* [karma] Numbers: 240000000 Time: 15.8808sec Rate: 15112628.3947nums/sec *
* [strtk] Numbers: 240000000 Time: 5.7537sec Rate: 41712168.1004nums/sec *
* [so ] Numbers: 240000000 Time: 6.7677sec Rate: 35462365.3011nums/sec *
* [timo ] Numbers: 240000000 Time: 8.8778sec Rate: 27033588.5472nums/sec *
* [voigt] Numbers: 240000000 Time: 10.5976sec Rate: 22646661.9538nums/sec *
* [hopman] Numbers: 240000000 Time: 9.7909sec Rate: 24512562.7480nums/sec *
* *
* Details: *
* 0. Intel Xeon W3680 3.3GHz *
* 1. Ubuntu 10.10 (Kernel 2.6.32) *
* 2. GCC 4.8, O2, PGO *
* *
* Note: Copyright of portions of the code below other than StrTk is *
* the purview of its owner. *
* *
*****************************************************************************
*/
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <string>
#include <iterator>
#include "strtk.hpp"
#include <boost/lexical_cast.hpp>
//Note: Define USE_SPIRIT to include Karma (requires Boost 1.45+)
#define USE_SPIRIT
#ifdef USE_SPIRIT
#define INCLUDE_KARMA
#include <boost/spirit/include/karma.hpp>
#endif
void print_mode(const std::string& mode)
{
static const std::size_t test_mode_length = sizeof("[sprintf]");
printf("%s", strtk::text::left_align(test_mode_length, ' ', mode).c_str());
fflush(stdout);
}
#define enable_test_type01
#define enable_test_type02
#define enable_test_type03
static const int randval[] =
{
936116, 369532, 453755, -72860, 209713, 268347, 435278, -360266, -416287, -182064,
-644712, 944969, 640463, -366588, 471577, -69401, -744294, -505829, 923883, 831785,
-601136, -636767, -437054, 591718, 100758, 231907, -719038, 973540, -605220, 506659,
-871653, 462533, 764843, -919138, 404305, -630931, -288711, -751454, -173726, -718208,
432689, -281157, 360737, 659827, 19174, -376450, 769984, -858198, 439127, 734703,
-683426, 7, 386135, 186997, -643900, -744422, -604708, -629545, 42313, -933592,
-635566, 182308, 439024, -367219, -73924, -516649, 421935, -470515, 413507, -78952,
-427917, -561158, 737176, 94538, 572322, 405217, 709266, -357278, -908099, -425447,
601119, 750712, -862285, -177869, 900102, 384877, 157859, -641680, 503738, -702558,
278225, 463290, 268378, -212840, 580090, 347346, -473985, -950968, -114547, -839893,
-738032, -789424, 409540, 493495, 432099, 119755, 905004, -174834, 338266, 234298,
74641, -965136, -754593, 685273, 466924, 920560, 385062, 796402, -67229, 994864,
376974, 299869, -647540, -128724, 469890, -163167, -547803, -743363, 486463, -621028,
612288, 27459, -514224, 126342, -66612, 803409, -777155, -336453, -284002, 472451,
342390, -163630, 908356, -456147, -825607, 268092, -974715, 287227, 227890, -524101,
616370, -782456, 922098, -624001, -813690, 171605, -192962, 796151, 707183, -95696,
-23163, -721260, 508892, 430715, 791331, 482048, -996102, 863274, 275406, -8279,
-556239, -902076, 268647, -818565, 260069, -798232, -172924, -566311, -806503, -885992,
813969, -78468, 956632, 304288, 494867, -508784, 381751, 151264, 762953, 76352,
594902, 375424, 271700, -743062, 390176, 924237, 772574, 676610, 435752, -153847,
3959, -971937, -294181, -538049, -344620, -170136, 19120, -703157, 868152, -657961,
-818631, 219015, -872729, -940001, -956570, 880727, -345910, 942913, -942271, -788115,
225294, 701108, -517736, -416071, 281940, 488730, 942698, 711494, 838382, -892302,
-533028, 103052, 528823, 901515, 949577, 159364, 718227, -241814, -733661, -462928,
-495829, 165170, 513580, -629188, -509571, -459083, 198437, 77198, -644612, 811276,
-422298, -860842, -52584, 920369, 686424, -530667, -243476, 49763, 345866, -411960,
-114863, 470810, -302860, 683007, -509080, 2, -174981, -772163, -48697, 447770,
-268246, 213268, 269215, 78810, -236340, -639140, -864323, 505113, -986569, -325215,
541859, 163070, -819998, -645161, -583336, 573414, 696417, -132375, 3, -294501,
320435, 682591, 840008, 351740, 426951, 609354, 898154, -943254, 227321, -859793,
-727993, 44137, -497965, -782239, 14955, -746080, -243366, 9837, -233083, 606507,
-995864, -615287, -994307, 602715, 770771, -315040, 610860, 446102, -307120, 710728,
-590392, -230474, -762625, -637525, 134963, -202700, -766902, -985541, 218163, 682009,
926051, 525156, -61195, 403211, -810098, 245539, -431733, 179998, -806533, 745943,
447597, 131973, -187130, 826019, 286107, -937230, -577419, 20254, 681802, -340500,
323080, 266283, -667617, 309656, 416386, 611863, 759991, -534257, 523112, -634892,
-169913, -204905, -909867, -882185, -944908, 741811, -717675, 967007, -317396, 407230,
-412805, 792905, 994873, 744793, -456797, 713493, 355232, 116900, -945199, 880539,
342505, -580824, -262273, 982968, -349497, -735488, 311767, -455191, 570918, 389734,
-958386, 10262, -99267, 155481, 304210, 204724, 704367, -144893, -233664, -671441,
896849, 408613, 762236, 322697, 981321, 688476, 13663, -970704, -379507, 896412,
977084, 348869, 875948, 341348, 318710, 512081, 6163, 669044, 833295, 811883,
708756, -802534, -536057, 608413, -389625, -694603, 541106, -110037, 720322, -540581,
645420, 32980, 62442, 510157, -981870, -87093, -325960, -500494, -718291, -67889,
991501, 374804, 769026, -978869, 294747, 714623, 413327, -199164, 671368, 804789,
-362507, 798196, -170790, -568895, -869379, 62020, -316693, -837793, 644994, -39341,
-417504, -243068, -957756, 99072, 622234, -739992, 225668, 8863, -505910, 82483,
-559244, 241572, 1315, -36175, -54990, 376813, -11, 162647, -688204, -486163,
-54934, -197470, 744223, -762707, 732540, 996618, 351561, -445933, -898491, 486531,
456151, 15276, 290186, -817110, -52995, 313046, -452533, -96267, 94470, -500176,
-818026, -398071, -810548, -143325, -819741, 1338, -897676, -101577, -855445, 37309,
285742, 953804, -777927, -926962, -811217, -936744, -952245, -802300, -490188, -964953,
-552279, 329142, -570048, -505756, 682898, -381089, -14352, 175138, 152390, -582268,
-485137, 717035, 805329, 239572, -730409, 209643, -184403, -385864, 675086, 819648,
629058, -527109, -488666, -171981, 532788, 552441, 174666, 984921, 766514, 758787,
716309, 338801, -978004, -412163, 876079, -734212, 789557, -160491, -522719, 56644,
-991, -286038, -53983, 663740, 809812, 919889, -717502, -137704, 220511, 184396,
-825740, -588447, 430870, 124309, 135956, 558662, -307087, -788055, -451328, 812260,
931601, 324347, -482989, -117858, -278861, 189068, -172774, 929057, 293787, 198161,
-342386, -47173, 906555, -759955, -12779, 777604, -97869, 899320, 927486, -25284,
-848550, 259450, -485856, -17820, 88, 171400, 235492, -326783, -340793, 886886,
112428, -246280, 5979, 648444, -114982, 991013, -56489, -9497, 419706, 632820,
-341664, 393926, -848977, -22538, 257307, 773731, -905319, 491153, 734883, -868212,
-951053, 644458, -580758, 764735, 584316, 297077, 28852, -397710, -953669, 201772,
879050, -198237, -588468, 448102, -116837, 770007, -231812, 642906, -582166, -885828,
9, 305082, -996577, 303559, 75008, -772956, -447960, 599825, -295552, 870739,
-386278, -950300, 485359, -457081, 629461, -850276, 550496, -451755, -620841, -11766,
-950137, 832337, 28711, -273398, -507197, 91921, -271360, -705991, -753220, -388968,
967945, 340434, -320883, -662793, -554617, -574568, 477946, -6148, -129519, 689217,
920020, -656315, -974523, -212525, 80921, -612532, 645096, 545655, 655713, -591631,
-307385, -816688, -618823, -113713, 526430, 673063, 735916, -809095, -850417, 639004,
432281, -388185, 270708, 860146, -39902, -786157, -258180, -246169, -966720, -264957,
548072, -306010, -57367, -635665, 933824, 70553, -989936, -488741, 72411, -452509,
529831, 956277, 449019, -577850, -360986, -803418, 48833, 296073, 203430, 609591,
715483, 470964, 658106, -718254, -96424, 790163, 334739, 181070, -373578, 5,
-435088, 329841, 330939, -256602, 394355, 912412, 231910, 927278, -661933, 788539,
-769664, -893274, -96856, 298205, 901043, -608122, -527430, 183618, -553963, -35246,
-393924, 948832, -483198, 594501, 35460, -407007, 93494, -336881, -634072, 984205,
-812161, 944664, -31062, 753872, 823933, -69566, 50445, 290147, 85134, 34706,
551902, 405202, -991246, -84642, 154341, 316432, -695101, -651588, -5030, 137564,
-294665, 332541, 528307, -90572, -344923, 523766, -758498, -968047, 339028, 494578,
593129, -725773, 31834, -718406, -208638, 159665, -2043, 673344, -442767, 75816,
755442, 769257, -158730, -410272, 691688, 589550, -878398, -184121, 460679, 346312,
294163, -544602, 653308, 254167, -276979, 52073, -892684, 887653, -41222, 983065,
-68258, -408799, -99069, -674069, -863635, -32890, 622757, -743862, 40872, -4837,
-967228, 522370, -903951, -818669, 524459, 514702, 925801, 20007, -299229, 579348,
626021, 430089, 348139, -562692, -607728, -130606, -928451, -424793, -458647, -448892,
-312230, 143337, 109746, 880042, -339658, -785614, 938995, 540916, 118429, 661351,
-402967, 404729, -40918, -976535, 743230, 713110, 440182, -381314, -499252, 74613,
193652, 912717, 491323, 583633, 324691, 459397, 281253, 195540, -2764, -888651,
892449, 132663, -478373, -430002, -314551, 527826, 247165, 557966, 554778, 481531,
-946634, 431685, -769059, -348371, 174046, 184597, -354867, 584422, 227390, -850397,
-542924, -849093, -737769, 325359, 736314, 269101, 767940, 674809, 81413, -447458,
445076, 189072, 906218, 502688, -718476, -863827, -731381, 100660, 623249, 710008,
572060, 922203, 685740, 55096, 263394, -243695, -353910, -516788, 388471, 455165,
844103, -643772, 363976, 268875, -899450, 104470, 104029, -238874, -274659, 732969,
-676443, 953291, -916289, -861849, -242344, 958083, -479593, -970395, 799831, 277841,
-243236, -283462, -201510, 166263, -259105, -575706, 878926, 891064, 895297, 655262,
-34807, -809833, -89281, 342585, 554920, 1, 902141, -333425, 139703, 852318,
-618438, 329498, -932596, -692836, -513372, 733656, -523411, 85779, 500478, -682697,
-502836, 138776, 156341, -420037, -557964, -556378, 710993, -50383, -877159, 916334,
132996, 583516, -603392, -111615, -12288, -780214, 476780, 123327, 137607, 519956,
745837, 17358, -158581, -53490
};
static const int max_i2s = 80000000;
void sprintf_lexical_cast_test_i2s()
{
print_mode("[sprintf]");
std::string s;
s.reserve(32);
std::size_t total_length = 0;
strtk::util::timer t;
t.start();
for (int i = (-max_i2s / 2); i < (max_i2s / 2); ++i)
{
#ifdef enable_test_type01
s.resize(sprintf(const_cast<char*>(s.c_str()),"%d",((i & 1) ? i : -i)));
total_length += s.size();
#endif
#ifdef enable_test_type02
s.resize(sprintf(const_cast<char*>(s.c_str()),"%d",max_i2s + i));
total_length += s.size();
#endif
#ifdef enable_test_type03
s.resize(sprintf(const_cast<char*>(s.c_str()),"%d",randval[(max_i2s + i) & 1023]));
total_length += s.size();
#endif
}
t.stop();
printf("Numbers:%10lu\tTotal:%12lu\tTime:%8.4fsec\tRate:%14.4fnums/sec\n",
static_cast<unsigned long>(3 * max_i2s),
static_cast<unsigned long>(total_length),
t.time(),
(3.0 * max_i2s) / t.time());
}
void boost_lexical_cast_test_i2s()
{
print_mode("[boost]");
std::string s;
s.reserve(32);
std::size_t total_length = 0;
strtk::util::timer t;
t.start();
for (int i = (-max_i2s / 2); i < (max_i2s / 2); ++i)
{
#ifdef enable_test_type01
s = boost::lexical_cast<std::string>(((i & 1) ? i : -i));
total_length += s.size();
#endif
#ifdef enable_test_type02
s = boost::lexical_cast<std::string>(max_i2s + i);
total_length += s.size();
#endif
#ifdef enable_test_type03
s = boost::lexical_cast<std::string>(randval[(max_i2s + i) & 1023]);
total_length += s.size();
#endif
}
t.stop();
printf("Numbers:%10lu\tTotal:%12lu\tTime:%8.4fsec\tRate:%14.4fnums/sec\n",
static_cast<unsigned long>(3 * max_i2s),
static_cast<unsigned long>(total_length),
t.time(),
(3.0 * max_i2s) / t.time());
}
#ifdef INCLUDE_KARMA
#include <boost/spirit/include/karma.hpp>
inline bool karma_int_to_string(const int& value, std::string& str)
{
using namespace boost::spirit;
using boost::spirit::karma::generate;
char buffer[16];
char* x = buffer;
if (!generate(x, int_, value))
return false;
str.assign(buffer, x - buffer);
return true;
}
void karma_lexical_cast_test_i2s()
{
print_mode("[karma]");
std::string s;
s.reserve(32);
std::size_t total_length = 0;
strtk::util::timer t;
t.start();
for (int i = (-max_i2s / 2); i < (max_i2s / 2); ++i)
{
#ifdef enable_test_type01
karma_int_to_string(((i & 1) ? i : -i),s);
total_length += s.size();
#endif
#ifdef enable_test_type02
karma_int_to_string(max_i2s + i,s);
total_length += s.size();
#endif
#ifdef enable_test_type03
karma_int_to_string(randval[(max_i2s + i) & 1023],s);
total_length += s.size();
#endif
}
t.stop();
printf("Numbers:%10lu\tTotal:%12lu\tTime:%8.4fsec\tRate:%14.4fnums/sec\n",
static_cast<unsigned long>(3 * max_i2s),
static_cast<unsigned long>(total_length),
t.time(),
(3.0 * max_i2s) / t.time());
}
#else
void karma_lexical_cast_test_i2s(){}
#endif
void strtk_lexical_cast_test_i2s()
{
print_mode("[strtk]");
std::string s;
s.reserve(32);
std::size_t total_length = 0;
strtk::util::timer t;
t.start();
for (int i = (-max_i2s / 2); i < (max_i2s / 2); ++i)
{
#ifdef enable_test_type01
strtk::type_to_string(((i & 1) ? i : -i),s);
total_length += s.size();
#endif
#ifdef enable_test_type02
strtk::type_to_string(max_i2s + i,s);
total_length += s.size();
#endif
#ifdef enable_test_type03
strtk::type_to_string(randval[(max_i2s + i) & 1023],s);
total_length += s.size();
#endif
}
t.stop();
printf("Numbers:%10lu\tTotal:%12lu\tTime:%8.4fsec\tRate:%14.4fnums/sec\n",
static_cast<unsigned long>(3 * max_i2s),
static_cast<unsigned long>(total_length),
t.time(),
(3.0 * max_i2s) / t.time());
}
namespace so
{
std::string& itostr(int n, std::string& s)
{
if (n == 0)
{
s = "0";
return s;
}
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;
}
}
s.resize(-sign + size);
char* c = &s[0];
if (sign)
*c++='-';
char* d = c + size - 1;
while(val > 0)
{
*d-- = '0' + (val % 10);
val /= 10;
}
return s;
}
}
void so_lexical_cast_test_i2s()
{
print_mode("[so ]");
std::string s;
s.reserve(32);
std::size_t total_length = 0;
strtk::util::timer t;
t.start();
for (int i = (-max_i2s / 2); i < (max_i2s / 2); ++i)
{
#ifdef enable_test_type01
so::itostr(((i & 1) ? i : -i),s);
total_length += s.size();
#endif
#ifdef enable_test_type02
so::itostr(max_i2s + i,s);
total_length += s.size();
#endif
#ifdef enable_test_type03
so::itostr(randval[(max_i2s + i) & 1023],s);
total_length += s.size();
#endif
}
t.stop();
printf("Numbers:%10lu\tTotal:%12lu\tTime:%8.4fsec\tRate:%14.4fnums/sec\n",
static_cast<unsigned long>(3 * max_i2s),
static_cast<unsigned long>(total_length),
t.time(),
(3.0 * max_i2s) / t.time());
}
const char digit_pairs[201] = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
static const int BUFFER_SIZE = 11;
std::string timo_itostr(int val)
{
char buf[BUFFER_SIZE];
char *it = &buf[BUFFER_SIZE - 2];
if (val >= 0)
{
int div = val / 100;
while(div)
{
memcpy(it,&digit_pairs[2 * (val - div * 100)],2);
val = div;
it -= 2;
div = val / 100;
}
memcpy(it,&digit_pairs[2 * val],2);
if (val < 10)
it++;
}
else
{
int div = val / 100;
while(div)
{
memcpy(it,&digit_pairs[-2 * (val - div * 100)],2);
val = div;
it -= 2;
div = val / 100;
}
memcpy(it,&digit_pairs[-2 * val],2);
if (val <= -10)
it--;
*it = '-';
}
return std::string(it,&buf[BUFFER_SIZE] - it);
}
void timo_lexical_cast_test_i2s()
{
print_mode("[timo ]");
std::string s;
s.reserve(32);
std::size_t total_length = 0;
strtk::util::timer t;
t.start();
for (int i = (-max_i2s / 2); i < (max_i2s / 2); ++i)
{
#ifdef enable_test_type01
s = timo_itostr(((i & 1) ? i : -i));
total_length += s.size();
#endif
#ifdef enable_test_type02
s = timo_itostr(max_i2s + i);
total_length += s.size();
#endif
#ifdef enable_test_type03
s = timo_itostr(randval[(max_i2s + i) & 1023]);
total_length += s.size();
#endif
}
t.stop();
printf("Numbers:%10lu\tTotal:%12lu\tTime:%8.4fsec\tRate:%14.4fnums/sec\n",
static_cast<unsigned long>(3 * max_i2s),
static_cast<unsigned long>(total_length),
t.time(),
(3.0 * max_i2s) / t.time());
}
namespace voigt
{
template<typename T>
struct assert_integral
{
enum { value = (T)0.5 };
char test[1 - 4 * value];
};
template<typename T, bool is_signed, size_t bits>
struct itostr_impl { };
template<typename T, bool is_signed>
struct itostr_impl<T,is_signed,8>
{
static std::string cvt(T val)
{
std::string retval(5, '\0');
int i = 0;
char ch = 0;
if (is_signed)
{
if (val < 0)
{
retval[i] = '-';
++i;
if (val <= -100)
{
ch = '1';
val += 100;
}
val = -val;
}
else if (val >= 100)
{
ch |= '1';
val -= 100;
}
}
else
{
if (val >= 200)
{
ch |= '2';
val -= 200;
}
else if (val >= 100)
{
ch |= '1';
val -= 100;
}
}
if (ch)
{
retval[i] = ch;
++i;
ch = '0';
}
if (val >= 80)
{
ch |= '8';
val -= 80;
}
else if (val >= 40)
{
ch |= '4';
val -= 40;
}
if (val >= 20)
{
ch |= '2';
val -= 20;
}
if (val >= 10)
{
ch |= '1';
val -= 10;
}
if (ch)
{
retval[i] = ch;
++i;
}
retval[i] = '0' + val;
retval.resize(i+1);
return retval;
}
};
template<typename T, bool is_signed>
struct itostr_impl<T,is_signed,16>
{
static std::string cvt(T val)
{
std::string retval(7, '\0');
int i = 0;
char ch = 0;
if (is_signed)
{
if (val < 0)
{
retval[i] = '-';
++i;
if (val <= -20000)
{
ch = '2';
val += 20000;
}
val = -val;
}
else if (val >= 20000)
{
ch |= '2';
val -= 20000;
}
}
else
{
if (val >= 40000)
{
ch |= '4';
val -= 40000;
}
else if (val >= 20000)
{
ch |= '2';
val -= 20000;
}
}
if (val >= 10000)
{
ch |= '1';
val -= 10000;
}
if (ch)
{
retval[i] = ch;
++i;
ch = '0';
}
if (val >= 8000)
{
ch |= '8';
val -= 8000;
}
else if (val >= 4000)
{
ch |= '4';
val -= 4000;
}
if (val >= 2000)
{
ch |= '2';
val -= 2000;
}
if (val >= 1000)
{
ch |= '1';
val -= 1000;
}
if (ch)
{
retval[i] = ch;
++i;
ch = '0';
}
if (val >= 800)
{
ch |= '8';
val -= 800;
}
else if (val >= 400)
{
ch |= '4';
val -= 400;
}
if (val >= 200)
{
ch |= '2';
val -= 200;
}
if (val >= 100)
{
ch |= '1';
val -= 100;
}
if (ch)
{
retval[i] = ch;
++i;
ch = '0';
}
if (val >= 80)
{
ch |= '8';
val -= 80;
}
else if (val >= 40)
{
ch |= '4';
val -= 40;
}
if (val >= 20)
{
ch |= '2';
val -= 20;
}
if (val >= 10)
{
ch |= '1';
val -= 10;
}
if (ch)
{
retval[i] = ch;
++i;
}
retval[i] = '0' + val;
retval.resize(i+1);
return retval;
}
};
const char digit_pair_table[201] = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
template<typename T, bool is_signed>
struct itostr_impl<T,is_signed,32>
{
static std::string cvt(T val)
{
char buf[11], ch = 0;
char* start = buf + 1;
char* p = start;
bool neg = val < 0;
int digit;
if (is_signed)
{
if (neg)
{
if (val <= -2000000000)
{
ch = '2';
val += 2000000000;
}
val = -val;
}
else if (val >= 2000000000)
{
ch = '2';
val -= 2000000000;
}
}
else
{
if (val >= 4000000000U)
{
ch |= '4';
val -= 4000000000U;
}
else if (val >= 2000000000)
{
ch |= '2';
val -= 2000000000;
}
}
if (val >= 1000000000)
{
ch |= '1';
val -= 1000000000;
}
if (ch)
{
*p = ch;
++p;
ch = '0';
}
else if (val < 1000)
{
if (val < 10) goto d1;
if (val < 1000) goto d10;
}
else
{
if (val < 100000) goto d1000;
if (val < 10000000) goto d100000;
}
#define DO_PAIR(n) \
d##n: \
digit = val / n; \
*(p++) = digit_pair_table[digit * 2]; \
*(p++) = digit_pair_table[digit * 2 + 1]; \
val -= n * digit;
DO_PAIR(10000000);
DO_PAIR(100000);
DO_PAIR(1000);
DO_PAIR(10);
d1:
*p = '0' | static_cast<char>(val);
if (p > start && *start == '0') ++start;
if (is_signed && neg) *--start = '-';
return std::string(start, p + 1 - start);
}
};
template<typename T>
std::string itostr(T val)
{
sizeof(assert_integral<T>);
return itostr_impl<T,((T)-1) < 0,sizeof(T) * CHAR_BIT>::cvt(val);
}
}
void voigt_lexical_cast_test_i2s()
{
print_mode("[voigt]");
std::string s;
s.reserve(32);
std::size_t total_length = 0;
strtk::util::timer t;
t.start();
for (int i = (-max_i2s / 2); i < (max_i2s / 2); ++i)
{
#ifdef enable_test_type01
s = voigt::itostr(((i & 1) ? i : -i));
total_length += s.size();
#endif
#ifdef enable_test_type02
s = voigt::itostr(max_i2s + i);
total_length += s.size();
#endif
#ifdef enable_test_type03
s = voigt::itostr(randval[(max_i2s + i) & 1023]);
total_length += s.size();
#endif
}
t.stop();
printf("Numbers:%10lu\tTotal:%12lu\tTime:%8.4fsec\tRate:%14.4fnums/sec\n",
static_cast<unsigned long>(3 * max_i2s),
static_cast<unsigned long>(total_length),
t.time(),
(3.0 * max_i2s) / t.time());
}
namespace hopman_fast
{
struct itostr_helper
{
static unsigned out[10000];
itostr_helper()
{
for (int i = 0; i < 10000; i++)
{
unsigned v = i;
char * o = (char*)(out + i);
o[3] = v % 10 + '0';
o[2] = (v % 100) / 10 + '0';
o[1] = static_cast<char>((v % 1000) / 100) + '0';
o[0] = static_cast<char>((v % 10000) / 1000);
if (o[0]) o[0] |= 0x30;
else if (o[1] != '0') o[0] |= 0x20;
else if (o[2] != '0') o[0] |= 0x10;
else o[0] |= 0x00;
}
}
};
unsigned itostr_helper::out[10000];
itostr_helper hlp_init;
template <typename T>
std::string itostr(T o)
{
typedef itostr_helper hlp;
unsigned blocks[3], *b = blocks + 2;
blocks[0] = o < 0 ? ~o + 1 : o;
blocks[2] = blocks[0] % 10000; blocks[0] /= 10000;
blocks[2] = hlp::out[blocks[2]];
if (blocks[0])
{
blocks[1] = blocks[0] % 10000; blocks[0] /= 10000;
blocks[1] = hlp::out[blocks[1]];
blocks[2] |= 0x30303030;
b--;
}
if (blocks[0])
{
blocks[0] = hlp::out[blocks[0] % 10000];
blocks[1] |= 0x30303030;
b--;
}
char* f = ((char*)b);
f += 3 - (*f >> 4);
char* str = (char*)blocks;
if (o < 0) *--f = '-';
return std::string(f, (str + 12) - f);
}
}
void hopman_fast_lexical_cast_test_i2s()
{
print_mode("[hopman]");
std::string s;
s.reserve(32);
std::size_t total_length = 0;
strtk::util::timer t;
t.start();
for (int i = (-max_i2s / 2); i < (max_i2s / 2); ++i)
{
#ifdef enable_test_type01
s = hopman_fast::itostr(((i & 1) ? i : -i));
total_length += s.size();
#endif
#ifdef enable_test_type02
s = hopman_fast::itostr(max_i2s + i);
total_length += s.size();
#endif
#ifdef enable_test_type03
s = hopman_fast::itostr(randval[(max_i2s + i) & 1023]);
total_length += s.size();
#endif
}
t.stop();
printf("Numbers:%10lu\tTotal:%12lu\tTime:%8.4fsec\tRate:%14.4fnums/sec\n",
static_cast<unsigned long>(3 * max_i2s),
static_cast<unsigned long>(total_length),
t.time(),
(3.0 * max_i2s) / t.time());
}
int main()
{
std::cout << "Integer To String Test" << std::endl;
sprintf_lexical_cast_test_i2s();
//boost_lexical_cast_test_i2s(); too slow to even be considered.
karma_lexical_cast_test_i2s();
strtk_lexical_cast_test_i2s();
so_lexical_cast_test_i2s();
timo_lexical_cast_test_i2s();
voigt_lexical_cast_test_i2s();
hopman_fast_lexical_cast_test_i2s();
return 0;
}
@Hsilgos
Copy link

Hsilgos commented Jun 8, 2015

643: error, should be "if (val >= 20000)" (without else). Otherwise unsigned 16 bit values > 60000 converts incorrectly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment