STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
intksort.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/algo/intksort.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002 Peter Sanders <[email protected]>
7  *
8  * Distributed under the Boost Software License, Version 1.0.
9  * (See accompanying file LICENSE_1_0.txt or copy at
10  * http://www.boost.org/LICENSE_1_0.txt)
11  **************************************************************************/
12 
13 #ifndef STXXL_ALGO_INTKSORT_HEADER
14 #define STXXL_ALGO_INTKSORT_HEADER
15 
16 #include <algorithm>
17 #include <cassert>
19 #include <stxxl/bits/unused.h>
20 #include <stxxl/bits/parallel.h>
21 
22 
24 
25 template <typename type_key>
26 static void
27 count(type_key* a, type_key* aEnd, int_type* bucket, int_type K, typename type_key::key_type offset,
28  unsigned shift)
29 {
30  // reset buckets
31  std::fill(bucket, bucket + K, 0);
32 
33  // count occupancies
34  for (type_key* p = a; p < aEnd; p++)
35  {
36  int_type i = (p->key - offset) >> shift;
37  /*
38  if (!(i < K && i >= 0))
39  {
40  STXXL_ERRMSG("i: " << i);
41  abort();
42  }
43  */
44  bucket[i]++;
45  }
46 }
47 
48 
49 static inline void
51 {
52  int_type sum = 0;
53  for (int_type i = 0; i < K; i++)
54  {
55  int_type current = bucket[i];
56  bucket[i] = sum;
57  sum += current;
58  }
59 }
60 
61 
62 // distribute input a to output b using bucket for the starting indices
63 template <typename type_key>
64 static void
65 classify(type_key* a, type_key* aEnd, type_key* b, int_type* bucket, typename type_key::key_type offset, unsigned shift)
66 {
67  for (type_key* p = a; p < aEnd; p++)
68  {
69  int_type i = (p->key - offset) >> shift;
70  int_type bi = bucket[i];
71  b[bi] = *p;
72  bucket[i] = bi + 1;
73  }
74 }
75 
76 
77 template <class T>
78 inline void
79 sort2(T& a, T& b)
80 {
81  if (b < a)
82  std::swap(a, b);
83 }
84 
85 template <class T>
86 inline void
87 sort3(T& a, T& b, T& c)
88 {
89  T temp;
90  if (b < a)
91  {
92  if (c < a)
93  { // b , c < a
94  if (b < c)
95  { // b < c < a
96  temp = a;
97  a = b;
98  b = c;
99  c = temp;
100  }
101  else
102  { // c <=b < a
103  std::swap(c, a);
104  }
105  }
106  else
107  { // b < a <=c
108  std::swap(a, b);
109  }
110  }
111  else
112  { // a <=b
113  if (c < a)
114  { // c < a <=b
115  temp = a;
116  a = c;
117  c = b;
118  b = temp;
119  }
120  else
121  { // a <=b , c
122  if (c < b)
123  { // a <=c < b
124  std::swap(b, c);
125  }
126  }
127  }
128  // Assert1 (!(b < a) && !(c < b));
129 }
130 
131 
132 template <class T>
133 inline void
134 sort4(T& a, T& b, T& c, T& d)
135 {
136  sort2(a, b);
137  sort2(c, d); // a < b ; c < d
138  if (c < a)
139  { // c minimal, a < b
140  if (d < a)
141  { // c < d < a < b
142  std::swap(a, c);
143  std::swap(b, d);
144  }
145  else
146  { // c < a < {db}
147  if (d < b)
148  { // c < a < d < b
149  T temp = a;
150  a = c;
151  c = d;
152  d = b;
153  b = temp;
154  }
155  else
156  { // c < a < b < d
157  T temp = a;
158  a = c;
159  c = b;
160  b = temp;
161  }
162  }
163  }
164  else
165  { // a minimal ; c < d
166  if (c < b)
167  { // c < (bd)
168  if (d < b)
169  { // c < d < b
170  T temp = b;
171  b = c;
172  c = d;
173  d = temp;
174  }
175  else
176  { // a < c < b < d
177  std::swap(b, c);
178  }
179  } // else sorted
180  }
181  //Assert1 (!(b < a) && !(c < b) & !(d < c));
182 }
183 
184 
185 template <class T>
186 inline void
187 sort5(T& a, T& b, T& c, T& d, T& e)
188 {
189  sort2(a, b);
190  sort2(d, e);
191  if (d < a)
192  {
193  std::swap(a, d);
194  std::swap(b, e);
195  } // a < d < e, a < b
196  if (d < c)
197  {
198  std::swap(c, d); // a minimal, c < {de}
199  sort2(d, e);
200  }
201  else
202  { // a<b, a<d<e, c<d<e
203  sort2(a, c);
204  } // a min, c < d < e
205  // insert b int cde by binary search
206  if (d < b)
207  { // c < d < {be}
208  if (e < b)
209  { // c < d < e < b
210  T temp = b;
211  b = c;
212  c = d;
213  d = e;
214  e = temp;
215  }
216  else
217  { // c < d < b < e
218  T temp = b;
219  b = c;
220  c = d;
221  d = temp;
222  }
223  }
224  else
225  { // {cb} <=d < e
226  sort2(b, c);
227  }
228  //Assert1 (!(b < a) && !(c < b) & !(d < c) & !(e < d));
229 }
230 
231 
232 template <class T>
233 inline void
234 insertion_sort(T* a, T* aEnd)
235 {
236  T* pp;
237  for (T* p = a + 1; p < aEnd; p++)
238  {
239  // Invariant a..p-1 is sorted;
240  T t = *p;
241  if (t < *a)
242  { // new minimum
243  // move stuff to the right
244  for (pp = p; pp != a; pp--)
245  {
246  *pp = *(pp - 1);
247  }
248  *pp = t;
249  }
250  else
251  {
252  // now we can use *a as a sentinel
253  for (pp = p; t < *(pp - 1); pp--)
254  {
255  *pp = *(pp - 1);
256  }
257  *pp = t;
258  }
259  }
260 }
261 
262 // sort each bucket
263 // bucket[i] is an index one off to the right from
264 // the end of the i-th bucket
265 template <class T>
266 static void
267 cleanup(T* b, int_type* bucket, int_type K)
268 {
269  T* c = b;
270  for (int_type i = 0; i < K; i++)
271  {
272  T* cEnd = b + bucket[i];
273  switch (cEnd - c)
274  {
275  case 0:
276  break;
277  case 1:
278  break;
279  case 2:
280  sort2(c[0], c[1]);
281  break;
282  case 3:
283  sort3(c[0], c[1], c[2]);
284  break;
285  case 4:
286  sort4(c[0], c[1], c[2], c[3]);
287  break;
288  case 5:
289 #if 0
290  sort5(c[0], c[1], c[2], c[3], c[4]);
291  break;
292 #endif
293  case 6:
294  case 7:
295  case 8:
296  case 9:
297  case 10:
298  case 11:
299  case 12:
300  case 13:
301  case 14:
302  case 15:
303  case 16:
304  insertion_sort(c, cEnd);
305  break;
306  default:
309  sort(c, cEnd);
310  }
311  c = cEnd;
312  }
313 }
314 
315 // do a single level MDS radix sort
316 // using bucket[0..K-1] as a counter array
317 // and using (key(x) - offset) >> shift to index buckets.
318 // and using (key(x) - offset) >> shift to index buckets.
319 // the input comes from a..aEnd-1
320 // the output goes to b
321 template <typename type_key>
322 void
323 l1sort(type_key* a,
324  type_key* aEnd,
325  type_key* b, int_type* bucket, int_type K, typename type_key::key_type offset, int shift)
326 {
327  count(a, aEnd, bucket, K, offset, shift);
328  exclusive_prefix_sum(bucket, K);
329  classify(a, aEnd, b, bucket, offset, shift);
330  cleanup(b, bucket, K);
331 }
332 
333 template <typename type, typename type_key, typename key_extractor>
334 void classify_block(type* begin, type* end, type_key*& out,
335  int_type* bucket, typename key_extractor::key_type offset, unsigned shift, key_extractor keyobj)
336 {
337  assert(shift < (sizeof(typename key_extractor::key_type) * 8 + 1));
338  for (type* p = begin; p < end; p++, out++) // count & create references
339  {
340  out->ptr = p;
341  typename key_extractor::key_type key = keyobj(*p);
342  int_type ibucket = (key - offset) >> shift;
343  out->key = key;
344  bucket[ibucket]++;
345  }
346 }
347 template <typename type, typename type_key, typename key_extractor>
348 void classify_block(type* begin, type* end, type_key*& out, int_type* bucket, typename type::key_type offset, unsigned shift,
349  const int_type K, key_extractor keyobj)
350 {
351  assert(shift < (sizeof(typename type::key_type) * 8 + 1));
352  for (type* p = begin; p < end; p++, out++) // count & create references
353  {
354  out->ptr = p;
355  typename type::key_type key = keyobj(*p);
356  int_type ibucket = (key - offset) >> shift;
357  /*
358  if (!(ibucket < K && ibucket >= 0))
359  {
360  STXXL_ERRMSG("ibucket: " << ibucket << " K:" << K);
361  abort();
362  }
363  */
364  out->key = key;
365  bucket[ibucket]++;
366  }
367  STXXL_UNUSED(K);
368 }
369 
371 
372 #endif // !STXXL_ALGO_INTKSORT_HEADER
void sort(ExtIterator first, ExtIterator last, StrictWeakOrdering cmp, unsigned_type M)
Sort records comparison-based, see stxxl::sort -- Sorting Comparison-Based.
Definition: sort.h:673
void sort3(T &a, T &b, T &c)
Definition: intksort.h:87
void insertion_sort(T *a, T *aEnd)
Definition: intksort.h:234
void check_sort_settings()
Definition: parallel.h:98
static void cleanup(T *b, int_type *bucket, int_type K)
Definition: intksort.h:267
void sort2(T &a, T &b)
Definition: intksort.h:79
choose_int_types< my_pointer_size >::int_type int_type
Definition: types.h:66
static void count(type_key *a, type_key *aEnd, int_type *bucket, int_type K, typename type_key::key_type offset, unsigned shift)
Definition: intksort.h:27
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
void STXXL_UNUSED(const U &)
Definition: unused.h:23
static void classify(type_key *a, type_key *aEnd, type_key *b, int_type *bucket, typename type_key::key_type offset, unsigned shift)
Definition: intksort.h:65
void sort4(T &a, T &b, T &c, T &d)
Definition: intksort.h:134
void l1sort(type_key *a, type_key *aEnd, type_key *b, int_type *bucket, int_type K, typename type_key::key_type offset, int shift)
Definition: intksort.h:323
static void exclusive_prefix_sum(int_type *bucket, int_type K)
Definition: intksort.h:50
void classify_block(type *begin, type *end, type_key *&out, int_type *bucket, typename key_extractor::key_type offset, unsigned shift, key_extractor keyobj)
Definition: intksort.h:334
void sort5(T &a, T &b, T &c, T &d, T &e)
Definition: intksort.h:187
#define STXXL_END_NAMESPACE
Definition: namespace.h:17