Advertisement
Michaelangel007

isqrt code golf benchmark

Aug 8th, 2014
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.51 KB | None | 0 0
  1. // http://codegolf.stackexchange.com/questions/35182/integer-square-root-of-integer
  2. // http://stackoverflow.com/questions/21657491/an-efficient-algorithm-to-calculate-the-integer-square-root-isqrt-of-arbitrari
  3. // http://www.codecodex.com/wiki/Calculate_an_integer_square_root
  4.  
  5. #include <stdio.h>
  6. #include <stdint.h> // uint64_t
  7. #include <time.h>   // clock()
  8. #include <string.h> // strcpy()
  9.  
  10. // g++ --version
  11. // Apple LLVM version 5.1 (clang-503.0.40)
  12.  
  13. //#define FASTEST
  14.   #define ITERATIVE
  15. //#define RECURSIVE
  16. //#define FASTER
  17. //#define SLOWEST
  18.  
  19. #if defined(FASTEST) // -O3: 0.0 secs, 95 chars, by edc65
  20.     typedef uint64_t Z;Z q(Z x){Z n=1,a=x,m=0;for(;a-m&&a-n;)n=a,m=x/n,a=m/2+n/2+(m&n&1);return a;}
  21.     #define isqrt q
  22. #else
  23. #if defined(ITERATIVE) // -O3: 0.0 secs, by Asuka Kenji - Siu Ching Pong
  24.     typedef uint64_t Z;
  25.     uint32_t isqrt_iterative(uint64_t const n)
  26.     {
  27.         Z xk = n;
  28.         if (n == 0) return 0;
  29.         //if (n == 18446744073709551615ULL) return 4294967295U;
  30.         if( n == -1 ) return -1; // optimization
  31.         do
  32.         {
  33.             Z const xk1 = (xk + n / xk) / 2;
  34.             if (xk1 >= xk)
  35.                 return xk;
  36.             else
  37.                 xk = xk1;
  38.         } while (1);
  39.     }
  40.     #define isqrt isqrt_iterative
  41. #else
  42. #if defined(RECURSIVE) // -O3: 0.0 secs, by Asuka Kenji - Siu Ching Pong
  43.     uint32_t isqrt_impl(
  44.         uint64_t const n,
  45.         uint64_t const xk)
  46.     {
  47.         uint64_t const xk1 = (xk + n / xk) / 2;
  48.         return (xk1 >= xk) ? xk : isqrt_impl(n, xk1);
  49.     }
  50.     uint32_t isqrt_recursive(uint64_t const n)
  51.     {
  52.         if (n == 0) return 0;
  53.         if (n == 18446744073709551615ULL) return 4294967295U;
  54.         return isqrt_impl(n, n);
  55.     }
  56.     #define isqrt isqrt_recursive
  57. #else
  58. #if defined(FASTER)  // -O3: 4.0 secs, 70 chars
  59.     typedef uint64_t Z;Z z(Z x){Z n=0,s=0;for(;s<x;s+=2*n+1)n++;return n;}
  60.     #define isqrt z
  61. #else
  62. #if defined(SLOWEST) // -O3 177.3 secs, 58 chars, undefined behavior by Todd Lehman
  63.     typedef uint64_t Z;Z r(Z n,Z r){for(;n/++r/r;);return--r;}
  64.     #define isqrt(x) r(x,0)
  65. // C++ Non-wrapper version:
  66. //    typedef uint64_t Z;Z isqrt(Z n,Z r=0){for(;n/++r/r;);return--r;}
  67. #else
  68.     #error "Didn't define isqrt() to test!"
  69. #endif // SLOWEST
  70. #endif // FASTER
  71. #endif // RECURSIVE
  72. #endif // ITERATIVE
  73. #endif // FASTEST
  74.  
  75. char* i2a( uint64_t x, int base = 10, bool comma = true )
  76. {
  77.     const  int    SIZE    = 64; // largest is binary + null
  78.     static char t[SIZE  ] ;     // output buffer
  79.     const  int    BASE    = 16; // largest base
  80.     const  char s[BASE+1] = "0123456789ABCDEF";
  81.     /* */  char*p         = t + SIZE - 1;
  82.     /* */  int  digits    = 0;
  83.     /* */  int  r         ;     // remainder
  84.  
  85.     if( base > BASE ) base = BASE;
  86.     if( base <    2 ) base =    2;
  87.  
  88.     *p-- = 0;
  89.     while( x >= base )
  90.     {
  91.         digits++;  
  92.         r  = x % base;
  93.         x -= r;
  94.         x /= base;
  95.         *p = s[ r ];
  96.         p--;
  97.  
  98.         if( comma && base == 16 && digits && ((digits & 7) == 0 )) *p-- = '_';
  99.         if( comma && base == 10 && digits && ((digits % 3) == 0 )) *p-- = ',';
  100.     }
  101.     r = x % base;
  102.     *p = s[ r ];
  103.  
  104.     if( base == 16 ) *--p = 'x';
  105.     if( base ==  2 ) *--p = 'z';
  106.     if( base == 16 || base == 2 || base == 8 ) *--p = '0';
  107.  
  108.     return p;
  109. }
  110.  
  111. inline
  112. void entry( const int i, const uint64_t& n, uint64_t& s )
  113. {
  114.     // If your compiler -O2 is buggy *cough clang cough*
  115.     // ... don't put isqrt() outside the function
  116.     s = isqrt(n);
  117.  
  118.     printf( "#%d  isqrt( ", i );
  119.     printf( "%s = ", i2a( n,16,0) );
  120.     printf( "%s ) ", i2a( n,10,0) );
  121.     printf( "= %s ", i2a( s     ) );
  122.     printf( "\n" );
  123. }
  124.  
  125. int main(int nArg, char* aArg[])
  126. {
  127.     time_t start = clock();
  128.  
  129.         uint64_t n = 0;
  130.         uint64_t s = 0;
  131.         for( int i = 0; i <= sizeof(uint64_t)*8; i++ )
  132.         {
  133.             entry( i, n, s );
  134.             n <<= 1;
  135.             if( !n ) n++; // handle zero case
  136.         }
  137.  
  138.         n = -1; // 0xFFFFffffFFFFffffULL;
  139.         entry( 65, n, s );
  140.  
  141.     time_t end = clock();
  142.     double dif = (end - start);
  143.     double sec = dif / CLOCKS_PER_SEC;
  144.     printf( "Time: %5.3f secs\n", sec );
  145.  
  146.     uint64_t actual = s;
  147.     uint64_t expect = 4294967295ULL; // 2^32-1;
  148.     bool     pass   = (actual == expect);
  149.     char     act[64];
  150.     char     exp[64];
  151.     strcpy( act, i2a( actual ) );
  152.     strcpy( exp, i2a( expect ) );
  153.     printf( "Verify #65 %s =?= %s ? %s\n", act, exp, pass ? "pass." : "FAIL!" );
  154.  
  155.     return 0;
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement