Stxxl  1.4.0
include/stxxl/bits/algo/intksort.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  include/stxxl/bits/algo/intksort.h
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2002 Peter Sanders <sanders@mpi-sb.mpg.de>
00007  *
00008  *  Distributed under the Boost Software License, Version 1.0.
00009  *  (See accompanying file LICENSE_1_0.txt or copy at
00010  *  http://www.boost.org/LICENSE_1_0.txt)
00011  **************************************************************************/
00012 
00013 #ifndef STXXL_INTKSORT_HEADER
00014 #define STXXL_INTKSORT_HEADER
00015 
00016 #include <algorithm>
00017 #include <cassert>
00018 #include <stxxl/bits/common/types.h>
00019 #include <stxxl/bits/unused.h>
00020 #include <stxxl/bits/parallel.h>
00021 
00022 
00023 __STXXL_BEGIN_NAMESPACE
00024 
00025 template <typename type_key>
00026 static void
00027 count(type_key * a, type_key * aEnd, int_type * bucket, int_type K, typename type_key::key_type offset,
00028       unsigned shift)
00029 {
00030     // reset buckets
00031     std::fill(bucket, bucket + K, 0);
00032 
00033     // count occupancies
00034     for (type_key * p = a; p < aEnd; p++)
00035     {
00036         int_type i = (p->key - offset) >> shift;
00037         /*
00038         if (!(i < K && i >= 0))
00039         {
00040             STXXL_ERRMSG("i: " << i);
00041             abort();
00042         }
00043         */
00044         bucket[i]++;
00045     }
00046 }
00047 
00048 
00049 static void
00050 exclusive_prefix_sum(int_type * bucket, int_type K)
00051 {
00052     int_type sum = 0;
00053     for (int_type i = 0; i < K; i++)
00054     {
00055         int_type current = bucket[i];
00056         bucket[i] = sum;
00057         sum += current;
00058     }
00059 }
00060 
00061 
00062 // distribute input a to output b using bucket for the starting indices
00063 template <typename type_key>
00064 static void
00065 classify(type_key * a, type_key * aEnd, type_key * b, int_type * bucket, typename type_key::key_type offset, unsigned shift)
00066 {
00067     for (type_key * p = a; p < aEnd; p++)
00068     {
00069         int_type i = (p->key - offset) >> shift;
00070         int_type bi = bucket[i];
00071         b[bi] = *p;
00072         bucket[i] = bi + 1;
00073     }
00074 }
00075 
00076 
00077 template <class T>
00078 inline void
00079 sort2(T & a, T & b)
00080 {
00081     if (b < a)
00082         std::swap(a, b);
00083 }
00084 
00085 template <class T>
00086 inline void
00087 sort3(T & a, T & b, T & c)
00088 {
00089     T temp;
00090     if (b < a)
00091     {
00092         if (c < a)
00093         {                       // b , c < a
00094             if (b < c)
00095             {                   // b < c < a
00096                 temp = a;
00097                 a = b;
00098                 b = c;
00099                 c = temp;
00100             }
00101             else
00102             {                   // c <=b < a
00103                 std::swap(c, a);
00104             }
00105         }
00106         else
00107         {                       // b < a <=c
00108             std::swap(a, b);
00109         }
00110     }
00111     else
00112     {                           // a <=b
00113         if (c < a)
00114         {                       // c < a <=b
00115             temp = a;
00116             a = c;
00117             c = b;
00118             b = temp;
00119         }
00120         else
00121         {                       // a <=b , c
00122             if (c < b)
00123             {                   // a <=c < b
00124                 std::swap(b, c);
00125             }
00126         }
00127     }
00128     // Assert1 (!(b < a) && !(c < b));
00129 }
00130 
00131 
00132 template <class T>
00133 inline void
00134 sort4(T & a, T & b, T & c, T & d)
00135 {
00136     sort2(a, b);
00137     sort2(c, d);                // a < b ; c < d
00138     if (c < a)
00139     {                           // c minimal, a < b
00140         if (d < a)
00141         {                       // c < d < a < b
00142             std::swap(a, c);
00143             std::swap(b, d);
00144         }
00145         else
00146         {                       // c < a < {db}
00147             if (d < b)
00148             {                   // c < a < d < b
00149                 T temp = a;
00150                 a = c;
00151                 c = d;
00152                 d = b;
00153                 b = temp;
00154             }
00155             else
00156             {                   // c < a < b < d
00157                 T temp = a;
00158                 a = c;
00159                 c = b;
00160                 b = temp;
00161             }
00162         }
00163     }
00164     else
00165     {                           // a minimal ; c < d
00166         if (c < b)
00167         {                       // c < (bd)
00168             if (d < b)
00169             {                   // c < d < b
00170                 T temp = b;
00171                 b = c;
00172                 c = d;
00173                 d = temp;
00174             }
00175             else
00176             {                   // a < c < b < d
00177                 std::swap(b, c);
00178             }
00179         }                       // else sorted
00180     }
00181     //Assert1 (!(b < a) && !(c < b) & !(d < c));
00182 }
00183 
00184 
00185 template <class T>
00186 inline void
00187 sort5(T & a, T & b, T & c, T & d, T & e)
00188 {
00189     sort2(a, b);
00190     sort2(d, e);
00191     if (d < a)
00192     {
00193         std::swap(a, d);
00194         std::swap(b, e);
00195     }                           // a < d < e, a < b
00196     if (d < c)
00197     {
00198         std::swap(c, d);        // a minimal, c < {de}
00199         sort2(d, e);
00200     }
00201     else
00202     {                           // a<b, a<d<e, c<d<e
00203         sort2(a, c);
00204     }                           // a min, c < d < e
00205     // insert b int cde by binary search
00206     if (d < b)
00207     {                           // c < d < {be}
00208         if (e < b)
00209         {                       // c < d < e < b
00210             T temp = b;
00211             b = c;
00212             c = d;
00213             d = e;
00214             e = temp;
00215         }
00216         else
00217         {                       // c < d < b < e
00218             T temp = b;
00219             b = c;
00220             c = d;
00221             d = temp;
00222         }
00223     }
00224     else
00225     {                           // {cb} <=d < e
00226         sort2(b, c);
00227     }
00228     //Assert1 (!(b < a) && !(c < b) & !(d < c) & !(e < d));
00229 }
00230 
00231 
00232 template <class T>
00233 inline void
00234 insertion_sort(T * a, T * aEnd)
00235 {
00236     T * pp;
00237     for (T * p = a + 1; p < aEnd; p++)
00238     {
00239         // Invariant a..p-1 is sorted;
00240         T t = *p;
00241         if (t < *a)
00242         {   // new minimum
00243             // move stuff to the right
00244             for (pp = p; pp != a; pp--)
00245             {
00246                 *pp = *(pp - 1);
00247             }
00248             *pp = t;
00249         }
00250         else
00251         {
00252             // now we can use *a as a sentinel
00253             for (pp = p; t < *(pp - 1); pp--)
00254             {
00255                 *pp = *(pp - 1);
00256             }
00257             *pp = t;
00258         }
00259     }
00260 }
00261 
00262 // sort each bucket
00263 // bucket[i] is an index one off to the right from
00264 // the end of the i-th bucket
00265 template <class T>
00266 static void
00267 cleanup(T * b, int_type * bucket, int_type K)
00268 {
00269     T * c = b;
00270     for (int_type i = 0; i < K; i++)
00271     {
00272         T * cEnd = b + bucket[i];
00273         switch (cEnd - c)
00274         {
00275         case 0:
00276             break;
00277         case 1:
00278             break;
00279         case 2:
00280             sort2(c[0], c[1]);
00281             break;
00282         case 3:
00283             sort3(c[0], c[1], c[2]);
00284             break;
00285         case 4:
00286             sort4(c[0], c[1], c[2], c[3]);
00287             break;
00288         case 5:
00289 #if 0
00290             sort5(c[0], c[1], c[2], c[3], c[4]);
00291             break;
00292 #endif
00293         case 6:
00294         case 7:
00295         case 8:
00296         case 9:
00297         case 10:
00298         case 11:
00299         case 12:
00300         case 13:
00301         case 14:
00302         case 15:
00303         case 16:
00304             insertion_sort(c, cEnd);
00305             break;
00306         default:
00307             check_sort_settings();
00308             potentially_parallel::
00309             sort(c, cEnd);
00310         }
00311         c = cEnd;
00312     }
00313 }
00314 
00315 // do a single level MDS radix sort
00316 // using bucket[0..K-1] as a counter array
00317 // and using (key(x) - offset) >> shift to index buckets.
00318 // and using (key(x) - offset) >> shift to index buckets.
00319 // the input comes from a..aEnd-1
00320 // the output goes to b
00321 template <typename type_key>
00322 void
00323 l1sort(type_key * a,
00324        type_key * aEnd,
00325        type_key * b, int_type * bucket, int_type K, typename type_key::key_type offset, int shift)
00326 {
00327     count(a, aEnd, bucket, K, offset, shift);
00328     exclusive_prefix_sum(bucket, K);
00329     classify(a, aEnd, b, bucket, offset, shift);
00330     cleanup(b, bucket, K);
00331 }
00332 
00333 template <typename type, typename type_key, typename key_extractor>
00334 void classify_block(type * begin, type * end, type_key * & out,
00335                     int_type * bucket, typename key_extractor::key_type offset, unsigned shift, key_extractor keyobj)
00336 {
00337     assert(shift < (sizeof(typename key_extractor::key_type) * 8 + 1));
00338     for (type * p = begin; p < end; p++, out++) // count & create references
00339     {
00340         out->ptr = p;
00341         typename key_extractor::key_type key = keyobj(*p);
00342         int_type ibucket = (key - offset) >> shift;
00343         out->key = key;
00344         bucket[ibucket]++;
00345     }
00346 }
00347 template <typename type, typename type_key, typename key_extractor>
00348 void classify_block(type * begin, type * end, type_key * & out, int_type * bucket, typename type::key_type offset, unsigned shift,
00349                     const int_type K, key_extractor keyobj)
00350 {
00351     assert(shift < (sizeof(typename type::key_type) * 8 + 1));
00352     for (type * p = begin; p < end; p++, out++) // count & create references
00353     {
00354         out->ptr = p;
00355         typename type::key_type key = keyobj(*p);
00356         int_type ibucket = (key - offset) >> shift;
00357         /*
00358         if (!(ibucket < K && ibucket >= 0))
00359         {
00360             STXXL_ERRMSG("ibucket: " << ibucket << " K:" << K);
00361             abort();
00362         }
00363         */
00364         out->key = key;
00365         bucket[ibucket]++;
00366     }
00367     STXXL_UNUSED(K);
00368 }
00369 
00370 __STXXL_END_NAMESPACE
00371 
00372 #endif // !STXXL_INTKSORT_HEADER
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines