mirror of
https://github.com/boostorg/heap.git
synced 2025-05-11 21:44:02 +00:00
278 lines
6.3 KiB
C++
278 lines
6.3 KiB
C++
/*=============================================================================
|
|
Copyright (c) 2010 Tim Blechmann
|
|
|
|
Use, modification and distribution is subject to the Boost Software
|
|
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
|
http://www.boost.org/LICENSE_1_0.txt)
|
|
=============================================================================*/
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
|
|
#include "high_resolution_timer.hpp"
|
|
#include <boost/foreach.hpp>
|
|
|
|
#include <boost/heap/heap_merge.hpp>
|
|
|
|
#if defined( __GNUC__ ) && ( !defined __INTEL_COMPILER )
|
|
# define no_inline __attribute__( ( noinline ) )
|
|
#else
|
|
# define no_inline
|
|
#endif
|
|
|
|
typedef std::vector< int > test_data;
|
|
|
|
const int num_benchmarks = 1;
|
|
|
|
inline test_data make_sequential_test_data( int size )
|
|
{
|
|
test_data v( size );
|
|
for ( int i = 0; i != size; ++i )
|
|
v[ i ] = i;
|
|
return v;
|
|
}
|
|
|
|
inline test_data make_test_data( int size )
|
|
{
|
|
test_data v = make_sequential_test_data( size );
|
|
std::random_shuffle( v.begin(), v.end() );
|
|
return v;
|
|
}
|
|
|
|
const int max_data = 20;
|
|
|
|
test_data const& get_data( int index )
|
|
{
|
|
static std::vector< test_data > data;
|
|
if ( data.empty() )
|
|
for ( int i = 0; i != num_benchmarks; ++i )
|
|
data.push_back( make_test_data( ( 1 << ( max_data + 1 ) ) + 1024 ) );
|
|
|
|
return data[ index ];
|
|
}
|
|
|
|
|
|
#define DEFINE_BENCHMARKS_SELECTOR( SUFFIX ) \
|
|
struct make_##SUFFIX \
|
|
{ \
|
|
template < typename heap > \
|
|
struct rebind \
|
|
{ \
|
|
typedef run_##SUFFIX< heap > type; \
|
|
}; \
|
|
};
|
|
|
|
|
|
template < typename pri_queue >
|
|
void fill_heap( pri_queue& q, int index, int size, int offset = 0 )
|
|
{
|
|
test_data const& data = get_data( index );
|
|
|
|
for ( int i = 0; i != size + 1; ++i ) {
|
|
q.push( data[ i ] );
|
|
int top = q.top();
|
|
q.pop();
|
|
q.push( top );
|
|
}
|
|
}
|
|
|
|
template < typename pri_queue, typename handle_container >
|
|
void fill_heap_with_handles( pri_queue& q, handle_container& handles, int index, int size, int offset = 0 )
|
|
{
|
|
test_data const& data = get_data( index );
|
|
|
|
for ( int i = 0; i != size + 1; ++i ) {
|
|
handles[ i ] = q.push( data[ i ] );
|
|
|
|
if ( i > 0 ) {
|
|
typename pri_queue::handle_type last = handles[ i - 1 ];
|
|
int val = *last;
|
|
q.erase( last );
|
|
handles[ i - 1 ] = q.push( val );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
template < typename pri_queue >
|
|
struct run_sequential_push
|
|
{
|
|
run_sequential_push( int size ) :
|
|
size( size )
|
|
{}
|
|
|
|
void prepare( int index )
|
|
{
|
|
q.clear();
|
|
fill_heap( q, index, size );
|
|
}
|
|
|
|
no_inline void operator()( int index )
|
|
{
|
|
test_data const& data = get_data( index );
|
|
|
|
for ( int i = 0; i != 16; ++i )
|
|
q.push( data[ ( 1 << max_data ) + i ] );
|
|
}
|
|
|
|
pri_queue q;
|
|
int size;
|
|
};
|
|
|
|
DEFINE_BENCHMARKS_SELECTOR( sequential_push )
|
|
|
|
template < typename pri_queue >
|
|
struct run_sequential_pop
|
|
{
|
|
run_sequential_pop( int size ) :
|
|
size( size )
|
|
{}
|
|
|
|
void prepare( int index )
|
|
{
|
|
q.clear();
|
|
fill_heap( q, index, size );
|
|
}
|
|
|
|
no_inline void operator()( int index )
|
|
{
|
|
for ( int i = 0; i != 16; ++i )
|
|
q.pop();
|
|
}
|
|
|
|
pri_queue q;
|
|
int size;
|
|
};
|
|
|
|
DEFINE_BENCHMARKS_SELECTOR( sequential_pop )
|
|
|
|
template < typename pri_queue >
|
|
struct run_sequential_increase
|
|
{
|
|
run_sequential_increase( int size ) :
|
|
size( size ),
|
|
handles( size )
|
|
{}
|
|
|
|
void prepare( int index )
|
|
{
|
|
q.clear();
|
|
fill_heap_with_handles( q, handles, index, size );
|
|
}
|
|
|
|
no_inline void operator()( int index )
|
|
{
|
|
test_data const& data = get_data( index );
|
|
for ( int i = 0; i != 16; ++i )
|
|
q.increase( handles[ i ], data[ i ] + ( 1 << max_data ) );
|
|
}
|
|
|
|
pri_queue q;
|
|
int size;
|
|
std::vector< typename pri_queue::handle_type > handles;
|
|
};
|
|
|
|
DEFINE_BENCHMARKS_SELECTOR( sequential_increase )
|
|
|
|
template < typename pri_queue >
|
|
struct run_sequential_decrease
|
|
{
|
|
run_sequential_decrease( int size ) :
|
|
size( size ),
|
|
handles( size )
|
|
{}
|
|
|
|
void prepare( int index )
|
|
{
|
|
q.clear();
|
|
fill_heap_with_handles( q, handles, index, size );
|
|
}
|
|
|
|
no_inline void operator()( int index )
|
|
{
|
|
test_data const& data = get_data( index );
|
|
for ( int i = 0; i != 16; ++i )
|
|
q.decrease( handles[ i ], data[ i ] + ( 1 << max_data ) );
|
|
}
|
|
|
|
pri_queue q;
|
|
int size;
|
|
std::vector< typename pri_queue::handle_type > handles;
|
|
};
|
|
|
|
DEFINE_BENCHMARKS_SELECTOR( sequential_decrease )
|
|
|
|
template < typename pri_queue >
|
|
struct run_merge_and_clear
|
|
{
|
|
run_merge_and_clear( int size ) :
|
|
size( size )
|
|
{}
|
|
|
|
void prepare( int index )
|
|
{
|
|
q.clear();
|
|
r.clear();
|
|
|
|
fill_heap( q, index, size );
|
|
fill_heap( r, index, size, size );
|
|
}
|
|
|
|
no_inline void operator()( int index )
|
|
{
|
|
boost::heap::heap_merge( q, r );
|
|
}
|
|
|
|
pri_queue q, r;
|
|
int size;
|
|
};
|
|
|
|
DEFINE_BENCHMARKS_SELECTOR( merge_and_clear )
|
|
|
|
template < typename pri_queue >
|
|
struct run_equivalence
|
|
{
|
|
run_equivalence( int size ) :
|
|
size( size )
|
|
{}
|
|
|
|
void prepare( int index )
|
|
{
|
|
q.clear();
|
|
r.clear();
|
|
s.clear();
|
|
|
|
fill_heap( q, index, size );
|
|
fill_heap( r, index, size, size );
|
|
fill_heap( s, index, size );
|
|
}
|
|
|
|
no_inline bool operator()( int index )
|
|
{
|
|
return ( q == r ) ^ ( q == s );
|
|
}
|
|
|
|
pri_queue q, r, s;
|
|
int size;
|
|
};
|
|
|
|
DEFINE_BENCHMARKS_SELECTOR( equivalence )
|
|
|
|
|
|
template < typename benchmark >
|
|
inline double run_benchmark( benchmark& b )
|
|
{
|
|
boost::high_resolution_timer timer;
|
|
std::vector< double > results;
|
|
|
|
for ( int i = 0; i != num_benchmarks; ++i ) {
|
|
b.prepare( i );
|
|
timer.restart();
|
|
b( i );
|
|
double t = timer.elapsed();
|
|
results.push_back( t );
|
|
}
|
|
|
|
return results.at( results.size() / 2 ); // median
|
|
}
|