Advertisement
Guest User

Benchmark of different methods to concatenate two integers

a guest
Jul 1st, 2016
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.08 KB | None | 0 0
  1. // Compile and link:
  2. // g++ -std=c++11 -O3 -march=native main.cpp -lm
  3.  
  4. // Run and benchmark:
  5. // echo '1234 567890' > cin.txt
  6. // time ./a.out < cin.txt
  7.  
  8. // Check compiler optimizations:
  9. // objdump -dC -j .text a.out > disasm.s
  10.  
  11. // Use static test values, or allow user input from cin?
  12. // 0: Use two integers read from cin.
  13. // 1: Use const values 1234 and 567890.
  14.  
  15. #define STATIC 0
  16.  
  17. // See also the commented out lines in main() below!!!
  18.  
  19. #include <iostream>
  20. #include <sstream>
  21.  
  22. #include <cmath>
  23. #include <cstdlib>
  24.  
  25. namespace i2f {
  26.  
  27. namespace constant {
  28.  
  29.     namespace {
  30.  
  31.         template <typename F=double, typename I=long>
  32.         F scale(const F post) {
  33.             return static_cast<I>(post) ? scale(post * 0.1) : post;
  34.         }
  35.  
  36.     } // helper
  37.  
  38.     template <typename F=double, typename I=long>
  39.     constexpr F concat(const I &pre, const I &post) {
  40.         return static_cast<F>(pre) + scale<F>(post);
  41.     }
  42.  
  43. } // namespace constant
  44.  
  45. namespace log {
  46.  
  47.     template <typename F=double, typename I=long>
  48.     inline F concat(const I &pre, const I &post) {
  49.         return pre + (post > 0 ? (post / ::pow(10, ::floor(::log10(post)) + 1)) : 0);
  50.     }
  51.  
  52. } // namespace log
  53.  
  54. namespace mul {
  55.  
  56.     template <typename F=double, typename I=long>
  57.     inline F concat(const I &pre, const I &post) {
  58.         F frac = post;
  59.  
  60.         while (frac >= 1) {
  61.             frac *= 0.1;
  62.         }
  63.  
  64.         return pre + frac;
  65.     }
  66.  
  67. } // namespace mul
  68.  
  69. namespace str {
  70.  
  71.     namespace {
  72.  
  73.         template <typename F>
  74.         inline F parse_float(const char *cstr) = delete;
  75.  
  76.         template <>
  77.         inline float parse_float<float>(const char *cstr) {
  78.             return strtof(cstr, nullptr);
  79.         }
  80.  
  81.         template <>
  82.         inline double parse_float<double>(const char *cstr) {
  83.             return strtod(cstr, nullptr);
  84.         }
  85.  
  86.         template <>
  87.         inline long double parse_float<long double>(const char *cstr) {
  88.             return strtold(cstr, nullptr);
  89.         }
  90.  
  91.     } // helper
  92.  
  93.     namespace a {
  94.  
  95.         template <typename F=double, typename I=long>
  96.         inline F concat(const I &pre, const I &post) {
  97.             using namespace std;
  98.  
  99.             stringstream ss;
  100.             ss << pre << '.' << post;
  101.  
  102.             constexpr size_t bufsz = 128;
  103.             char buf[bufsz];
  104.             ss.get(buf, bufsz);
  105.  
  106.             return parse_float<F>(buf);
  107.         }
  108.  
  109.     } // namespace a
  110.  
  111.     namespace b {
  112.  
  113.         template <typename F=double, typename I=long>
  114.         inline F concat(const I &pre, const I &post) {
  115.             using namespace std;
  116.  
  117.             stringstream ss;
  118.             ss << post;
  119.  
  120.             constexpr I base = 10;
  121.             const I exp = static_cast<I>(ss.tellp());
  122.  
  123.             return pre + post / ::pow(base, exp);
  124.         }
  125.  
  126.     } // namespace b
  127.  
  128. } // namespace str
  129.  
  130. } // namespace i2f
  131.  
  132. int main(void) {
  133.     using namespace std;
  134.  
  135. #if STATIC == 0
  136.         cout << "DYNAMIC mode!!!" << endl;
  137.  
  138.         long i1, i2;
  139.  
  140.         cout << "Enter two integers separated by space:" << endl;
  141.         cin >> i1 >> i2;
  142. #   else
  143.         cout << "STATIC mode!!!" << endl;
  144.  
  145.         const long i1 = 1234;
  146.         const long i2 = 567890;
  147. #   endif
  148.  
  149.     cout << "Using " << i1 << " and " << i2 << '.' << endl;
  150.  
  151.     constexpr size_t count = 10000000L;
  152.     cout << "Iterating " << count << " times ..." << endl;
  153.  
  154.     double d = 0.0;
  155.  
  156.     // The "volatile" keyword prevents the compiler from
  157.     // completely removing the following loop, while keeping
  158.     // all other optimizations intact.
  159.     for (volatile size_t i = 0; i < count; ++i) {
  160.        
  161.         //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  162.         //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  163.         //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  164.         //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  165.  
  166.         //XXX Uncomment only a single line per test!
  167.  
  168.         //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  169.         //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  170.         //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  171.         //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  172.  
  173.         // static 0.01 / dynamic 0.04
  174.         d = i2f::constant::concat(i1, i2);
  175.  
  176.         // static 0.01 / dynamic 1.00
  177.         //d = i2f::log::concat(i1, i2);
  178.  
  179.         // static 0.01 / dynamic 0.04
  180.         //d = i2f::mul::concat(i1, i2);
  181.  
  182.         // static 8.66 / dynamic 8.66
  183.         //d = i2f::str::a::concat(i1, i2);
  184.  
  185.         // static 6.52 / dynamic 6.45
  186.         //d = i2f::str::b::concat(i1, i2);
  187.     }
  188.  
  189.     // Result as float: 1234.567890
  190.     cout << fixed << "Concatenated result: " << d << endl;
  191. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement