Stxxl
1.4.0
|
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