Stxxl  1.3.2
intksort.h
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_INTKSORT_HEADER
14 #define STXXL_INTKSORT_HEADER
15 
16 #include <algorithm>
17 #include <cassert>
18 #include <stxxl/bits/common/types.h>
19 #include <stxxl/bits/unused.h>
20 #include <stxxl/bits/parallel.h>
21 
22 
23 __STXXL_BEGIN_NAMESPACE
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 void
50 exclusive_prefix_sum(int_type * bucket, int_type K)
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:
308  sort(c, cEnd);
309  }
310  c = cEnd;
311  }
312 }
313 
314 // do a single level MDS radix sort
315 // using bucket[0..K-1] as a counter array
316 // and using (key(x) - offset) >> shift to index buckets.
317 // and using (key(x) - offset) >> shift to index buckets.
318 // the input comes from a..aEnd-1
319 // the output goes to b
320 template <typename type_key>
321 void
322 l1sort(type_key * a,
323  type_key * aEnd,
324  type_key * b, int_type * bucket, int_type K, typename type_key::key_type offset, int shift)
325 {
326  count(a, aEnd, bucket, K, offset, shift);
327  exclusive_prefix_sum(bucket, K);
328  classify(a, aEnd, b, bucket, offset, shift);
329  cleanup(b, bucket, K);
330 }
331 
332 template <typename type, typename type_key, typename key_extractor>
333 void classify_block(type * begin, type * end, type_key * & out,
334  int_type * bucket, typename key_extractor::key_type offset, unsigned shift, key_extractor keyobj)
335 {
336  assert(shift < (sizeof(typename key_extractor::key_type) * 8 + 1));
337  for (type * p = begin; p < end; p++, out++) // count & create references
338  {
339  out->ptr = p;
340  typename key_extractor::key_type key = keyobj(*p);
341  int_type ibucket = (key - offset) >> shift;
342  out->key = key;
343  bucket[ibucket]++;
344  }
345 }
346 template <typename type, typename type_key, typename key_extractor>
347 void classify_block(type * begin, type * end, type_key * & out, int_type * bucket, typename type::key_type offset, unsigned shift,
348  const int_type K, key_extractor keyobj)
349 {
350  assert(shift < (sizeof(typename type::key_type) * 8 + 1));
351  for (type * p = begin; p < end; p++, out++) // count & create references
352  {
353  out->ptr = p;
354  typename type::key_type key = keyobj(*p);
355  int_type ibucket = (key - offset) >> shift;
356  /*
357  if (!(ibucket < K && ibucket >= 0))
358  {
359  STXXL_ERRMSG("ibucket: " << ibucket << " K:" << K);
360  abort();
361  }
362  */
363  out->key = key;
364  bucket[ibucket]++;
365  }
366  STXXL_UNUSED(K);
367 }
368 
369 __STXXL_END_NAMESPACE
370 
371 #endif // !STXXL_INTKSORT_HEADER
void sort(ExtIterator_ first, ExtIterator_ last, StrictWeakOrdering_ cmp, unsigned_type M)
Sort records comparison-based.
Definition: sort.h:700