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