source: soft/giet_vm/mover/include/libelfpp/dpp/radix_sort @ 160

Last change on this file since 160 was 160, checked in by karaoui, 12 years ago

giet-vm new version

File size: 7.2 KB
Line 
1/* -*- c++ -*-
2
3   Template Radix sort implementation
4
5   This file is part of the dpp library of C++ template classes
6
7   doc: http://diaxen.ssji.net/dpp/index.html
8   repo: https://www.ssji.net/svn/projets/trunk/libdpp
9
10   This program is free software: you can redistribute it and/or
11   modify it under the terms of the GNU Lesser General Public License
12   as published by the Free Software Foundation, either version 3 of
13   the License, or (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful, but
16   WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   Lesser General Public License for more details.
19
20   You should have received a copy of the GNU Lesser General Public
21   License along with this program.  If not, see
22   <http://www.gnu.org/licenses/>.
23
24   (c) 2012 Alexandre Becoulet <alexandre.becoulet@free.fr>
25
26*/
27
28#ifndef DPP_RADIX_SORT_HH_
29#define DPP_RADIX_SORT_HH_
30
31#include <algorithm>
32#include <cassert>
33
34#include <stdint.h>
35
36/** @file @module{Radix sort} */
37
38namespace dpp {
39
40  /** @This class may be specialized to describe how radix are
41      extracted from values for a given type. Specializations are
42      provided for integer and floating-point types. */
43  template <typename X, size_t bits>
44  struct radix_sort_type
45  {
46    static unsigned int extract(const X x, size_t pos)
47    {
48      X::_requires_8bits_radix_width_for_custom_types();
49    }
50  };
51
52  /** @This provides a generic byte-slicing radix extraction function. */
53  template <typename X>
54  struct radix_sort_type<const X &, 8>
55  {
56    static unsigned int extract(const X x, size_t pos)
57    {
58      const uint8_t *d = (const uint8_t *)&x;
59      return d[pos];
60    }
61  };
62
63  /** @internal */
64#define _DPP_RADIX_SORT_INT(type)                                       \
65  /** @This class provides a radix extaction function for @tt{type} integers */ \
66  template <size_t bits>                                                \
67  struct radix_sort_type<type, bits>                                    \
68  {                                                                     \
69    static const size_t _bsize = 1 << bits;                             \
70    static const size_t _passes = sizeof(type) * 8 / bits + (bits % 8 != 0); \
71                                                                        \
72    static unsigned int extract(type x, size_t pos)                     \
73    {                                                                   \
74      return (x >> (bits * pos)) & ((1 << bits) - 1);                   \
75    }                                                                   \
76  }
77
78  _DPP_RADIX_SORT_INT(signed char);
79  _DPP_RADIX_SORT_INT(unsigned char);
80  _DPP_RADIX_SORT_INT(signed short);
81  _DPP_RADIX_SORT_INT(unsigned short);
82  _DPP_RADIX_SORT_INT(signed int);
83  _DPP_RADIX_SORT_INT(unsigned int);
84  _DPP_RADIX_SORT_INT(signed long);
85  _DPP_RADIX_SORT_INT(unsigned long);
86  _DPP_RADIX_SORT_INT(signed long long);
87  _DPP_RADIX_SORT_INT(unsigned long long);
88
89  /** @internal */
90#define _DPP_RADIX_SORT_FLOAT(type)                                     \
91  /** @This class provides a radix extaction function for @tt{type} floating-point values */    \
92  template <size_t bits>                                                \
93  struct radix_sort_type<type, bits>                                    \
94  {                                                                     \
95    static const size_t _bsize = 1 << bits;                             \
96    static const size_t _passes = sizeof(type) * 8 / bits + (bits % 8 != 0); \
97                                                                        \
98    static unsigned int extract(type x, size_t pos)                     \
99    {                                                                   \
100      switch (sizeof(type))                                             \
101        {                                                               \
102          case 4: {                                                     \
103            int32_t v = *(int32_t*)&x;                          \
104            return ((((v >> 31) | (1 << 31)) ^ v) >> (bits * pos)) & ((1 << bits) - 1); \
105          }                                                             \
106          case 8: {                                                     \
107            int64_t v = *(int64_t*)&x;                          \
108            return ((((v >> 63) | (1ULL << 63)) ^ v) >> (bits * pos)) & ((1 << bits) - 1); \
109          }                                                             \
110        default:                                                        \
111          std::abort();                                                 \
112        }                                                               \
113    }                                                                   \
114  }
115
116  _DPP_RADIX_SORT_FLOAT(float);
117  _DPP_RADIX_SORT_FLOAT(double);
118
119  /** @internal */
120  template <typename X, size_t bits>
121  struct _radix_sort
122  {
123    static const size_t _bsize = 1 << bits;
124    static const size_t _passes = sizeof(X) * 8 / bits + (bits % 8 != 0); \
125
126    /** @This performs actual sorting */
127    static void sort(X *in, X *next_in, X *out, size_t len)
128    {
129      size_t hist[_passes][_bsize];
130
131      // zero histograms
132      for (size_t j = 0; j < _passes; j++)
133        for (size_t i = 0; i < _bsize; i++)
134          hist[j][i] = 0;
135
136      // compute histograms
137      for (size_t i = 0; i < len; i++)
138        for (size_t j = 0; j < _passes; j++)
139          hist[j][radix_sort_type<X, bits>::extract(in[i], j)]++;
140
141      // multiple passes stable radix-sort
142      for (size_t j = 0; j < _passes; j++)
143        {
144          uintptr_t offset[_bsize], o;
145
146          // compute offsets
147          o = offset[0] = 0;
148          for (size_t i = 1; i < _bsize; i++)
149            o = offset[i] = o + hist[j][i - 1];
150
151          // reorder array
152          for (size_t i = 0; i < len; i++)
153            {
154              size_t x = radix_sort_type<X, bits>::extract(in[i], j);
155              out[offset[x]++] = in[i];
156            }
157
158          // swap input/output arrays for next pass
159          in = next_in;
160          std::swap(in, out);
161          next_in = in;
162        }
163    }
164
165    /** @This performs sorting and final array copy when number of passes are odd
166        and sorting result must be stored back in original array. */
167    static void sort_in(X *in, size_t len)
168    {
169      X tmp[len];
170
171      sort(in, in, tmp, len);
172
173      if (_passes % 2)
174        for (size_t i = 0; i < len; i++)
175          in[i] = tmp[i];
176    }
177   
178    /** @This performs input array copy to temporary storage when
179        number of passes are odd and sorting. */
180    static void sort_out(const X *in, X *out, size_t len)
181    {
182      if (_passes % 2)
183        {
184          X tmp[len];
185
186          for (size_t i = 0; i < len; i++)
187            tmp[i] = in[i];
188          sort(tmp, tmp, out, len);
189        }
190      else if (_passes > 1)
191        {
192          X tmp[len];
193          sort((X*)in, out, tmp, len);
194        }
195      else
196        {
197          sort((X*)in, 0, out, len);
198        }
199    }
200  };
201
202  /** @This function performs radix-sort on container iterators. Radix
203      width is 8 bits. */
204  template <typename iterator>
205  void radix_sort(const iterator &begin, const iterator &end)
206  {
207    typedef typename iterator::value_type type;
208    size_t len = end - begin;
209
210    _radix_sort<type, 8>::sort_in(&*begin, len);
211  }
212
213  /** @This function performs radix-sort on container
214      iterators. Specified radix bit width is used. */
215  template <typename iterator, size_t bits>
216  void radix_sort(const iterator &begin, const iterator &end)
217  {
218    typedef typename iterator::value_type type;
219    size_t len = end - begin;
220
221    _radix_sort<type, bits>::sort_in(&*begin, len);
222  }
223
224  /** @This function performs radix-sort on array. Radix
225      width is 8 bits. */
226  template <typename X>
227  void radix_sort(X *begin, X *end)
228  {
229    typedef X type;
230    size_t len = end - begin;
231
232    _radix_sort<type, 8>::sort_in(begin, len);
233  }
234
235  /** @This function performs radix-sort on array.
236      Specified radix bit width is used. */
237  template <typename X, size_t bits>
238  void radix_sort(X *begin, X *end)
239  {
240    typedef X type;
241    size_t len = end - begin;
242
243    _radix_sort<type, bits>::sort_in(begin, len);
244  }
245
246  /** @This function performs radix-sort on array. Radix
247      width is 8 bits. */
248  template <typename X>
249  void radix_sort(const X *begin, const X *end, X *out)
250  {
251    typedef X type;
252    size_t len = end - begin;
253
254    _radix_sort<type, 8>::sort_out(begin, out, len);
255  }
256
257  /** @This function performs radix-sort on array.
258      Specified radix bit width is used. */
259  template <typename X, size_t bits>
260  void radix_sort(const X *begin, const X *end, X *out)
261  {
262    typedef X type;
263    size_t len = end - begin;
264
265    _radix_sort<type, bits>::sort_out(begin, out, len);
266  }
267
268}
269
270#endif
271
Note: See TracBrowser for help on using the repository browser.