#if _MSC_VER
#pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#include <iostream>
#include <stdio.h> // printf
#include <string.h> // memcmp
#define min_( a, b ) ( (a) < (b) ? (a) : (b) )
//------------------------------+---------------------------------------------------------------
#ifndef SYS_BITS
#define CHAR_BITS 8
#define SYS_BYTES sizeof( std::size_t )
#define SYS_BITS ( SYS_BYTES * CHAR_BITS )
#endif
//------------------------------+---------------------------------------------------------------
using ON_RUN = void( & )( void* );
using ON_PREPARE = void( & )( void* );
using ON_COMPARE = bool( & )( void*, void*, std::size_t );
//------------------------------+---------------------------------------------------------------
// BENCH 에 의해서만 접근되기 때문에 모든 멤버가 private ( class default ) 입니다
class RUNNER
{
friend class BENCH;
const char* name;
unsigned long long elapsed;
const ON_RUN on_run;
void* result;
RUNNER( const char* name, ON_RUN& on_run, void* result )
: name( name )
, on_run( on_run )
, elapsed( -1 )
, result( result )
{
}
void run()
{
auto begin = __rdtsc();
on_run( result );
elapsed = min_( elapsed, __rdtsc() - begin );
}
};
///-----------------------------+---------------------------------------------------------------
#include <vector>
class BENCH
{
private:
const char* title;
std::vector< RUNNER* > runners;
ON_PREPARE on_prepare;
ON_COMPARE on_compare;
void* answer;
std::size_t answer_size;
const unsigned int trial;
public:
BENCH( const char* title, const int trial,
ON_PREPARE& prepare, ON_COMPARE& compare
)
: title( title )
, trial( trial )
, on_prepare( prepare )
, on_compare( compare )
{
};
~BENCH()
{
for( auto runner : runners )
delete[] runner;
runners.clear();
}
auto record( unsigned int index ) const
{
return runners[ index ]->elapsed;
}
auto runner_count() const
{
return runners.size();
}
void solution( ON_RUN& correct_function,
void* result, const std::size_t bytes )
{
answer = result;
answer_size = bytes;
on_prepare( result );
correct_function( result );
}
template< typename T >
void solution( ON_RUN& correct_function,
T& result, const std::size_t bytes )
{
solution( correct_function, &result, bytes );
}
void add( const char* name, ON_RUN& on_run, void* result )
{
runners.emplace_back( new RUNNER( name, on_run, result ) );
}
template< typename T >
void add( const char* name, ON_RUN& on_run, T& result )
{
add( name, on_run, &result );
}
void run() const
{
if( runners.empty() )
return;
printf( "\n < %d bits %d trial > %s\n", (int)SYS_BITS, trial, title );
puts( " ----------------+---------------------------------+-----------------------" );
puts( " | CHECKER | function name | minimum clocks |" );
puts( " ----------------+---------------------------------+-----------------------" );
unsigned long long min_clocks = -1;
unsigned long long max_clocks = 0;
RUNNER* min_runner = runners[ 0 ];
RUNNER* max_runner = runners[ 0 ];
for( const auto runner : runners )
{
int pass_count = 0;
for( unsigned int i = 0; i < trial; ++i )
{
on_prepare( runner->result );
runner->run();
pass_count += on_compare( runner->result, answer, answer_size );
}
if( min_clocks > runner->elapsed )
{
min_runner = runner;
min_clocks = runner->elapsed;
}
if( max_clocks < runner->elapsed )
{
max_runner = runner;
max_clocks = runner->elapsed;
}
char temp[ 14 ];
if( trial == pass_count )
sprintf( temp, " PASSED" );
else
sprintf( temp, "FAILED%7d", trial - pass_count );
printf( " [ %s ] %32s %15llu clocks\n", temp, runner->name, runner->elapsed );
}
puts( " --------------------------------------------------------------------------" );
printf( " Winner is %s ( %.2f times faster )\n\n",
min_runner->name, float( max_clocks ) / min_clocks );
}
};
#define FUN( function_name ) #function_name, function_name
//==============================================================================================
//------------------------------+---------------------------------------------------------------
using SOURCE = char;
using RESULT = char;
SOURCE src[ 65536 ];
constexpr std::size_t SIZE = sizeof src / sizeof *src;
RESULT dst0[ SIZE ], dst1[ SIZE ], dst2[ SIZE ], dst3[ SIZE ], dst4[ SIZE ];
//------------------------------+---------------------------------------------------------------
// 테스트전에 불려질 초기화 함수
void prepare( void* result )
{
for( auto& v : src )
v = '1';
src[ sizeof src - 1 ] = 0;
// memcpy( result, src, sizeof src );
}
// 테스트후에 불려질 점검 함수
bool compare( void* result, void* answer, std::size_t bytes )
{
return memcmp( result, answer, bytes ) == 0;
}
//------------------------------+---------------------------------------------------------------
// 테스트할 함수들
namespace cose
{
inline int radix( const char* buf, const int mul )
{
if( mul == 1 )
return *buf & 0xF;
return ( *buf & 0xF ) * mul + radix( buf + 1, mul / 10 );
}
void run( void* dst )
{
for( int i = 0; i < 10000; ++i )
((int*)dst)[ i ] = radix( src + i * 10, 1000000000 );
}
}
namespace pooper
{
long getHeadLen( char *out )
{
return ((out[6] -'0') *1000000000+
(out[7] -'0') *100000000+
(out[8] -'0') *10000000+
(out[9] -'0') *1000000+
(out[10]-'0') *100000+
(out[11]-'0') *10000+
(out[12]-'0') *1000+
(out[13]-'0') *100+
(out[14]-'0') *10+
(out[15]-'0'));
}
void run( void* dst )
{
for( int i = 0; i < 10000; ++i )
((int*)dst)[ i ] = getHeadLen( src + i * 10 );
}
};
namespace cose2
{
inline long ascDec( const char* s )
{
return ( s[ 0 ] -'0' ) * 1000000000 + ( s[ 1 ] -'0' ) * 100000000 +
( s[ 2 ] -'0' ) * 10000000 + ( s[ 3 ] -'0' ) * 1000000 +
( s[ 4 ] -'0' ) * 100000 + ( s[ 5 ] -'0' ) * 10000 +
( s[ 12 ] -'0' ) * 1000 + ( s[ 13 ] -'0' ) * 100 +
( s[ 14 ] -'0' ) * 10 + ( s[ 15 ] -'0' );
}
inline long getHeadLen( const char *out )
{
return ascDec( out + 6 );
}
void run( void* dst )
{
for( int i = 0; i < 10000; ++i )
((int*)dst)[ i ] = getHeadLen( src + i * 10 );
}
};
//------------------------------+---------------------------------------------------------------
int main()
{
BENCH bench( "ascii to decimal", 1000, prepare, compare );
bench.solution( pooper::run, dst0, sizeof dst0 );
bench.add( FUN( pooper::run ), dst3 );
bench.add( FUN( cose::run ), dst2 );
bench.add( FUN( cose2::run ), dst1 );
bench.run();
getchar();
return 0;
}