#include <iostream>
#include <random>
#include <memory>
#include "bm.h"
#include "bmalgo.h"
#include "bmtimer.h"
#include "bmundef.h"
using namespace std;
bm::chrono_taker::duration_map_type timing_map;
const unsigned benchmark_count = 10000;
unsigned vector_max = 400000000;
std::random_device rand_dev;
std::mt19937 gen(rand_dev()); std::uniform_int_distribution<> rand_dis(1, int(vector_max));
static
void generate_bvector(bm::bvector<>& bv)
{
bm::bvector<>::size_type i, j;
for (i = 0; i < vector_max;)
{
for (j = 0; j < 65535*8; i += 10, j++)
{
bv.set(i);
}
if (i > vector_max)
break;
for (j = 0; j < 65535; i += 120, j++)
{
unsigned len = rand() % 64;
bv.set_range(i, i + len);
i += len;
if (i > vector_max)
break;
}
}
BM_DECLARE_TEMP_BLOCK(tb)
bv.optimize(tb);
bm::bvector<>::statistics st;
bv.calc_stat(&st);
std::cout << "Bit-vector statistics: GAP (compressed blocks)=" << st.gap_blocks
<< ", BIT (uncompressed blocks)=" << st.bit_blocks
<< std::endl << std::endl;
}
static
bm::bvector<>::size_type pre_heat(const bm::bvector<>& bv)
{
bm::bvector<>::size_type cnt = 0;
bm::bvector<>::size_type m = 1;
for (unsigned i = 0; i < benchmark_count; ++i)
{
cnt += bv.count();
m+=cnt*cnt;
}
return m;
}
static
void bv_count_test(const bm::bvector<>& bv)
{
bm::bvector<>::size_type cnt = 0;
{
bm::chrono_taker tt1("1. bvector<>::count()", benchmark_count / 2, &timing_map);
for (unsigned i = 0; i < benchmark_count / 2; ++i)
{
cnt += bv.count();
}
}
std::cout << "Count test finished." << cnt << "\r";
}
static
void bv_count_range(const bm::bvector<>& bv)
{
bm::bvector<>::size_type cnt = 0;
{
bm::chrono_taker tt1("2. bvector<>::count_range()", benchmark_count, &timing_map);
for (unsigned i = 0; i < benchmark_count; ++i)
{
unsigned from = unsigned(rand_dis(gen));
unsigned to = unsigned(rand_dis(gen));
if (from > to)
swap(from, to);
cnt += bv.count_range(from, to);
}
}
std::cout << "Count range test finished." << cnt << "\r";
}
static
void bv_count_range_acc(const bm::bvector<>& bv)
{
bm::bvector<>::size_type cnt = 0;
std::unique_ptr<bm::bvector<>::rs_index_type> rs(new bm::bvector<>::rs_index_type());
bv.build_rs_index(rs.get());
{
bm::chrono_taker tt1("3. bvector<>::count_range() with rs_index", benchmark_count, &timing_map);
cnt = 0;
for (unsigned i = 0; i < benchmark_count; ++i)
{
unsigned from = unsigned(rand_dis(gen));
unsigned to = unsigned(rand_dis(gen));
if (from > to)
swap(from, to);
cnt += bv.count_range(from, to, *rs); } }
std::cout << "Count range with blocks test finished." << cnt << "\r";
}
static
void bv_count_to_acc(const bm::bvector<>& bv)
{
bm::bvector<>::size_type cnt = 0;
std::unique_ptr<bm::bvector<>::rs_index_type> rs(new bm::bvector<>::rs_index_type());
bv.build_rs_index(rs.get());
{
bm::chrono_taker tt1("4. bvector<>::count_to() with rs_index", benchmark_count, &timing_map);
for (unsigned i = 0; i < benchmark_count; ++i)
{
unsigned to = unsigned(rand_dis(gen));
cnt += bv.count_to(to, *rs); }
}
std::cout << "Count to with blocks test finished." << cnt << "\r";
}
static
void bv_count_to_range_acc(const bm::bvector<>& bv)
{
bm::bvector<>::size_type cnt = 0;
std::unique_ptr<bm::bvector<>::rs_index_type> rs(new bm::bvector<>::rs_index_type());
bv.build_rs_index(rs.get());
{
bm::chrono_taker tt1("5. bvector<>::count_to to simulate count_range()", benchmark_count, &timing_map);
for (unsigned i = 0; i < benchmark_count; ++i)
{
unsigned from = unsigned(rand_dis(gen));
unsigned to = unsigned(rand_dis(gen));
if (from > to)
swap(from, to);
bm::bvector<>::size_type cnt_to = bv.count_to(to, *rs);
bm::bvector<>::size_type cnt_from = bv.count_to(from - 1, *rs);
bm::bvector<>::size_type cnt_r = cnt_to - cnt_from;
cnt += cnt_r;
}
}
std::cout << "Count range via count_to test finished." << cnt << "\r";
}
static
void bv_count_and(const bm::bvector<>& bv)
{
bm::bvector<>::size_type cnt = 0;
{
bm::chrono_taker tt1("6. bm::count_and with mask vector", benchmark_count, &timing_map);
bm::bvector<> mask_bv(bm::BM_GAP); for (unsigned i = 0; i < benchmark_count; ++i)
{
unsigned from = unsigned(rand_dis(gen));
unsigned to = unsigned(rand_dis(gen));
if (from > to)
swap(from, to);
mask_bv.set_range(from, to, true);
cnt += bm::count_and(bv, mask_bv);
mask_bv.clear(true); }
}
std::cout << "count AND finished." << cnt << "\r";
}
static
void bv_counted_enumerator(const bm::bvector<>& bv)
{
bm::bvector<>::size_type cnt = 0;
{
bm::chrono_taker tt1("7. bm::bvector<>::counted_enumerator", benchmark_count/20, &timing_map);
for (unsigned i = 0; i < benchmark_count/20; ++i)
{
unsigned to = unsigned(rand_dis(gen));
bm::bvector<>::counted_enumerator en = bv.first();
for (; en.valid(); ++en)
{
if (*en > to)
break;
}
cnt += en.count();
}
}
std::cout << "counted_enumerator finished." << cnt << "\r";
}
int main(void)
{
try
{
bm::bvector<> bv;
generate_bvector(bv);
unsigned s = pre_heat(bv);
std::cout << s << "\r";
bv_count_test(bv);
bv_count_range(bv);
bv_count_range_acc(bv);
bv_count_to_acc(bv);
bv_count_to_range_acc(bv);
bv_count_and(bv);
bv_counted_enumerator(bv);
std::cout << " "
<< std::endl;
bm::chrono_taker::print_duration_map(timing_map, bm::chrono_taker::ct_ops_per_sec);
}
catch(std::exception& ex)
{
std::cerr << ex.what() << std::endl;
return 1;
}
return 0;
}