15 #ifndef STXXL_RANDOM_SHUFFLE_HEADER
16 #define STXXL_RANDOM_SHUFFLE_HEADER
23 #include <stxxl/bits/stream/stream.h>
25 #include <stxxl/stack>
28 __STXXL_BEGIN_NAMESPACE
44 template <
typename ExtIterator_,
45 typename RandomNumberGenerator_,
48 typename AllocStrategy_>
51 RandomNumberGenerator_ & rand,
53 AllocStrategy_ AS = STXXL_DEFAULT_ALLOC_STRATEGY())
56 typedef typename ExtIterator_::value_type value_type;
57 typedef typename stxxl::STACK_GENERATOR<value_type, stxxl::external,
58 stxxl::grow_shrink2, PageSize_,
59 BlockSize_, void, 0, AllocStrategy_>::result stack_type;
60 typedef typename stack_type::block_type block_type;
62 STXXL_VERBOSE1(
"random_shuffle: Plain Version");
63 STXXL_STATIC_ASSERT(
int(BlockSize_) < 0 &&
"This implementation was never tested. Please report to the stxxl developers if you have an ExtIterator_ that works with this implementation.");
65 stxxl::int64 n = last - first;
68 if (M < 6 * BlockSize_ + PageSize_ * BlockSize_) {
69 STXXL_ERRMSG(
"random_shuffle: insufficient memory, " << M <<
" bytes supplied,");
70 M = 6 * BlockSize_ + PageSize_ * BlockSize_;
71 STXXL_ERRMSG(
"random_shuffle: increasing to " << M <<
" bytes (6 blocks + 1 page)");
74 int_type k = M / (3 * BlockSize_);
77 stxxl::int64 i, j, size = 0;
79 value_type * temp_array;
80 typedef typename stxxl::VECTOR_GENERATOR<value_type,
81 PageSize_, 4, BlockSize_, AllocStrategy_>::result temp_vector_type;
82 temp_vector_type * temp_vector;
84 STXXL_VERBOSE1(
"random_shuffle: " << M / BlockSize_ - k <<
" write buffers for " << k <<
" buckets");
85 stxxl::read_write_pool<block_type> pool(0, M / BlockSize_ - k);
87 stack_type ** buckets;
90 buckets =
new stack_type *[k];
91 for (j = 0; j < k; j++)
92 buckets[j] =
new stack_type(pool, 0);
100 int_type random_bucket = 0;
101 for (i = 0; i < n; ++i) {
102 random_bucket = rand(k);
103 buckets[random_bucket]->push(*in);
109 pool.resize_write(0);
110 pool.resize_prefetch(PageSize_);
112 unsigned_type space_left = M - k * BlockSize_ -
113 PageSize_ * BlockSize_;
114 ExtIterator_ Writer = first;
115 ExtIterator_ it = first;
117 for (i = 0; i < k; i++) {
118 STXXL_VERBOSE1(
"random_shuffle: bucket no " << i <<
" contains " << buckets[i]->size() <<
" elements");
122 for (i = 0; i < k; i++) {
123 buckets[i]->set_prefetch_aggr(PageSize_);
124 size = buckets[i]->size();
127 if (size *
sizeof(value_type) < space_left) {
128 STXXL_VERBOSE1(
"random_shuffle: no recursion");
131 temp_array =
new value_type[size];
132 for (j = 0; j < size; j++) {
133 temp_array[j] = buckets[i]->top();
142 for (j = 0; j < size; j++) {
143 *Writer = temp_array[j];
151 STXXL_VERBOSE1(
"random_shuffle: recursion");
154 temp_vector =
new temp_vector_type(size);
156 for (j = 0; j < size; j++) {
157 (*temp_vector)[j] = buckets[i]->top();
161 pool.resize_prefetch(0);
162 space_left += PageSize_ * BlockSize_;
163 STXXL_VERBOSE1(
"random_shuffle: Space left: " << space_left);
167 temp_vector->end(), rand, space_left);
169 pool.resize_prefetch(PageSize_);
172 for (j = 0; j < size; j++) {
173 *Writer = (*temp_vector)[j];
183 space_left += BlockSize_;
194 template <
typename Tp_,
typename AllocStrategy_,
typename SzTp_,
typename DiffTp_,
195 unsigned BlockSize_,
typename PgTp_,
unsigned PageSize_,
typename RandomNumberGenerator_>
196 void random_shuffle(stxxl::vector_iterator<Tp_, AllocStrategy_, SzTp_, DiffTp_, BlockSize_, PgTp_, PageSize_> first,
197 stxxl::vector_iterator<Tp_, AllocStrategy_, SzTp_, DiffTp_, BlockSize_, PgTp_, PageSize_> last,
198 RandomNumberGenerator_ & rand,
201 typedef stxxl::vector_iterator<Tp_, AllocStrategy_, SzTp_, DiffTp_, BlockSize_, PgTp_, PageSize_> ExtIterator_;
202 typedef typename ExtIterator_::value_type value_type;
203 typedef typename stxxl::STACK_GENERATOR<value_type, stxxl::external,
204 stxxl::grow_shrink2, PageSize_, BlockSize_>::result stack_type;
205 typedef typename stack_type::block_type block_type;
207 STXXL_VERBOSE1(
"random_shuffle: Vector Version");
210 if (M < 6 * BlockSize_ + PageSize_ * BlockSize_) {
211 STXXL_ERRMSG(
"random_shuffle: insufficient memory, " << M <<
" bytes supplied,");
212 M = 6 * BlockSize_ + PageSize_ * BlockSize_;
213 STXXL_ERRMSG(
"random_shuffle: increasing to " << M <<
" bytes (6 blocks + 1 page)");
216 stxxl::int64 n = last - first;
217 int_type k = M / (3 * BlockSize_);
219 stxxl::int64 i, j, size = 0;
221 value_type * temp_array;
222 typedef typename stxxl::VECTOR_GENERATOR<value_type,
223 PageSize_, 4, BlockSize_, AllocStrategy_>::result temp_vector_type;
224 temp_vector_type * temp_vector;
226 stxxl::read_write_pool<block_type> pool(0, M / BlockSize_ - k);
228 stack_type ** buckets;
231 buckets =
new stack_type *[k];
232 for (j = 0; j < k; j++)
233 buckets[j] =
new stack_type(pool, 0);
242 buf_istream_type in(first.bid(), last.bid() + ((last.block_offset()) ? 1 : 0), 2);
244 buf_ostream_type out(first.bid(), 2);
246 ExtIterator_ _cur = first - first.block_offset();
249 for ( ; _cur != first; ++_cur)
251 typename ExtIterator_::value_type tmp;
259 int_type random_bucket = 0;
260 for (i = 0; i < n; ++i, ++_cur) {
261 random_bucket = rand(k);
262 typename ExtIterator_::value_type tmp;
264 buckets[random_bucket]->push(tmp);
269 pool.resize_write(0);
270 pool.resize_prefetch(PageSize_);
272 unsigned_type space_left = M - k * BlockSize_ -
273 PageSize_ * BlockSize_;
275 for (i = 0; i < k; i++) {
276 STXXL_VERBOSE1(
"random_shuffle: bucket no " << i <<
" contains " << buckets[i]->size() <<
" elements");
280 for (i = 0; i < k; i++) {
281 buckets[i]->set_prefetch_aggr(PageSize_);
282 size = buckets[i]->size();
285 if (size *
sizeof(value_type) < space_left) {
286 STXXL_VERBOSE1(
"random_shuffle: no recursion");
289 temp_array =
new value_type[size];
290 for (j = 0; j < size; j++) {
291 temp_array[j] = buckets[i]->top();
300 for (j = 0; j < size; j++) {
301 typename ExtIterator_::value_type tmp;
309 STXXL_VERBOSE1(
"random_shuffle: recursion");
311 temp_vector =
new temp_vector_type(size);
313 for (j = 0; j < size; j++) {
314 (*temp_vector)[j] = buckets[i]->top();
318 pool.resize_prefetch(0);
319 space_left += PageSize_ * BlockSize_;
321 STXXL_VERBOSE1(
"random_shuffle: Space left: " << space_left);
325 temp_vector->end(), rand, space_left);
327 pool.resize_prefetch(PageSize_);
330 for (j = 0; j < size; j++) {
331 typename ExtIterator_::value_type tmp;
332 tmp = (*temp_vector)[j];
342 space_left += BlockSize_;
348 if (last.block_offset())
350 ExtIterator_ _last_block_end = last + (block_type::size - last.block_offset());
351 for ( ; _cur != _last_block_end; ++_cur)
353 typename ExtIterator_::value_type tmp;
364 template <
typename Tp_,
typename AllocStrategy_,
typename SzTp_,
typename DiffTp_,
365 unsigned BlockSize_,
typename PgTp_,
unsigned PageSize_>
367 void random_shuffle(stxxl::vector_iterator<Tp_, AllocStrategy_, SzTp_, DiffTp_, BlockSize_, PgTp_, PageSize_> first,
368 stxxl::vector_iterator<Tp_, AllocStrategy_, SzTp_, DiffTp_, BlockSize_, PgTp_, PageSize_> last,
371 stxxl::random_number<> rand;
377 __STXXL_END_NAMESPACE
379 #endif // !STXXL_RANDOM_SHUFFLE_HEADER
Buffered input stream.
Definition: buf_istream.h:36
A model of stream that retrieves the data from an input iterator For convenience use streamify functi...
Definition: stream.h:70
iterator2stream< InputIterator_ > streamify(InputIterator_ begin, InputIterator_ end)
Input iterator range to stream converter.
Definition: stream.h:115
void random_shuffle(ExtIterator_ first, ExtIterator_ last, RandomNumberGenerator_ &rand, unsigned_type M, AllocStrategy_ AS=STXXL_DEFAULT_ALLOC_STRATEGY())
External equivalent of std::random_shuffle.
Definition: random_shuffle.h:49
Buffered output stream.
Definition: buf_ostream.h:30