1 /***************************************************************************
2  *  examples/stream/stream1.cpp
3  *
4  *  This file contains the example snippets from the stream tutorial.
5  *
6  *  Part of the STXXL. See http://stxxl.sourceforge.net
7  *
8  *  Copyright (C) 2012-2013 Timo Bingmann <tb@panthema.net>
9  *
10  *  Distributed under the Boost Software License, Version 1.0.
11  *  (See accompanying file LICENSE_1_0.txt or copy at
12  *  http://www.boost.org/LICENSE_1_0.txt)
13  **************************************************************************/
14 
15 #include <stxxl/stream>
16 #include <stxxl/vector>
17 #include <stxxl/sorter>
18 
19 #include <vector>
20 #include <climits>
21 
22 struct counter_object
23 {
24     // This stream produces a sequence of integers.
25     typedef int value_type;
26 
27 private:
28     // A class attribute to save the current value.
29     int m_current_value;
30 
31 public:
32     // A constructor to set the initial value to 1.
counter_objectcounter_object33     counter_object()
34         : m_current_value(1)
35     { }
36 
37     // The retrieve operator returning the current value.
operator *counter_object38     const value_type& operator * () const
39     {
40         return m_current_value;
41     }
42 
43     // Increment operator advancing to the next integer.
operator ++counter_object44     counter_object& operator ++ ()
45     {
46         ++m_current_value;
47         return *this;
48     }
49 
50     // Empty indicator, which in this case can check the current value.
emptycounter_object51     bool empty() const
52     {
53         return (m_current_value > 1000);
54     }
55 };
56 
57 template <typename InputStream>
58 struct squaring_object
59 {
60     // This stream produces a sequence of integers.
61     typedef int value_type;
62 
63 private:
64     // A reference to another stream of integers, which are our input.
65     InputStream& m_input_stream;
66 
67     // A temporary value buffer to hold the current square in for retrieval.
68     value_type m_current_value;
69 
70 public:
71     // A constructor taking another stream of integers as input.
squaring_objectsquaring_object72     squaring_object(InputStream& input_stream)
73         : m_input_stream(input_stream)
74     {
75         if (!m_input_stream.empty())
76         {
77             m_current_value = *m_input_stream;
78             m_current_value = m_current_value * m_current_value;
79         }
80     }
81 
82     // The retrieve operator returning the square of the input stream.
operator *squaring_object83     const value_type& operator * () const
84     {
85         return m_current_value;
86     }
87 
88     // Increment operator: handled by incrementing the input stream.
operator ++squaring_object89     squaring_object& operator ++ ()
90     {
91         ++m_input_stream;
92         if (!m_input_stream.empty())
93         {
94             m_current_value = *m_input_stream;
95             m_current_value = m_current_value * m_current_value;
96         }
97         return *this;
98     }
99 
100     // Empty indicator: this stream is empty when the input stream is.
emptysquaring_object101     bool empty() const
102     {
103         return m_input_stream.empty();
104     }
105 };
106 
107 // define comparator class: compare right-most decimal and then absolute value
108 struct CompareMod10
109 {
110     // comparison operator() returning true if (a < b)
operator ()CompareMod10111     inline bool operator () (int a, int b) const
112     {
113         if ((a % 10) == (b % 10))
114             return a < b;
115         else
116             return (a % 10) < (b % 10);
117     }
118 
119     // smallest possible integer value
min_valueCompareMod10120     int min_value() const { return INT_MIN; }
121     // largest possible integer value
max_valueCompareMod10122     int max_value() const { return INT_MAX; }
123 };
124 
main()125 int main()
126 {
127     {
128         counter_object counter;
129 
130         while (!counter.empty())
131         {
132             std::cout << *counter << " ";
133             ++counter;
134         }
135         std::cout << std::endl;
136     }
137 
138     {
139         for (counter_object cnt; !cnt.empty(); ++cnt)
140         {
141             std::cout << *cnt << " ";
142         }
143         std::cout << std::endl;
144     }
145 
146     {
147         counter_object counter;
148         squaring_object<counter_object> squares(counter);
149 
150         while (!squares.empty())
151         {
152             std::cout << *squares << " ";
153             ++squares;
154         }
155         std::cout << std::endl;
156     }
157 
158     {
159         std::vector<int> intvector;
160         // (fill intvector)
161 
162         // define stream class iterating over an integer vector
163         typedef stxxl::stream::iterator2stream<std::vector<int>::const_iterator> intstream_type;
164 
165         // instantiate the stream object, iterate from begin to end of intvector.
166         intstream_type intstream(intvector.begin(), intvector.end());
167 
168         // plug in squaring object after vector iterator stream.
169         squaring_object<intstream_type> squares(intstream);
170     }
171 
172     {
173         stxxl::vector<int> intvector;
174         // (fill intvector)
175 
176         // define stream class iterating over an integer vector
177         typedef stxxl::stream::vector_iterator2stream<stxxl::vector<int>::const_iterator> intstream_type;
178 
179         // instantiate the stream object, iterate from begin to end of intvector.
180         intstream_type intstream(intvector.begin(), intvector.end());
181 
182         // plug in squaring object after vector iterator stream.
183         squaring_object<intstream_type> squares(intstream);
184     }
185 
186     {
187         // construct the squared counter stream
188         counter_object counter;
189         squaring_object<counter_object> squares(counter);
190 
191         // allocate vector of 100 integers
192         std::vector<int> intvector(100);
193 
194         // materialize 100 integers from stream and put into vector
195         stxxl::stream::materialize(squares, intvector.begin(), intvector.end());
196     }
197 
198     {
199         // construct the squared counter stream
200         counter_object counter;
201         squaring_object<counter_object> squares(counter);
202 
203         // allocate STXXL vector of 100 integers
204         stxxl::vector<int> intvector(100);
205 
206         // materialize 100 integers from stream and put into STXXL vector
207         stxxl::stream::materialize(squares, intvector.begin(), intvector.end());
208     }
209 
210     {
211         static const int ram_use = 10 * 1024 * 1024; // amount of memory to use in runs creation
212 
213         counter_object counter;                      // the counter stream from first examples
214 
215         // define a runs sorter for the counter stream which order by CompareMod10 object.
216         typedef stxxl::stream::runs_creator<counter_object, CompareMod10> rc_counter_type;
217 
218         // instance of CompareMod10 comparator class
219         CompareMod10 comparemod10;
220 
221         // instance of runs_creator which reads the counter stream.
222         rc_counter_type rc_counter(counter, comparemod10, ram_use);
223 
224         // define a runs merger for the sorted runs from rc_counter.
225         typedef stxxl::stream::runs_merger<rc_counter_type::sorted_runs_type, CompareMod10> rm_counter_type;
226 
227         // instance of runs_merger which merges sorted runs from rc_counter.
228         rm_counter_type rm_counter(rc_counter.result(), comparemod10, ram_use);
229 
230         // read sorted stream: runs_merger also conforms to the stream interface.
231         while (!rm_counter.empty())
232         {
233             std::cout << *rm_counter << " ";
234             ++rm_counter;
235         }
236         std::cout << std::endl;
237     }
238 
239     {
240         static const int ram_use = 10 * 1024 * 1024;   // amount of memory to use in runs creation
241 
242         // define a runs sorter which accepts imperative push()s and orders by CompareMod10 object.
243         typedef stxxl::stream::runs_creator<stxxl::stream::use_push<int>, CompareMod10> rc_counter_type;
244 
245         // instance of CompareMod10 comparator class.
246         CompareMod10 comparemod10;
247 
248         // instance of runs_creator which waits for input.
249         rc_counter_type rc_counter(comparemod10, ram_use);
250 
251         // write sequence of integers into runs
252         for (int i = 1; i <= 1000; ++i)
253             rc_counter.push(i);
254 
255         // define a runs merger for the sorted runs from rc_counter.
256         typedef stxxl::stream::runs_merger<rc_counter_type::sorted_runs_type, CompareMod10> rm_counter_type;
257 
258         // instance of runs_merger which merges sorted runs from rc_counter.
259         rm_counter_type rm_counter(rc_counter.result(), comparemod10, ram_use);
260 
261         // read sorted stream: runs_merger also conforms to the stream interface.
262         while (!rm_counter.empty())
263         {
264             std::cout << *rm_counter << " ";
265             ++rm_counter;
266         }
267         std::cout << std::endl;
268     }
269 
270     {
271         static const int ram_use = 10 * 1024 * 1024;   // amount of memory to use in runs creation
272 
273         // define a runs sorter which accepts imperative push()s and orders by CompareMod10 object.
274         typedef stxxl::sorter<int, CompareMod10> sr_counter_type;
275 
276         // instance of CompareMod10 comparator class.
277         CompareMod10 comparemod10;
278 
279         // instance of sorter which waits for input.
280         sr_counter_type sr_counter(comparemod10, ram_use);
281 
282         // write sequence of integers into sorter, which creates sorted runs
283         for (int i = 1; i <= 1000; ++i)
284             sr_counter.push(i);
285 
286         // signal sorter that the input stream is finished and switch to output mode.
287         sr_counter.sort();
288 
289         // read sorted stream: sorter also conforms to the stream interface.
290         while (!sr_counter.empty())
291         {
292             std::cout << *sr_counter << " ";
293             ++sr_counter;
294         }
295         std::cout << std::endl;
296     }
297 }
298