http://stxxl.sourceforge.net
<fedorow@cs.uni-frankfurt.de>
<beckmann@cs.uni-frankfurt.de>
http://www.boost.org/LICENSE_1_0.txt
#include <iostream>
#include <limits>
#include <stxxl/mng>
#include <stxxl/vector>
#include <stxxl/stream>
using std::cout;
using std::endl;
const stxxl::uint64 memory_to_use = 3ul * 1024 * 1024 * 1024;
bool verbose;
struct random_generator
{
typedef stxxl::random_number32::value_type value_type;
typedef stxxl::uint64 size_type;
value_type current;
size_type count;
stxxl::random_number32 rnd;
random_generator(size_type _count) : count(_count)
{
if (verbose) cout << "Random Stream: ";
current = rnd();
}
value_type operator * () const
{
return current;
}
random_generator & operator ++ ()
{
count--;
if (verbose) {
cout << current << ", ";
if (empty()) cout << endl;
}
current = rnd();
return *this;
}
bool empty() const
{
return (count == 0);
}
};
template <typename value_type>
struct Cmp : std::binary_function<value_type, value_type, bool>
{
bool operator () (const value_type & a, const value_type & b) const
{
return a < b;
}
static value_type min_value()
{
return value_type((std::numeric_limits<value_type>::min)());
}
static value_type max_value()
{
return value_type((std::numeric_limits<value_type>::max)());
}
};
template <typename Input>
struct filter
{
typedef typename Input::value_type value_type;
typedef stxxl::uint64 size_type;
Input & input;
value_type filter_value;
size_type & counter;
void apply_filter()
{
while (!input.empty() && *input == filter_value) {
++input;
counter++;
}
}
filter(Input & _input, value_type _filter_value, size_type & _counter) : input(_input), filter_value(_filter_value), counter(_counter)
{
apply_filter();
}
const value_type operator * () const
{
return *input;
}
filter & operator ++ ()
{
++input;
apply_filter();
return *this;
}
bool empty() const
{
return input.empty();
}
};
template <typename Input>
struct output
{
typedef typename Input::value_type value_type;
Input & input;
output(Input & _input) : input(_input) { }
const value_type operator * () const
{
return *input;
}
output & operator ++ ()
{
if (verbose) cout << *input << ", ";
++input;
if (empty() && verbose)
cout << endl;
return *this;
}
bool empty() const
{
return input.empty();
}
};
template <typename Input>
struct shuffle
{
typedef typename Input::value_type value_type;
Input & input;
value_type current, next;
bool even, is_empty;
int count_bits(stxxl::uint64 v)
{
int c;
for (c = 0; v; c++) {
v &= v - 1;
}
return c;
}
void apply_shuffle()
{
is_empty = input.empty();
if (!is_empty) {
current = *input;
++input;
if (!input.empty()) {
STXXL_STATIC_ASSERT(sizeof(value_type) == 4);
stxxl::uint64 combined = current;
combined = combined << 32 | *input;
combined = (1ul << count_bits(combined)) - 1;
current = combined >> 32;
next = combined;
}
}
}
shuffle(Input & _input) : input(_input), current(0), next(0), even(true), is_empty(false)
{
apply_shuffle();
}
value_type operator * () const
{
return current;
}
shuffle & operator ++ ()
{
even = !even;
is_empty = input.empty();
if (even) {
++input;
apply_shuffle();
} else {
current = next;
}
return *this;
}
bool empty() const
{
return is_empty;
}
};
typedef random_generator input_generator_type;
typedef Cmp<input_generator_type::value_type> cmp;
typedef stxxl::stream::runs_creator<input_generator_type, cmp> runs_creator_type0;
typedef runs_creator_type0::sorted_runs_type sorted_runs_type;
typedef stxxl::stream::runs_merger<sorted_runs_type, cmp> runs_merger_type;
typedef output<runs_merger_type> output_type;
typedef filter<output_type> filter_type0;
typedef filter<filter_type0> filter_type1;
typedef shuffle<filter_type1> shuffle_type;
typedef stxxl::stream::runs_creator<shuffle_type, cmp> runs_creator_type1;
int main(int argc, char ** argv)
{
if (argc < 2) {
cout << "Usage: " << argv[0] << " count [Options]\nOptions: -v \t prints elements of each iteration\n";
return EXIT_FAILURE;
}
stxxl::block_manager::get_instance();
verbose = (argc == 3) && !strcmp(argv[2], "-v");
stxxl::uint64 total = atoi(argv[1]);
input_generator_type input_stream(total);
runs_creator_type0 runs_creator(input_stream, cmp(), memory_to_use);
sorted_runs_type& sorted_runs = runs_creator.result();
stxxl::uint64 counter = 0;
int i;
for (i = 0; counter < total - 1; ++i) {
if (verbose) cout << "Iteration " << i << ": ";
runs_merger_type runs_merger(sorted_runs, cmp(), memory_to_use);
output_type output_stream(runs_merger);
filter_type0 filter0(output_stream, 0, counter);
filter_type1 filter1(filter0, filter_type1::value_type(-1), counter);
shuffle_type shuffled_stream(filter1);
runs_creator_type1 runs_creator(shuffled_stream, cmp(), memory_to_use);
sorted_runs.swap( runs_creator.result() );
}
runs_merger_type runs_merger(sorted_runs, cmp(), memory_to_use);
while (!runs_merger.empty()) {
if (verbose) cout << "Iteration " << i << ": " << *runs_merger << endl;
++runs_merger;
}
cout << "\nIteration needed: " << i << endl;
return 0;
}