Stxxl  1.4.0
stream/test_loop.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  stream/test_loop.cpp
00003  *
00004  *  example for building a loop of stream operations
00005  *
00006  *  Part of the STXXL. See http://stxxl.sourceforge.net
00007  *
00008  *  Copyright © 2011 Jaroslaw Fedorowicz <fedorow@cs.uni-frankfurt.de>
00009  *  Copyright © 2011 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
00010  *
00011  *  Distributed under the Boost Software License, Version 1.0.
00012  *  (See accompanying file LICENSE_1_0.txt or copy at
00013  *  http://www.boost.org/LICENSE_1_0.txt)
00014  **************************************************************************/
00015 
00016 //! \example stream/test_loop.cpp
00017 //! This is an example of how to use some basic algorithms from the
00018 //! stream package to form a loop iterating over the data.
00019 //! Some input is generated, sorted, some elements are filtered out.
00020 //! The remaining elements are transformed, sorted and processed in the
00021 //! next pass. The loop will terminate if at most one element remains.
00022 //! A split sorter is used to cut the data flow (and type dependency) cycle.
00023 
00024 #include <iostream>
00025 #include <limits>
00026 
00027 #include <stxxl/mng>
00028 #include <stxxl/vector>
00029 #include <stxxl/stream>
00030 
00031 using std::cout;
00032 using std::endl;
00033 
00034 const stxxl::uint64 memory_to_use = 3ul * 1024 * 1024 * 1024;
00035 
00036 bool verbose;
00037 
00038 struct random_generator
00039 {
00040     typedef stxxl::random_number32::value_type value_type;
00041     typedef stxxl::uint64 size_type;
00042     value_type current;
00043     size_type count;
00044     stxxl::random_number32 rnd;
00045 
00046     random_generator(size_type _count) : count(_count)
00047     {
00048         if (verbose) cout << "Random Stream: ";
00049         current = rnd();
00050     }
00051 
00052     value_type operator * () const
00053     {
00054         return current;
00055     }
00056     random_generator & operator ++ ()
00057     {
00058         count--;
00059         if (verbose) {
00060             cout << current << ", ";
00061             if (empty()) cout << endl;
00062         }
00063         current = rnd();
00064         return *this;
00065     }
00066     bool empty() const
00067     {
00068         return (count == 0);
00069     }
00070 };
00071 
00072 template <typename value_type>
00073 struct Cmp : std::binary_function<value_type, value_type, bool>
00074 {
00075     bool operator () (const value_type & a, const value_type & b) const
00076     {
00077         return a < b;
00078     }
00079     static value_type min_value()
00080     {
00081         return value_type((std::numeric_limits<value_type>::min)());
00082     }
00083     static value_type max_value()
00084     {
00085         return value_type((std::numeric_limits<value_type>::max)());
00086     }
00087 };
00088 
00089 template <typename Input>
00090 struct filter
00091 {
00092     typedef typename Input::value_type value_type;
00093     typedef stxxl::uint64 size_type;
00094     Input & input;
00095     value_type filter_value;
00096     size_type & counter;
00097 
00098     void apply_filter()
00099     {
00100         while (!input.empty() && *input == filter_value) {
00101             ++input;
00102             counter++;
00103         }
00104     }
00105 
00106     filter(Input & _input, value_type _filter_value, size_type & _counter) : input(_input), filter_value(_filter_value), counter(_counter)
00107     {
00108         apply_filter();
00109     }
00110 
00111     const value_type operator * () const
00112     {
00113         return *input;
00114     }
00115 
00116     filter & operator ++ ()
00117     {
00118         ++input;
00119         apply_filter();
00120         return *this;
00121     }
00122 
00123     bool empty() const
00124     {
00125         return input.empty();
00126     }
00127 };
00128 
00129 template <typename Input>
00130 struct output
00131 {
00132     typedef typename Input::value_type value_type;
00133     Input & input;
00134 
00135     output(Input & _input) : input(_input) { }
00136 
00137     const value_type operator * () const
00138     {
00139         return *input;
00140     }
00141 
00142     output & operator ++ ()
00143     {
00144         if (verbose) cout << *input << ", ";
00145         ++input;
00146         if (empty() && verbose)
00147             cout << endl;
00148         return *this;
00149     }
00150 
00151     bool empty() const
00152     {
00153         return input.empty();
00154     }
00155 };
00156 
00157 template <typename Input>
00158 struct shuffle
00159 {
00160     typedef typename Input::value_type value_type;
00161     Input & input;
00162     value_type current, next;
00163     bool even, is_empty;
00164 
00165     // from http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
00166     int count_bits(stxxl::uint64 v)
00167     {
00168         int c;
00169         for (c = 0; v; c++) {
00170             v &= v - 1;
00171         }
00172         return c;
00173     }
00174 
00175     void apply_shuffle()
00176     {
00177         is_empty = input.empty();
00178         if (!is_empty) {
00179             current = *input;
00180             ++input;
00181             if (!input.empty()) {
00182                 STXXL_STATIC_ASSERT(sizeof(value_type) == 4);
00183                 stxxl::uint64 combined = current;
00184                 combined = combined << 32 | *input;
00185                 combined = (1ul << count_bits(combined)) - 1;
00186                 current = combined >> 32;
00187                 next = combined;
00188             }
00189         }
00190     }
00191 
00192     shuffle(Input & _input) : input(_input), current(0), next(0), even(true), is_empty(false)
00193     {
00194         apply_shuffle();
00195     }
00196 
00197     value_type operator * () const
00198     {
00199         return current;
00200     }
00201 
00202     shuffle & operator ++ ()
00203     {
00204         even = !even;
00205         is_empty = input.empty();
00206         if (even) {
00207             ++input;
00208             apply_shuffle();
00209         } else {
00210             current = next;
00211         }
00212         return *this;
00213     }
00214 
00215     bool empty() const
00216     {
00217         return is_empty;
00218     }
00219 };
00220 
00221 typedef random_generator input_generator_type;
00222 typedef Cmp<input_generator_type::value_type> cmp;
00223 typedef stxxl::stream::runs_creator<input_generator_type, cmp> runs_creator_type0;
00224 typedef runs_creator_type0::sorted_runs_type sorted_runs_type;
00225 typedef stxxl::stream::runs_merger<sorted_runs_type, cmp> runs_merger_type;
00226 typedef output<runs_merger_type> output_type;
00227 typedef filter<output_type> filter_type0;
00228 typedef filter<filter_type0> filter_type1;
00229 typedef shuffle<filter_type1> shuffle_type;
00230 typedef stxxl::stream::runs_creator<shuffle_type, cmp> runs_creator_type1;
00231 
00232 int main(int argc, char ** argv)
00233 {
00234     if (argc < 2) {
00235         cout << "Usage: " << argv[0] << " count [Options]\nOptions: -v \t prints elements of each iteration\n";
00236         return EXIT_FAILURE;
00237     }
00238 
00239     stxxl::block_manager::get_instance();
00240 
00241     verbose = (argc == 3) && !strcmp(argv[2], "-v");
00242 
00243     stxxl::uint64 total = atoi(argv[1]);
00244 
00245     input_generator_type input_stream(total);
00246 
00247     runs_creator_type0 runs_creator(input_stream, cmp(), memory_to_use);
00248 
00249     sorted_runs_type& sorted_runs = runs_creator.result();
00250 
00251     stxxl::uint64 counter = 0;
00252     int i;
00253 
00254     for (i = 0; counter < total - 1; ++i) {
00255         if (verbose) cout << "Iteration " << i << ": ";
00256 
00257         runs_merger_type runs_merger(sorted_runs, cmp(), memory_to_use);
00258 
00259         output_type output_stream(runs_merger);
00260 
00261         filter_type0 filter0(output_stream, 0, counter);
00262 
00263         filter_type1 filter1(filter0, filter_type1::value_type(-1), counter);
00264 
00265         shuffle_type shuffled_stream(filter1);
00266 
00267         runs_creator_type1 runs_creator(shuffled_stream, cmp(), memory_to_use);
00268 
00269         sorted_runs.swap( runs_creator.result() );
00270     }
00271 
00272     runs_merger_type runs_merger(sorted_runs, cmp(), memory_to_use);
00273 
00274     while (!runs_merger.empty()) {
00275         if (verbose) cout << "Iteration " << i << ": " << *runs_merger << endl;
00276         ++runs_merger;
00277     }
00278     cout << "\nIteration needed: " << i << endl;
00279 
00280     return 0;
00281 }
00282 
00283 // vim: et:ts=4:sw=4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines